2003-03-28 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / class.cs
1 //
2 // class.cs: Class and Struct handlers
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 //          Martin Baulig (martin@gnome.org)
6 //
7 // Licensed under the terms of the GNU GPL
8 //
9 // (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
10 //
11 //
12 //  2002-10-11  Miguel de Icaza  <miguel@ximian.com>
13 //
14 //      * class.cs: Following the comment from 2002-09-26 to AddMethod, I
15 //      have fixed a remaining problem: not every AddXXXX was adding a
16 //      fully qualified name.  
17 //
18 //      Now everyone registers a fully qualified name in the DeclSpace as
19 //      being defined instead of the partial name.  
20 //
21 //      Downsides: we are slower than we need to be due to the excess
22 //      copies and the names being registered this way.  
23 //
24 //      The reason for this is that we currently depend (on the corlib
25 //      bootstrap for instance) that types are fully qualified, because
26 //      we dump all the types in the namespace, and we should really have
27 //      types inserted into the proper namespace, so we can only store the
28 //      basenames in the defined_names array.
29 //
30 //
31 #define CACHE
32 using System;
33 using System.Collections;
34 using System.Reflection;
35 using System.Reflection.Emit;
36 using System.Runtime.CompilerServices;
37
38 namespace Mono.CSharp {
39
40         /// <summary>
41         ///   This is the base class for structs and classes.  
42         /// </summary>
43         public class TypeContainer : DeclSpace, IMemberContainer {
44                 // Holds a list of classes and structures
45                 ArrayList types;
46
47                 // Holds the list of properties
48                 ArrayList properties;
49
50                 // Holds the list of enumerations
51                 ArrayList enums;
52
53                 // Holds the list of delegates
54                 ArrayList delegates;
55                 
56                 // Holds the list of constructors
57                 ArrayList instance_constructors;
58
59                 // Holds the list of fields
60                 ArrayList fields;
61
62                 // Holds a list of fields that have initializers
63                 ArrayList initialized_fields;
64
65                 // Holds a list of static fields that have initializers
66                 ArrayList initialized_static_fields;
67
68                 // Holds the list of constants
69                 ArrayList constants;
70
71                 // Holds the list of
72                 ArrayList interfaces;
73
74                 // Holds order in which interfaces must be closed
75                 ArrayList interface_order;
76                 
77                 // Holds the methods.
78                 ArrayList methods;
79
80                 // Holds the events
81                 ArrayList events;
82
83                 // Holds the indexers
84                 ArrayList indexers;
85
86                 // Holds the operators
87                 ArrayList operators;
88
89                 // The emit context for toplevel objects.
90                 EmitContext ec;
91                 
92                 //
93                 // Pointers to the default constructor and the default static constructor
94                 //
95                 Constructor default_constructor;
96                 Constructor default_static_constructor;
97
98                 //
99                 // Whether we have seen a static constructor for this class or not
100                 //
101                 bool have_static_constructor = false;
102
103                 //
104                 // Whether we have at least one non-static field
105                 //
106                 bool have_nonstatic_fields = false;
107                 
108                 //
109                 // This one is computed after we can distinguish interfaces
110                 // from classes from the arraylist `type_bases' 
111                 //
112                 string     base_class_name;
113
114                 ArrayList type_bases;
115
116                 // Attributes for this type
117                 protected Attributes attributes;
118
119                 // Information in the case we are an attribute type
120
121                 public AttributeTargets Targets = AttributeTargets.All;
122                 public bool AllowMultiple = false;
123                 public bool Inherited;
124
125                 // The interfaces we implement.
126                 Type [] ifaces;
127
128                 // The parent member container and our member cache
129                 IMemberContainer parent_container;
130                 MemberCache member_cache;
131                 
132                 //
133                 // The indexer name for this class
134                 //
135                 public string IndexerName;
136
137                 public TypeContainer (TypeContainer parent, string name, Location l)
138                         : base (parent, name, l)
139                 {
140                         string n;
141                         types = new ArrayList ();
142
143                         if (parent == null)
144                                 n = "";
145                         else
146                                 n = parent.Name;
147
148                         base_class_name = null;
149                         
150                         //Console.WriteLine ("New class " + name + " inside " + n);
151                 }
152
153                 public AdditionResult AddConstant (Const constant)
154                 {
155                         AdditionResult res;
156                         string basename = constant.Name;
157
158                         if ((res = IsValid (basename)) != AdditionResult.Success)
159                                 return res;
160                         
161                         if (constants == null)
162                                 constants = new ArrayList ();
163
164                         constants.Add (constant);
165                         DefineName (Name + "." + basename, constant);
166
167                         return AdditionResult.Success;
168                 }
169
170                 public AdditionResult AddEnum (Mono.CSharp.Enum e)
171                 {
172                         AdditionResult res;
173
174                         if ((res = IsValid (e.Basename)) != AdditionResult.Success)
175                                 return res;
176
177                         if (enums == null)
178                                 enums = new ArrayList ();
179
180                         enums.Add (e);
181                         DefineName (e.Name, e);
182
183                         return AdditionResult.Success;
184                 }
185                 
186                 public AdditionResult AddClass (Class c)
187                 {
188                         AdditionResult res;
189
190                         if ((res = IsValid (c.Basename)) != AdditionResult.Success)
191                                 return res;
192
193                         DefineName (c.Name, c);
194                         types.Add (c);
195
196                         return AdditionResult.Success;
197                 }
198
199                 public AdditionResult AddStruct (Struct s)
200                 {
201                         AdditionResult res;
202                         
203                         if ((res = IsValid (s.Basename)) != AdditionResult.Success)
204                                 return res;
205
206                         DefineName (s.Name, s);
207                         types.Add (s);
208
209                         return AdditionResult.Success;
210                 }
211
212                 public AdditionResult AddDelegate (Delegate d)
213                 {
214                         AdditionResult res;
215
216                         if ((res = IsValid (d.Basename)) != AdditionResult.Success)
217                                 return res;
218
219                         if (delegates == null)
220                                 delegates = new ArrayList ();
221                         
222                         DefineName (d.Name, d);
223                         delegates.Add (d);
224
225                         return AdditionResult.Success;
226                 }
227
228                 public AdditionResult AddMethod (Method method)
229                 {
230                         string basename = method.Name;
231                         string fullname = Name + "." + basename;
232
233                         Object value = defined_names [fullname];
234
235                         if (value != null && (!(value is Method)))
236                                 return AdditionResult.NameExists;
237
238                         if (basename == Basename)
239                                 return AdditionResult.EnclosingClash;
240
241                         if (methods == null)
242                                 methods = new ArrayList ();
243
244                         if (method.Name.IndexOf (".") != -1)
245                                 methods.Insert (0, method);
246                         else 
247                                 methods.Add (method);
248                         
249                         if (value == null)
250                                 DefineName (fullname, method);
251
252                         return AdditionResult.Success;
253                 }
254
255                 public AdditionResult AddConstructor (Constructor c)
256                 {
257                         if (c.Name != Basename) 
258                                 return AdditionResult.NotAConstructor;
259
260                         bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
261                         
262                         if (is_static){
263                                 have_static_constructor = true;
264                                 if (default_static_constructor != null){
265                                         Console.WriteLine ("I have a static constructor already");
266                                         Console.WriteLine ("   " + default_static_constructor);
267                                         return AdditionResult.MethodExists;
268                                 }
269
270                                 default_static_constructor = c;
271                         } else {
272                                 if (c.IsDefault ()){
273                                         if (default_constructor != null)
274                                                 return AdditionResult.MethodExists;
275                                         default_constructor = c;
276                                 }
277                                 
278                                 if (instance_constructors == null)
279                                         instance_constructors = new ArrayList ();
280                                 
281                                 instance_constructors.Add (c);
282                         }
283                         
284                         return AdditionResult.Success;
285                 }
286                 
287                 public AdditionResult AddInterface (Interface iface)
288                 {
289                         AdditionResult res;
290
291                         if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
292                                 return res;
293                         
294                         if (interfaces == null)
295                                 interfaces = new ArrayList ();
296                         interfaces.Add (iface);
297                         DefineName (iface.Name, iface);
298                         
299                         return AdditionResult.Success;
300                 }
301
302                 public AdditionResult AddField (Field field)
303                 {
304                         AdditionResult res;
305                         string basename = field.Name;
306
307                         if ((res = IsValid (basename)) != AdditionResult.Success)
308                                 return res;
309                         
310                         if (fields == null)
311                                 fields = new ArrayList ();
312                         
313                         fields.Add (field);
314                         
315                         if (field.HasInitializer){
316                                 if ((field.ModFlags & Modifiers.STATIC) != 0){
317                                         if (initialized_static_fields == null)
318                                                 initialized_static_fields = new ArrayList ();
319
320                                         initialized_static_fields.Add (field);
321
322                                         //
323                                         // We have not seen a static constructor,
324                                         // but we will provide static initialization of fields
325                                         //
326                                         have_static_constructor = true;
327                                 } else {
328                                         if (initialized_fields == null)
329                                                 initialized_fields = new ArrayList ();
330                                 
331                                         initialized_fields.Add (field);
332                                 }
333                         }
334
335                         if ((field.ModFlags & Modifiers.STATIC) == 0)
336                                 have_nonstatic_fields = true;
337
338                         DefineName (Name + "." + basename, field);
339                         return AdditionResult.Success;
340                 }
341
342                 public AdditionResult AddProperty (Property prop)
343                 {
344                         AdditionResult res;
345                         string basename = prop.Name;
346
347                         if ((res = IsValid (basename)) != AdditionResult.Success)
348                                 return res;
349
350                         if (properties == null)
351                                 properties = new ArrayList ();
352
353                         if (prop.Name.IndexOf (".") != -1)
354                                 properties.Insert (0, prop);
355                         else
356                                 properties.Add (prop);
357                         DefineName (Name + "." + basename, prop);
358
359                         return AdditionResult.Success;
360                 }
361
362                 public AdditionResult AddEvent (Event e)
363                 {
364                         AdditionResult res;
365                         string basename = e.Name;
366
367                         if ((res = IsValid (basename)) != AdditionResult.Success)
368                                 return res;
369
370                         if (events == null)
371                                 events = new ArrayList ();
372                         
373                         events.Add (e);
374                         DefineName (Name + "." + basename, e);
375
376                         return AdditionResult.Success;
377                 }
378
379                 public AdditionResult AddIndexer (Indexer i)
380                 {
381                         if (indexers == null)
382                                 indexers = new ArrayList ();
383
384                         if (i.InterfaceType != null)
385                                 indexers.Insert (0, i);
386                         else
387                                 indexers.Add (i);
388
389                         return AdditionResult.Success;
390                 }
391
392                 public AdditionResult AddOperator (Operator op)
393                 {
394                         if (operators == null)
395                                 operators = new ArrayList ();
396
397                         operators.Add (op);
398
399                         return AdditionResult.Success;
400                 }
401
402                 public void RegisterOrder (Interface iface)
403                 {
404                         if (interface_order == null)
405                                 interface_order = new ArrayList ();
406
407                         interface_order.Add (iface);
408                 }
409                 
410                 public ArrayList Types {
411                         get {
412                                 return types;
413                         }
414                 }
415
416                 public ArrayList Methods {
417                         get {
418                                 return methods;
419                         }
420                 }
421
422                 public ArrayList Constants {
423                         get {
424                                 return constants;
425                         }
426                 }
427
428                 public ArrayList Interfaces {
429                         get {
430                                 return interfaces;
431                         }
432                 }
433                 
434                 public string Base {
435                         get {
436                                 return base_class_name;
437                         }
438                 }
439                 
440                 public ArrayList Bases {
441                         get {
442                                 return type_bases;
443                         }
444
445                         set {
446                                 type_bases = value;
447                         }
448                 }
449
450                 public ArrayList Fields {
451                         get {
452                                 return fields;
453                         }
454
455                         set {
456                                 fields = value;
457                         }
458                 }
459
460                 public ArrayList InstanceConstructors {
461                         get {
462                                 return instance_constructors;
463                         }
464                 }
465
466                 public ArrayList Properties {
467                         get {
468                                 return properties;
469                         }
470                 }
471
472                 public ArrayList Events {
473                         get {
474                                 return events;
475                         }
476                 }
477                 
478                 public ArrayList Enums {
479                         get {
480                                 return enums;
481                         }
482                 }
483
484                 public ArrayList Indexers {
485                         get {
486                                 return indexers;
487                         }
488                 }
489
490                 public ArrayList Operators {
491                         get {
492                                 return operators;
493                         }
494                 }
495
496                 public ArrayList Delegates {
497                         get {
498                                 return delegates;
499                         }
500                 }
501                 
502                 public Attributes OptAttributes {
503                         get {
504                                 return attributes;
505                         }
506                 }
507                 
508                 public bool HaveStaticConstructor {
509                         get {
510                                 return have_static_constructor;
511                         }
512                 }
513                 
514                 public virtual TypeAttributes TypeAttr {
515                         get {
516                                 return Modifiers.TypeAttr (ModFlags, this);
517                         }
518                 }
519
520                 //
521                 // Emits the instance field initializers
522                 //
523                 public bool EmitFieldInitializers (EmitContext ec)
524                 {
525                         ArrayList fields;
526                         ILGenerator ig = ec.ig;
527                         Expression instance_expr;
528                         
529                         if (ec.IsStatic){
530                                 fields = initialized_static_fields;
531                                 instance_expr = null;
532                         } else {
533                                 fields = initialized_fields;
534                                 instance_expr = new This (Location.Null).Resolve (ec);
535                         }
536
537                         if (fields == null)
538                                 return true;
539
540                         foreach (Field f in fields){
541                                 Expression e = f.GetInitializerExpression (ec);
542                                 if (e == null)
543                                         return false;
544
545                                 Location l = f.Location;
546                                 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
547                                 fe.InstanceExpression = instance_expr;
548                                 Expression a = new Assign (fe, e, l);
549
550                                 a = a.Resolve (ec);
551                                 if (a == null)
552                                         return false;
553
554                                 if (a is ExpressionStatement)
555                                         ((ExpressionStatement) a).EmitStatement (ec);
556                                 else {
557                                         throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
558                                 }
559                         }
560
561                         return true;
562                 }
563                 
564                 //
565                 // Defines the default constructors
566                 //
567                 void DefineDefaultConstructor (bool is_static)
568                 {
569                         Constructor c;
570                         int mods = 0;
571
572                         c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters,
573                                              new ConstructorBaseInitializer (
574                                                      null, Parameters.EmptyReadOnlyParameters,
575                                                      Location.Null),
576                                              Location.Null);
577                         
578                         if (is_static)
579                                 mods = Modifiers.STATIC;
580
581                         c.ModFlags = mods;
582
583                         AddConstructor (c);
584                         
585                         c.Block = new Block (null);
586                         
587                 }
588
589                 public void ReportStructInitializedInstanceError ()
590                 {
591                         string n = TypeBuilder.FullName;
592                         
593                         foreach (Field f in initialized_fields){
594                                 Report.Error (
595                                         573, Location,
596                                         "`" + n + "." + f.Name + "': can not have " +
597                                         "instance field initializers in structs");
598                         }
599                 }
600
601                 /// <remarks>
602                 ///  The pending methods that need to be implemented (interfaces or abstract methods)
603                 /// </remarks>
604                 public PendingImplementation Pending;
605
606                 /// <summary>
607                 ///   This function computes the Base class and also the
608                 ///   list of interfaces that the class or struct @c implements.
609                 ///   
610                 ///   The return value is an array (might be null) of
611                 ///   interfaces implemented (as Types).
612                 ///   
613                 ///   The @parent argument is set to the parent object or null
614                 ///   if this is `System.Object'. 
615                 /// </summary>
616                 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
617                 {
618                         ArrayList bases = Bases;
619                         int count;
620                         int start, j, i;
621
622                         error = false;
623
624                         if (is_class)
625                                 parent = null;
626                         else
627                                 parent = TypeManager.value_type;
628
629                         if (bases == null){
630                                 if (is_class){
631                                         if (RootContext.StdLib)
632                                                 parent = TypeManager.object_type;
633                                         else if (Name != "System.Object")
634                                                 parent = TypeManager.object_type;
635                                 } else {
636                                         //
637                                         // If we are compiling our runtime,
638                                         // and we are defining ValueType, then our
639                                         // parent is `System.Object'.
640                                         //
641                                         if (!RootContext.StdLib && Name == "System.ValueType")
642                                                 parent = TypeManager.object_type;
643                                 }
644
645                                 return null;
646                         }
647
648                         //
649                         // Bases should be null if there are no bases at all
650                         //
651                         count = bases.Count;
652
653                         if (is_class){
654                                 Expression name = (Expression) bases [0];
655                                 name = ResolveTypeExpr (name, false, Location);
656
657                                 if (name == null){
658                                         error = true;
659                                         return null;
660                                 }
661
662                                 Type first = name.Type;
663
664                                 if (first.IsClass){
665                                         parent = first;
666                                         start = 1;
667                                 } else {
668                                         parent = TypeManager.object_type;
669                                         start = 0;
670                                 }
671
672                                 if (!AsAccessible (parent, ModFlags))
673                                         Report.Error (60, Location,
674                                                       "Inconsistent accessibility: base class `" +
675                                                       TypeManager.CSharpName (parent) + "' is less " +
676                                                       "accessible than class `" +
677                                                       Name + "'");
678
679                         } else {
680                                 start = 0;
681                         }
682
683                         Type [] ifaces = new Type [count-start];
684                         
685                         for (i = start, j = 0; i < count; i++, j++){
686                                 Expression name = (Expression) bases [i];
687                                 Expression resolved = ResolveTypeExpr (name, false, Location);
688                                 if (resolved == null)
689                                         return null;
690                                 
691                                 bases [i] = resolved;
692                                 Type t = resolved.Type;
693
694                                 if (t == null){
695                                         error = true;
696                                         return null;
697                                 }
698
699                                 if (is_class == false && !t.IsInterface){
700                                         Report.Error (527, "In Struct `" + Name + "', type `"+
701                                                       name +"' is not an interface");
702                                         error = true;
703                                         return null;
704                                 }
705                                 
706                                 if (t.IsSealed) {
707                                         string detail = "";
708                                         
709                                         if (t.IsValueType)
710                                                 detail = " (a class can not inherit from a struct/enum)";
711                                                         
712                                         Report.Error (509, "class `"+ Name +
713                                                       "': Cannot inherit from sealed class `"+
714                                                       bases [i]+"'"+detail);
715                                         error = true;
716                                         return null;
717                                 }
718
719                                 if (t.IsClass) {
720                                         if (parent != null){
721                                                 Report.Error (527, "In Class `" + Name + "', type `"+
722                                                               name+"' is not an interface");
723                                                 error = true;
724                                                 return null;
725                                         }
726                                 }
727
728                                 for (int x = 0; x < j; x++) {
729                                         if (t == ifaces [x]) {
730                                                 Report.Error (528, "`" + name + "' is already listed in interface list");
731                                                 error = true;
732                                                 return null;
733                                         }
734                                 }
735
736                                 ifaces [j] = t;
737                         }
738
739                         return TypeManager.ExpandInterfaces (ifaces);
740                 }
741                 
742                 //
743                 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
744                 //
745                 public override TypeBuilder DefineType ()
746                 {
747                         Type parent;
748                         bool error;
749                         bool is_class;
750
751                         if (TypeBuilder != null)
752                                 return TypeBuilder;
753                         
754                         if (InTransit)
755                                 return null;
756                         
757                         InTransit = true;
758
759                         if (this is Class)
760                                 is_class = true;
761                         else
762                                 is_class = false;
763
764                         ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
765
766                         ifaces = GetClassBases (is_class, out parent, out error); 
767                         
768                         if (error)
769                                 return null;
770
771                         if (is_class && parent != null){
772                                 if (parent == TypeManager.enum_type ||
773                                     (parent == TypeManager.value_type && RootContext.StdLib) ||
774                                     parent == TypeManager.delegate_type ||
775                                     parent == TypeManager.array_type){
776                                         Report.Error (
777                                                 644, Location, "`" + Name + "' cannot inherit from " +
778                                                 "special class `" + TypeManager.CSharpName (parent) + "'");
779                                         return null;
780                                 }
781                         }
782
783                         if (!is_class && TypeManager.value_type == null)
784                                 throw new Exception ();
785
786                         TypeAttributes type_attributes = TypeAttr;
787
788                         // if (parent_builder is ModuleBuilder) {
789                         if (IsTopLevel){
790                                 ModuleBuilder builder = CodeGen.ModuleBuilder;
791                                 TypeBuilder = builder.DefineType (
792                                         Name, type_attributes, parent, ifaces);
793                                 
794                         } else {
795                                 TypeBuilder builder = Parent.TypeBuilder;
796                                 TypeBuilder = builder.DefineNestedType (
797                                         Basename, type_attributes, parent, ifaces);
798                         }
799                                 
800                         //
801                         // Structs with no fields need to have at least one byte.
802                         // The right thing would be to set the PackingSize in a DefineType
803                         // but there are no functions that allow interfaces *and* the size to
804                         // be specified.
805                         //
806
807                         if (!is_class && !have_nonstatic_fields){
808                                 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
809                                                          FieldAttributes.Private);
810                                 // add interfaces that were not added at type creation
811                                 if (ifaces != null) {
812                                         foreach (Type i in ifaces)
813                                                 TypeBuilder.AddInterfaceImplementation (i);
814                                 }
815                         }
816
817                         //
818                         // Finish the setup for the EmitContext
819                         //
820                         ec.ContainerType = TypeBuilder;
821
822                         TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
823
824                         if ((parent != null) &&
825                             (parent == TypeManager.attribute_type ||
826                              parent.IsSubclassOf (TypeManager.attribute_type))) {
827                                 RootContext.RegisterAttribute (this);
828                                 TypeManager.RegisterAttrType (TypeBuilder, this);
829                         } else
830                                 RootContext.RegisterOrder (this); 
831                                 
832                         if (Interfaces != null) {
833                                 foreach (Interface iface in Interfaces)
834                                         iface.DefineType ();
835                         }
836                         
837                         if (Types != null) {
838                                 foreach (TypeContainer tc in Types)
839                                         tc.DefineType ();
840                         }
841
842                         if (Delegates != null) {
843                                 foreach (Delegate d in Delegates)
844                                         d.DefineType ();
845                         }
846
847                         if (Enums != null) {
848                                 foreach (Enum en in Enums)
849                                         en.DefineType ();
850                         }
851
852                         InTransit = false;
853                         return TypeBuilder;
854                 }
855
856
857                 /// <summary>
858                 ///   Defines the MemberCore objects that are in the `list' Arraylist
859                 ///
860                 ///   The `defined_names' array contains a list of members defined in
861                 ///   a base class
862                 /// </summary>
863                 static ArrayList remove_list = new ArrayList ();
864                 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
865                 {
866                         int idx;
867                         
868                         remove_list.Clear ();
869
870                         foreach (MemberCore mc in list){
871                                 if (!mc.Define (this)){
872                                         remove_list.Add (mc);
873                                         continue;
874                                 }
875                                                 
876                                 if (defined_names == null)
877                                         continue;
878
879                                 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
880                                 if (idx < 0){
881                                         if (RootContext.WarningLevel >= 4){
882                                                 if ((mc.ModFlags & Modifiers.NEW) != 0)
883                                                         Warning_KewywordNewNotRequired (mc.Location, mc);
884                                         }
885                                         continue;
886                                 }
887
888                                 MemberInfo match = defined_names [idx];
889
890                                 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
891                                         continue;
892
893                                 //
894                                 // If we are both methods, let the method resolution emit warnings
895                                 //
896                                 if (match is MethodBase && mc is MethodCore)
897                                         continue; 
898                                 
899                                 if ((mc.ModFlags & Modifiers.NEW) == 0)
900                                         Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
901                         }
902                         
903                         foreach (object o in remove_list)
904                                 list.Remove (o);
905                         
906                         remove_list.Clear ();
907                 }
908
909                 //
910                 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
911                 // class is consisten.  Either it is `Item' or it is the name defined by all the
912                 // indexers with the `IndexerName' attribute.
913                 //
914                 // Turns out that the IndexerNameAttribute is applied to each indexer,
915                 // but it is never emitted, instead a DefaultName attribute is attached
916                 // to the class.
917                 //
918                 void DefineIndexers ()
919                 {
920                         string class_indexer_name = null;
921                         
922                         foreach (Indexer i in Indexers){
923                                 string name;
924                                 
925                                 i.Define (this);
926
927                                 name = i.IndexerName;
928
929                                 if (i.InterfaceType != null)
930                                         continue;
931
932                                 if (class_indexer_name == null){
933                                         class_indexer_name = name;
934                                         continue;
935                                 }
936                                 
937                                 if (name == class_indexer_name)
938                                         continue;
939                                 
940                                 Report.Error (
941                                         668, "Two indexers have different names, " +
942                                         " you should use the same name for all your indexers");
943                         }
944                         if (class_indexer_name == null)
945                                 class_indexer_name = "Item";
946                         IndexerName = class_indexer_name;
947                 }
948
949                 static void Error_KeywordNotAllowed (Location loc)
950                 {
951                         Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
952                 }
953
954                 /// <summary>
955                 ///   Populates our TypeBuilder with fields and methods
956                 /// </summary>
957                 public override bool DefineMembers (TypeContainer parent)
958                 {
959                         MemberInfo [] defined_names = null;
960
961                         if (interface_order != null){
962                                 foreach (Interface iface in interface_order)
963                                         if ((iface.ModFlags & Modifiers.NEW) == 0)
964                                                 iface.DefineMembers (this);
965                                         else
966                                                 Error_KeywordNotAllowed (iface.Location);
967                         }
968
969                         if (RootContext.WarningLevel > 1){
970                                 Type ptype;
971
972                                 //
973                                 // This code throws an exception in the comparer
974                                 // I guess the string is not an object?
975                                 //
976                                 ptype = TypeBuilder.BaseType;
977                                 if (ptype != null){
978                                         defined_names = (MemberInfo []) FindMembers (
979                                                 ptype, MemberTypes.All & ~MemberTypes.Constructor,
980                                                 BindingFlags.Public | BindingFlags.Instance |
981                                                 BindingFlags.Static, null, null);
982
983                                         Array.Sort (defined_names, mif_compare);
984                                 }
985                         }
986                         
987                         if (constants != null)
988                                 DefineMembers (constants, defined_names);
989
990                         if (fields != null)
991                                 DefineMembers (fields, defined_names);
992
993                         if (this is Class){
994                                 if (instance_constructors == null){
995                                         if (default_constructor == null)
996                                                 DefineDefaultConstructor (false);
997                                 }
998
999                                 if (initialized_static_fields != null &&
1000                                     default_static_constructor == null)
1001                                         DefineDefaultConstructor (true);
1002                         }
1003
1004                         if (this is Struct){
1005                                 //
1006                                 // Structs can not have initialized instance
1007                                 // fields
1008                                 //
1009                                 if (initialized_static_fields != null &&
1010                                     default_static_constructor == null)
1011                                         DefineDefaultConstructor (true);
1012
1013                                 if (initialized_fields != null)
1014                                         ReportStructInitializedInstanceError ();
1015                         }
1016
1017                         Pending = PendingImplementation.GetPendingImplementations (this);
1018                         
1019                         //
1020                         // Constructors are not in the defined_names array
1021                         //
1022                         if (instance_constructors != null)
1023                                 DefineMembers (instance_constructors, null);
1024                 
1025                         if (default_static_constructor != null)
1026                                 default_static_constructor.Define (this);
1027                         
1028                         if (methods != null)
1029                                 DefineMembers (methods, defined_names);
1030
1031                         if (properties != null)
1032                                 DefineMembers (properties, defined_names);
1033
1034                         if (events != null)
1035                                 DefineMembers (events, defined_names);
1036
1037                         if (indexers != null) {
1038                                 DefineIndexers ();
1039                         } else
1040                                 IndexerName = "Item";
1041
1042                         if (operators != null){
1043                                 DefineMembers (operators, null);
1044
1045                                 CheckPairedOperators ();
1046                         }
1047
1048                         if (enums != null)
1049                                 DefineMembers (enums, defined_names);
1050                         
1051                         if (delegates != null)
1052                                 DefineMembers (delegates, defined_names);
1053
1054 #if CACHE
1055                         if (TypeBuilder.BaseType != null)
1056                                 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1057
1058                         member_cache = new MemberCache (this);
1059 #endif
1060
1061                         return true;
1062                 }
1063
1064                 public override bool Define (TypeContainer parent)
1065                 {
1066                         if (interface_order != null){
1067                                 foreach (Interface iface in interface_order)
1068                                         if ((iface.ModFlags & Modifiers.NEW) == 0)
1069                                                 iface.Define (this);
1070                         }
1071
1072                         return true;
1073                 }
1074
1075                 /// <summary>
1076                 ///   This function is based by a delegate to the FindMembers routine
1077                 /// </summary>
1078                 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1079                 {
1080                         return true;
1081                 }
1082
1083                 /// <summary>
1084                 ///   This filter is used by FindMembers, and we just keep
1085                 ///   a global for the filter to `AlwaysAccept'
1086                 /// </summary>
1087                 static MemberFilter accepting_filter;
1088
1089                 
1090                 /// <summary>
1091                 ///   A member comparission method based on name only
1092                 /// </summary>
1093                 static IComparer mif_compare;
1094
1095                 static TypeContainer ()
1096                 {
1097                         accepting_filter = new MemberFilter (AlwaysAccept);
1098                         mif_compare = new MemberInfoCompare ();
1099                 }
1100                 
1101                 /// <summary>
1102                 ///   This method returns the members of this type just like Type.FindMembers would
1103                 ///   Only, we need to use this for types which are _being_ defined because MS' 
1104                 ///   implementation can't take care of that.
1105                 /// </summary>
1106                 //
1107                 // FIXME: return an empty static array instead of null, that cleans up
1108                 // some code and is consistent with some coding conventions I just found
1109                 // out existed ;-)
1110                 //
1111                 //
1112                 // Notice that in various cases we check if our field is non-null,
1113                 // something that would normally mean that there was a bug elsewhere.
1114                 //
1115                 // The problem happens while we are defining p-invoke methods, as those
1116                 // will trigger a FindMembers, but this happens before things are defined
1117                 //
1118                 // Since the whole process is a no-op, it is fine to check for null here.
1119                 //
1120                 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1121                                                         MemberFilter filter, object criteria)
1122                 {
1123                         ArrayList members = new ArrayList ();
1124
1125                         int modflags = 0;
1126                         if ((bf & BindingFlags.Public) != 0)
1127                                 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1128                                         Modifiers.INTERNAL;
1129                         if ((bf & BindingFlags.NonPublic) != 0)
1130                                 modflags |= Modifiers.PRIVATE;
1131
1132                         int static_mask = 0, static_flags = 0;
1133                         switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1134                         case BindingFlags.Static:
1135                                 static_mask = static_flags = Modifiers.STATIC;
1136                                 break;
1137
1138                         case BindingFlags.Instance:
1139                                 static_mask = Modifiers.STATIC;
1140                                 static_flags = 0;
1141                                 break;
1142
1143                         default:
1144                                 static_mask = static_flags = 0;
1145                                 break;
1146                         }
1147
1148                         Timer.StartTimer (TimerType.TcFindMembers);
1149
1150                         if (filter == null)
1151                                 filter = accepting_filter; 
1152
1153                         if ((mt & MemberTypes.Field) != 0) {
1154                                 if (fields != null) {
1155                                         foreach (Field f in fields) {
1156                                                 if ((f.ModFlags & modflags) == 0)
1157                                                         continue;
1158                                                 if ((f.ModFlags & static_mask) != static_flags)
1159                                                         continue;
1160
1161                                                 FieldBuilder fb = f.FieldBuilder;
1162                                                 if (fb != null && filter (fb, criteria) == true)
1163                                                         members.Add (fb);
1164                                         }
1165                                 }
1166
1167                                 if (constants != null) {
1168                                         foreach (Const con in constants) {
1169                                                 if ((con.ModFlags & modflags) == 0)
1170                                                         continue;
1171                                                 if ((con.ModFlags & static_mask) != static_flags)
1172                                                         continue;
1173
1174                                                 FieldBuilder fb = con.FieldBuilder;
1175                                                 if (fb != null && filter (fb, criteria) == true)
1176                                                         members.Add (fb);
1177                                         }
1178                                 }
1179                         }
1180
1181                         if ((mt & MemberTypes.Method) != 0) {
1182                                 if (methods != null) {
1183                                         foreach (Method m in methods) {
1184                                                 if ((m.ModFlags & modflags) == 0)
1185                                                         continue;
1186                                                 if ((m.ModFlags & static_mask) != static_flags)
1187                                                         continue;
1188                                                 
1189                                                 MethodBuilder mb = m.MethodBuilder;
1190
1191                                                 if (mb != null && filter (mb, criteria) == true)
1192                                                         members.Add (mb);
1193                                         }
1194                                 }
1195
1196                                 if (operators != null){
1197                                         foreach (Operator o in operators) {
1198                                                 if ((o.ModFlags & modflags) == 0)
1199                                                         continue;
1200                                                 if ((o.ModFlags & static_mask) != static_flags)
1201                                                         continue;
1202                                                 
1203                                                 MethodBuilder ob = o.OperatorMethodBuilder;
1204                                                 if (ob != null && filter (ob, criteria) == true)
1205                                                         members.Add (ob);
1206                                         }
1207                                 }
1208
1209                                 if (properties != null){
1210                                         foreach (Property p in properties){
1211                                                 if ((p.ModFlags & modflags) == 0)
1212                                                         continue;
1213                                                 if ((p.ModFlags & static_mask) != static_flags)
1214                                                         continue;
1215                                                 
1216                                                 MethodBuilder b;
1217
1218                                                 b = p.GetBuilder;
1219                                                 if (b != null && filter (b, criteria) == true)
1220                                                         members.Add (b);
1221
1222                                                 b = p.SetBuilder;
1223                                                 if (b != null && filter (b, criteria) == true)
1224                                                         members.Add (b);
1225                                         }
1226                                 }
1227                                 
1228                                 if (indexers != null){
1229                                         foreach (Indexer ix in indexers){
1230                                                 if ((ix.ModFlags & modflags) == 0)
1231                                                         continue;
1232                                                 if ((ix.ModFlags & static_mask) != static_flags)
1233                                                         continue;
1234                                                 
1235                                                 MethodBuilder b;
1236
1237                                                 b = ix.GetBuilder;
1238                                                 if (b != null && filter (b, criteria) == true)
1239                                                         members.Add (b);
1240
1241                                                 b = ix.SetBuilder;
1242                                                 if (b != null && filter (b, criteria) == true)
1243                                                         members.Add (b);
1244                                         }
1245                                 }
1246                         }
1247
1248                         if ((mt & MemberTypes.Event) != 0) {
1249                                 if (events != null)
1250                                         foreach (Event e in events) {
1251                                                 if ((e.ModFlags & modflags) == 0)
1252                                                         continue;
1253                                                 if ((e.ModFlags & static_mask) != static_flags)
1254                                                         continue;
1255
1256                                                 MemberInfo eb = e.EventBuilder;
1257                                                 if (eb != null && filter (eb, criteria) == true)
1258                                                         members.Add (e.EventBuilder);
1259                                         }
1260                         }
1261                         
1262                         if ((mt & MemberTypes.Property) != 0){
1263                                 if (properties != null)
1264                                         foreach (Property p in properties) {
1265                                                 if ((p.ModFlags & modflags) == 0)
1266                                                         continue;
1267                                                 if ((p.ModFlags & static_mask) != static_flags)
1268                                                         continue;
1269
1270                                                 MemberInfo pb = p.PropertyBuilder;
1271                                                 if (pb != null && filter (pb, criteria) == true) {
1272                                                         members.Add (p.PropertyBuilder);
1273                                                 }
1274                                         }
1275
1276                                 if (indexers != null)
1277                                         foreach (Indexer ix in indexers) {
1278                                                 if ((ix.ModFlags & modflags) == 0)
1279                                                         continue;
1280                                                 if ((ix.ModFlags & static_mask) != static_flags)
1281                                                         continue;
1282
1283                                                 MemberInfo ib = ix.PropertyBuilder;
1284                                                 if (ib != null && filter (ib, criteria) == true) {
1285                                                         members.Add (ix.PropertyBuilder);
1286                                                 }
1287                                         }
1288                         }
1289                         
1290                         if ((mt & MemberTypes.NestedType) != 0) {
1291                                 if (types != null){
1292                                         foreach (TypeContainer t in types) {
1293                                                 if ((t.ModFlags & modflags) == 0)
1294                                                         continue;
1295
1296                                                 TypeBuilder tb = t.TypeBuilder;
1297                                                 if (tb != null && (filter (tb, criteria) == true))
1298                                                                 members.Add (tb);
1299                                         }
1300                                 }
1301
1302                                 if (enums != null){
1303                                         foreach (Enum en in enums){
1304                                                 if ((en.ModFlags & modflags) == 0)
1305                                                         continue;
1306
1307                                                 TypeBuilder tb = en.TypeBuilder;
1308                                                 if (tb != null && (filter (tb, criteria) == true))
1309                                                         members.Add (tb);
1310                                         }
1311                                 }
1312                                 
1313                                 if (delegates != null){
1314                                         foreach (Delegate d in delegates){
1315                                                 if ((d.ModFlags & modflags) == 0)
1316                                                         continue;
1317
1318                                                 TypeBuilder tb = d.TypeBuilder;
1319                                                 if (tb != null && (filter (tb, criteria) == true))
1320                                                         members.Add (tb);
1321                                         }
1322                                 }
1323
1324                                 if (interfaces != null){
1325                                         foreach (Interface iface in interfaces){
1326                                                 if ((iface.ModFlags & modflags) == 0)
1327                                                         continue;
1328
1329                                                 TypeBuilder tb = iface.TypeBuilder;
1330                                                 if (tb != null && (filter (tb, criteria) == true))
1331                                                         members.Add (tb);
1332                                         }
1333                                 }
1334                         }
1335
1336                         if ((mt & MemberTypes.Constructor) != 0){
1337                                 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1338                                         foreach (Constructor c in instance_constructors){
1339                                                 ConstructorBuilder cb = c.ConstructorBuilder;
1340                                                 if (cb != null)
1341                                                         if (filter (cb, criteria) == true)
1342                                                                 members.Add (cb);
1343                                         }
1344                                 }
1345
1346                                 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1347                                         ConstructorBuilder cb =
1348                                                 default_static_constructor.ConstructorBuilder;
1349                                         
1350                                         if (cb != null)
1351                                         if (filter (cb, criteria) == true)
1352                                                 members.Add (cb);
1353                                 }
1354                         }
1355
1356                         //
1357                         // Lookup members in parent if requested.
1358                         //
1359                         if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1360                                 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1361                                 members.AddRange (list);
1362                         }
1363
1364                         Timer.StopTimer (TimerType.TcFindMembers);
1365
1366                         return new MemberList (members);
1367                 }
1368
1369                 public override MemberCache MemberCache {
1370                         get {
1371                                 return member_cache;
1372                         }
1373                 }
1374
1375                 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1376                                                       MemberFilter filter, object criteria)
1377                 {
1378                         TypeContainer tc = TypeManager.LookupTypeContainer (t);
1379
1380                         if (tc != null)
1381                                 return tc.FindMembers (mt, bf, filter, criteria);
1382                         else
1383                                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1384                 }
1385
1386                 //
1387                 // FindMethods will look for methods not only in the type `t', but in
1388                 // any interfaces implemented by the type.
1389                 //
1390                 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1391                                                          MemberFilter filter, object criteria)
1392                 {
1393                         return null;
1394                 }
1395
1396                 /// <summary>
1397                 ///   Emits the values for the constants
1398                 /// </summary>
1399                 public void EmitConstants ()
1400                 {
1401                         if (constants != null)
1402                                 foreach (Const con in constants)
1403                                         con.EmitConstant (this);
1404                         return;
1405                 }
1406
1407                 /// <summary>
1408                 ///   Emits the code, this step is performed after all
1409                 ///   the types, enumerations, constructors
1410                 /// </summary>
1411                 public void Emit ()
1412                 {
1413                         if (instance_constructors != null)
1414                                 foreach (Constructor c in instance_constructors)
1415                                         c.Emit (this);
1416
1417                         if (default_static_constructor != null)
1418                                 default_static_constructor.Emit (this);
1419                         
1420                         if (methods != null)
1421                                 foreach (Method m in methods)
1422                                         m.Emit (this);
1423
1424                         if (operators != null)
1425                                 foreach (Operator o in operators)
1426                                         o.Emit (this);
1427
1428                         if (properties != null)
1429                                 foreach (Property p in properties)
1430                                         p.Emit (this);
1431
1432                         if (indexers != null){
1433                                 foreach (Indexer ix in indexers)
1434                                         ix.Emit (this);
1435                                 
1436                                 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1437                                         this, IndexerName, ModFlags, Location);
1438                                 TypeBuilder.SetCustomAttribute (cb);
1439                         }
1440                         
1441                         if (fields != null)
1442                                 foreach (Field f in fields)
1443                                         f.Emit (this);
1444
1445                         if (events != null){
1446                                 foreach (Event e in Events)
1447                                         e.Emit (this);
1448                         }
1449
1450                         if (Pending != null)
1451                                 if (Pending.VerifyPendingMethods ())
1452                                         return;
1453                         
1454                         Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1455
1456                         //
1457                         // Check for internal or private fields that were never assigned
1458                         //
1459                         if (RootContext.WarningLevel >= 3) {
1460                                 if (fields != null){
1461                                         foreach (Field f in fields) {
1462                                                 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1463                                                         continue;
1464                                                 
1465                                                 if (f.status == 0){
1466                                                         Report.Warning (
1467                                                                 169, f.Location, "Private field " +
1468                                                                 MakeName (f.Name) + " is never used");
1469                                                         continue;
1470                                                 }
1471                                                 
1472                                                 //
1473                                                 // Only report 649 on level 4
1474                                                 //
1475                                                 if (RootContext.WarningLevel < 4)
1476                                                         continue;
1477                                                 
1478                                                 if ((f.status & Field.Status.ASSIGNED) != 0)
1479                                                         continue;
1480                                                 
1481                                                 Report.Warning (
1482                                                         649, f.Location,
1483                                                         "Field " + MakeName (f.Name) + " is never assigned " +
1484                                                         " to and will always have its default value");
1485                                         }
1486                                 }
1487
1488                                 if (events != null){
1489                                         foreach (Event e in events){
1490                                                 if (e.status == 0)
1491                                                         Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1492                                         }
1493                                 }
1494                         }
1495                         
1496 //                      if (types != null)
1497 //                              foreach (TypeContainer tc in types)
1498 //                                      tc.Emit ();
1499                 }
1500                 
1501                 public override void CloseType ()
1502                 {
1503                         try {
1504                                 if (!Created){
1505                                         Created = true;
1506                                         TypeBuilder.CreateType ();
1507                                 }
1508                         } catch (TypeLoadException){
1509                                 //
1510                                 // This is fine, the code still created the type
1511                                 //
1512 //                              Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1513 //                              Console.WriteLine (e.Message);
1514                         } catch {
1515                                 Console.WriteLine ("In type: " + Name);
1516                                 throw;
1517                         }
1518                         
1519                         if (Enums != null)
1520                                 foreach (Enum en in Enums)
1521                                         en.CloseType ();
1522
1523                         if (interface_order != null){
1524                                 foreach (Interface iface in interface_order)
1525                                         iface.CloseType ();
1526                         }
1527                         
1528                         if (Types != null){
1529                                 foreach (TypeContainer tc in Types)
1530                                         if (tc is Struct)
1531                                                 tc.CloseType ();
1532
1533                                 foreach (TypeContainer tc in Types)
1534                                         if (!(tc is Struct))
1535                                                 tc.CloseType ();
1536                         }
1537
1538                         if (Delegates != null)
1539                                 foreach (Delegate d in Delegates)
1540                                         d.CloseType ();
1541                 }
1542
1543                 public string MakeName (string n)
1544                 {
1545                         return "`" + Name + "." + n + "'";
1546                 }
1547
1548                 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1549                 {
1550                         Report.Warning (
1551                                 108, l, "The keyword new is required on " + 
1552                                 MakeName (mi.Name) + " because it hides `" +
1553                                 mi.ReflectedType.Name + "." + mi.Name + "'");
1554                 }
1555
1556                 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1557                 {
1558                         Report.Warning (
1559                                 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1560                                 "inherited member, the keyword new is not required");
1561                 }
1562                 
1563                 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1564                 {
1565                         return 0;
1566                 }
1567
1568                 //
1569                 // Performs the validation on a Method's modifiers (properties have
1570                 // the same properties).
1571                 //
1572                 public bool MethodModifiersValid (int flags, string n, Location loc)
1573                 {
1574                         const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1575                         const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1576                         const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1577                         bool ok = true;
1578                         
1579                         //
1580                         // At most one of static, virtual or override
1581                         //
1582                         if ((flags & Modifiers.STATIC) != 0){
1583                                 if ((flags & vao) != 0){
1584                                         Report.Error (
1585                                                 112, loc, "static method " + MakeName (n) + "can not be marked " +
1586                                                 "as virtual, abstract or override");
1587                                         ok = false;
1588                                 }
1589                         }
1590
1591                         if (this is Struct){
1592                                 if ((flags & va) != 0){
1593                                         Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1594                                         ok = false;
1595                                 }
1596                         }
1597
1598                         if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1599                                 Report.Error (
1600                                         113, loc, MakeName (n) +
1601                                         " marked as override cannot be marked as new or virtual");
1602                                 ok = false;
1603                         }
1604
1605                         //
1606                         // If the declaration includes the abstract modifier, then the
1607                         // declaration does not include static, virtual or extern
1608                         //
1609                         if ((flags & Modifiers.ABSTRACT) != 0){
1610                                 if ((flags & Modifiers.EXTERN) != 0){
1611                                         Report.Error (
1612                                                 180, loc, MakeName (n) + " can not be both abstract and extern");
1613                                         ok = false;
1614                                 }
1615
1616                                 if ((flags & Modifiers.VIRTUAL) != 0){
1617                                         Report.Error (
1618                                                 503, loc, MakeName (n) + " can not be both abstract and virtual");
1619                                         ok = false;
1620                                 }
1621
1622                                 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1623                                         Report.Error (
1624                                                 513, loc, MakeName (n) +
1625                                                 " is abstract but its container class is not");
1626                                         ok = false;
1627
1628                                 }
1629                         }
1630
1631                         if ((flags & Modifiers.PRIVATE) != 0){
1632                                 if ((flags & vao) != 0){
1633                                         Report.Error (
1634                                                 621, loc, MakeName (n) +
1635                                                 " virtual or abstract members can not be private");
1636                                         ok = false;
1637                                 }
1638                         }
1639
1640                         if ((flags & Modifiers.SEALED) != 0){
1641                                 if ((flags & Modifiers.OVERRIDE) == 0){
1642                                         Report.Error (
1643                                                 238, loc, MakeName (n) +
1644                                                 " cannot be sealed because it is not an override");
1645                                         ok = false;
1646                                 }
1647                         }
1648
1649                         return ok;
1650                 }
1651
1652                 // Access level of a type.
1653                 enum AccessLevel {
1654                         Public                  = 0,
1655                         ProtectedInternal       = 1,
1656                         Internal                = 2,
1657                         Protected               = 3,
1658                         Private                 = 4
1659                 }
1660
1661                 // Check whether `flags' denotes a more restricted access than `level'
1662                 // and return the new level.
1663                 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1664                 {
1665                         AccessLevel old_level = level;
1666
1667                         if ((flags & Modifiers.INTERNAL) != 0) {
1668                                 if ((flags & Modifiers.PROTECTED) != 0) {
1669                                         if ((int) level < (int) AccessLevel.ProtectedInternal)
1670                                                 level = AccessLevel.ProtectedInternal;
1671                                 } else {
1672                                         if ((int) level < (int) AccessLevel.Internal)
1673                                                 level = AccessLevel.Internal;
1674                                 }
1675                         } else if ((flags & Modifiers.PROTECTED) != 0) {
1676                                 if ((int) level < (int) AccessLevel.Protected)
1677                                         level = AccessLevel.Protected;
1678                         } else if ((flags & Modifiers.PRIVATE) != 0)
1679                                 level = AccessLevel.Private;
1680
1681                         return level;
1682                 }
1683
1684                 // Return the access level for a new member which is defined in the current
1685                 // TypeContainer with access modifiers `flags'.
1686                 AccessLevel GetAccessLevel (int flags)
1687                 {
1688                         if ((flags & Modifiers.PRIVATE) != 0)
1689                                 return AccessLevel.Private;
1690
1691                         AccessLevel level;
1692                         if (!IsTopLevel && (Parent != null))
1693                                 level = Parent.GetAccessLevel (flags);
1694                         else
1695                                 level = AccessLevel.Public;
1696
1697                         return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1698                 }
1699
1700                 // Return the access level for type `t', but don't give more access than `flags'.
1701                 static AccessLevel GetAccessLevel (Type t, int flags)
1702                 {
1703                         if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1704                                 return AccessLevel.Private;
1705
1706                         AccessLevel level;
1707                         if (TypeManager.IsBuiltinType (t))
1708                                 return AccessLevel.Public;
1709                         else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1710                                 level = GetAccessLevel (t.DeclaringType, flags);
1711                         else {
1712                                 level = CheckAccessLevel (AccessLevel.Public, flags);
1713                         }
1714
1715                         if (t.IsNestedPublic)
1716                                 return level;
1717
1718                         if (t.IsNestedAssembly || t.IsNotPublic) {
1719                                 if ((int) level < (int) AccessLevel.Internal)
1720                                         level = AccessLevel.Internal;
1721                         }
1722
1723                         if (t.IsNestedFamily) {
1724                                 if ((int) level < (int) AccessLevel.Protected)
1725                                         level = AccessLevel.Protected;
1726                         }
1727
1728                         if (t.IsNestedFamORAssem) {
1729                                 if ((int) level < (int) AccessLevel.ProtectedInternal)
1730                                         level = AccessLevel.ProtectedInternal;
1731                         }
1732
1733                         return level;
1734                 }
1735
1736                 //
1737                 // Returns true if `parent' is as accessible as the flags `flags'
1738                 // given for this member.
1739                 //
1740                 public bool AsAccessible (Type parent, int flags)
1741                 {
1742                         while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1743                                 parent = parent.GetElementType ();
1744
1745                         AccessLevel level = GetAccessLevel (flags);
1746                         AccessLevel level2 = GetAccessLevel (parent, flags);
1747
1748                         return (int) level >= (int) level2;
1749                 }
1750
1751                 Hashtable builder_and_args;
1752                 
1753                 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1754                 {
1755                         if (builder_and_args == null)
1756                                 builder_and_args = new Hashtable ();
1757                         return true;
1758                 }
1759
1760                 /// <summary>
1761                 ///   Performs checks for an explicit interface implementation.  First it
1762                 ///   checks whether the `interface_type' is a base inteface implementation.
1763                 ///   Then it checks whether `name' exists in the interface type.
1764                 /// </summary>
1765                 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1766                 {
1767                         bool found = false;
1768
1769                         if (ifaces != null){
1770                                 foreach (Type t in ifaces){
1771                                         if (t == interface_type){
1772                                                 found = true;
1773                                                 break;
1774                                         }
1775                                 }
1776                         }
1777                         
1778                         if (!found){
1779                                 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1780                                 return false;
1781                         }
1782
1783                         return true;
1784                 }
1785
1786                 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1787                 {
1788                         Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1789                 }
1790
1791                 //
1792                 // IMemberContainer
1793                 //
1794
1795                 string IMemberContainer.Name {
1796                         get {
1797                                 return Name;
1798                         }
1799                 }
1800
1801                 Type IMemberContainer.Type {
1802                         get {
1803                                 return TypeBuilder;
1804                         }
1805                 }
1806
1807                 IMemberContainer IMemberContainer.Parent {
1808                         get {
1809                                 return parent_container;
1810                         }
1811                 }
1812
1813                 MemberCache IMemberContainer.MemberCache {
1814                         get {
1815                                 return member_cache;
1816                         }
1817                 }
1818
1819                 bool IMemberContainer.IsInterface {
1820                         get {
1821                                 return false;
1822                         }
1823                 }
1824
1825                 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1826                 {
1827                         return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1828                 }
1829
1830                 //
1831                 // Operator pair checking
1832                 //
1833
1834                 class OperatorEntry {
1835                         public int flags;
1836                         public Type ret_type;
1837                         public Type type1, type2;
1838                         public Operator op;
1839                         public Operator.OpType ot;
1840                         
1841                         public OperatorEntry (int f, Operator o)
1842                         {
1843                                 flags = f;
1844
1845                                 ret_type = o.OperatorMethod.GetReturnType ();
1846                                 Type [] pt = o.OperatorMethod.ParameterTypes;
1847                                 type1 = pt [0];
1848                                 type2 = pt [1];
1849                                 op = o;
1850                                 ot = o.OperatorType;
1851                         }
1852
1853                         public override int GetHashCode ()
1854                         {       
1855                                 return ret_type.GetHashCode ();
1856                         }
1857
1858                         public override bool Equals (object o)
1859                         {
1860                                 OperatorEntry other = (OperatorEntry) o;
1861
1862                                 if (other.ret_type != ret_type)
1863                                         return false;
1864                                 if (other.type1 != type1)
1865                                         return false;
1866                                 if (other.type2 != type2)
1867                                         return false;
1868                                 return true;
1869                         }
1870                 }
1871                                 
1872                 //
1873                 // Checks that some operators come in pairs:
1874                 //  == and !=
1875                 // > and <
1876                 // >= and <=
1877                 // true and false
1878                 //
1879                 // They are matched based on the return type and the argument types
1880                 //
1881                 void CheckPairedOperators ()
1882                 {
1883                         Hashtable pairs = new Hashtable (null, null);
1884                         Operator true_op = null;
1885                         Operator false_op = null;
1886                         
1887                         // Register all the operators we care about.
1888                         foreach (Operator op in operators){
1889                                 int reg = 0;
1890                                 
1891                                 switch (op.OperatorType){
1892                                 case Operator.OpType.Equality:
1893                                         reg = 1; break;
1894                                 case Operator.OpType.Inequality:
1895                                         reg = 2; break;
1896
1897                                 case Operator.OpType.True:
1898                                         true_op = op;
1899                                         break;
1900                                 case Operator.OpType.False:
1901                                         false_op = op;
1902                                         break;
1903                                         
1904                                 case Operator.OpType.GreaterThan:
1905                                         reg = 1; break;
1906                                 case Operator.OpType.LessThan:
1907                                         reg = 2; break;
1908                                         
1909                                 case Operator.OpType.GreaterThanOrEqual:
1910                                         reg = 1; break;
1911                                 case Operator.OpType.LessThanOrEqual:
1912                                         reg = 2; break;
1913                                 }
1914                                 if (reg == 0)
1915                                         continue;
1916
1917                                 OperatorEntry oe = new OperatorEntry (reg, op);
1918
1919                                 object o = pairs [oe];
1920                                 if (o == null)
1921                                         pairs [oe] = oe;
1922                                 else {
1923                                         oe = (OperatorEntry) o;
1924                                         oe.flags |= reg;
1925                                 }
1926                         }
1927
1928                         if (true_op != null){
1929                                 if (false_op == null)
1930                                         Report.Error (216, true_op.Location, "operator true requires a matching operator false");
1931                         } else if (false_op != null)
1932                                 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
1933                         
1934                         //
1935                         // Look for the mistakes.
1936                         //
1937                         foreach (DictionaryEntry de in pairs){
1938                                 OperatorEntry oe = (OperatorEntry) de.Key;
1939
1940                                 if (oe.flags == 3)
1941                                         continue;
1942
1943                                 string s = "";
1944                                 switch (oe.ot){
1945                                 case Operator.OpType.Equality:
1946                                         s = "!=";
1947                                         break;
1948                                 case Operator.OpType.Inequality: 
1949                                         s = "==";
1950                                         break;
1951                                 case Operator.OpType.GreaterThan: 
1952                                         s = "<";
1953                                         break;
1954                                 case Operator.OpType.LessThan:
1955                                         s = ">";
1956                                         break;
1957                                 case Operator.OpType.GreaterThanOrEqual:
1958                                         s = "<=";
1959                                         break;
1960                                 case Operator.OpType.LessThanOrEqual:
1961                                         s = ">=";
1962                                         break;
1963                                 }
1964                                 Report.Error (216, oe.op.Location,
1965                                               "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
1966                         }
1967                 }
1968                 
1969                 
1970         }
1971
1972         public class Class : TypeContainer {
1973                 // <summary>
1974                 //   Modifiers allowed in a class declaration
1975                 // </summary>
1976                 public const int AllowedModifiers =
1977                         Modifiers.NEW |
1978                         Modifiers.PUBLIC |
1979                         Modifiers.PROTECTED |
1980                         Modifiers.INTERNAL |
1981                         Modifiers.PRIVATE |
1982                         Modifiers.ABSTRACT |
1983                         Modifiers.SEALED |
1984                         Modifiers.UNSAFE;
1985
1986                 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1987                         : base (parent, name, l)
1988                 {
1989                         int accmods;
1990
1991                         if (parent.Parent == null)
1992                                 accmods = Modifiers.INTERNAL;
1993                         else
1994                                 accmods = Modifiers.PRIVATE;
1995
1996                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1997                         this.attributes = attrs;
1998                 }
1999
2000                 //
2001                 // FIXME: How do we deal with the user specifying a different
2002                 // layout?
2003                 //
2004                 public override TypeAttributes TypeAttr {
2005                         get {
2006                                 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2007                         }
2008                 }
2009         }
2010
2011         public class Struct : TypeContainer {
2012                 // <summary>
2013                 //   Modifiers allowed in a struct declaration
2014                 // </summary>
2015                 public const int AllowedModifiers =
2016                         Modifiers.NEW       |
2017                         Modifiers.PUBLIC    |
2018                         Modifiers.PROTECTED |
2019                         Modifiers.INTERNAL  |
2020                         Modifiers.UNSAFE    |
2021                         Modifiers.PRIVATE;
2022
2023                 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2024                         : base (parent, name, l)
2025                 {
2026                         int accmods;
2027                         
2028                         if (parent.Parent == null)
2029                                 accmods = Modifiers.INTERNAL;
2030                         else
2031                                 accmods = Modifiers.PRIVATE;
2032                         
2033                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2034
2035                         this.ModFlags |= Modifiers.SEALED;
2036                         this.attributes = attrs;
2037                         
2038                 }
2039
2040                 //
2041                 // FIXME: Allow the user to specify a different set of attributes
2042                 // in some cases (Sealed for example is mandatory for a class,
2043                 // but what SequentialLayout can be changed
2044                 //
2045                 public override TypeAttributes TypeAttr {
2046                         get {
2047                                 return base.TypeAttr |
2048                                         TypeAttributes.SequentialLayout |
2049                                         TypeAttributes.Sealed |
2050                                         TypeAttributes.BeforeFieldInit;
2051                         }
2052                 }
2053         }
2054
2055         public abstract class MethodCore : MemberBase {
2056                 public readonly Parameters Parameters;
2057                 protected Block block;
2058                 
2059                 //
2060                 // Parameters, cached for semantic analysis.
2061                 //
2062                 protected InternalParameters parameter_info;
2063                 protected Type [] parameter_types;
2064
2065                 public MethodCore (Expression type, int mod, int allowed_mod, string name,
2066                                    Attributes attrs, Parameters parameters, Location loc)
2067                         : base (type, mod, allowed_mod, name, attrs, loc)
2068                 {
2069                         Parameters = parameters;
2070                 }
2071                 
2072                 //
2073                 //  Returns the System.Type array for the parameters of this method
2074                 //
2075                 public Type [] ParameterTypes {
2076                         get {
2077                                 return parameter_types;
2078                         }
2079                 }
2080
2081                 public InternalParameters ParameterInfo
2082                 {
2083                         get {
2084                                 return parameter_info;
2085                         }
2086                 }
2087                 
2088                 public Block Block {
2089                         get {
2090                                 return block;
2091                         }
2092
2093                         set {
2094                                 block = value;
2095                         }
2096                 }
2097
2098                 protected virtual bool DoDefineParameters (TypeContainer parent)
2099                 {
2100                         // Check if arguments were correct
2101                         parameter_types = Parameters.GetParameterInfo (parent);
2102                         if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2103                                 return false;
2104
2105                         parameter_info = new InternalParameters (parent, Parameters);
2106
2107                         return true;
2108                 }
2109
2110                 public CallingConventions GetCallingConvention (bool is_class)
2111                 {
2112                         CallingConventions cc = 0;
2113                         
2114                         cc = Parameters.GetCallingConvention ();
2115
2116                         if (is_class)
2117                                 if ((ModFlags & Modifiers.STATIC) == 0)
2118                                         cc |= CallingConventions.HasThis;
2119
2120                         // FIXME: How is `ExplicitThis' used in C#?
2121                         
2122                         return cc;
2123                 }
2124
2125                 //
2126                 // The method's attributes are passed in because we need to extract
2127                 // the "return:" attribute from there to apply on the return type
2128                 //
2129                 public void LabelParameters (EmitContext ec, MethodBase builder, Attributes method_attrs)
2130                 {
2131                         //
2132                         // Define each type attribute (in/out/ref) and
2133                         // the argument names.
2134                         //
2135                         Parameter [] p = Parameters.FixedParameters;
2136                         int i = 0;
2137                         
2138                         MethodBuilder mb = null;
2139                         ConstructorBuilder cb = null;
2140
2141                         if (builder is MethodBuilder)
2142                                 mb = (MethodBuilder) builder;
2143                         else
2144                                 cb = (ConstructorBuilder) builder;
2145
2146                         if (p != null){
2147                                 for (i = 0; i < p.Length; i++) {
2148                                         ParameterBuilder pb;
2149                                         ParameterAttributes par_attr = p [i].Attributes;
2150                                         
2151                                         if (mb == null)
2152                                                 pb = cb.DefineParameter (
2153                                                         i + 1, par_attr, p [i].Name);
2154                                         else 
2155                                                 pb = mb.DefineParameter (
2156                                                         i + 1, par_attr, p [i].Name);
2157                                         
2158                                         Attributes attr = p [i].OptAttributes;
2159                                         if (attr != null){
2160                                                 Attribute.ApplyAttributes (ec, pb, pb, attr);
2161
2162                                                 if (par_attr == ParameterAttributes.Out){
2163                                                         if (attr.Contains (TypeManager.in_attribute_type))
2164                                                                 Report.Error (36, Location, "Can not use [In] attribute on out parameter");
2165                                                 }
2166                                         }
2167                                 }
2168                         }
2169
2170                         if (Parameters.ArrayParameter != null){
2171                                 ParameterBuilder pb;
2172                                 Parameter array_param = Parameters.ArrayParameter;
2173                                 
2174                                 if (mb == null)
2175                                         pb = cb.DefineParameter (
2176                                                 i + 1, array_param.Attributes,
2177                                                 array_param.Name);
2178                                 else
2179                                         pb = mb.DefineParameter (
2180                                                 i + 1, array_param.Attributes,
2181                                                 array_param.Name);
2182                                         
2183                                 CustomAttributeBuilder a = new CustomAttributeBuilder (
2184                                         TypeManager.cons_param_array_attribute, new object [0]);
2185                                 
2186                                 pb.SetCustomAttribute (a);
2187                         }
2188
2189                         //
2190                         // And now for the return type attribute decoration
2191                         //
2192                         ParameterBuilder ret_pb;
2193                         Attributes ret_attrs = null;
2194                                 
2195                         if (mb == null || method_attrs == null)
2196                                 return;
2197
2198                         foreach (AttributeSection asec in method_attrs.AttributeSections) {
2199
2200                                 if (asec.Target != "return")
2201                                         continue;
2202
2203                                 if (ret_attrs == null)
2204                                         ret_attrs = new Attributes (asec);
2205                                 else
2206                                         ret_attrs.AddAttributeSection (asec);
2207                         }
2208
2209                         if (ret_attrs != null) {
2210                                 try {
2211                                         ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2212                                         Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2213                                 } catch (ArgumentOutOfRangeException) {
2214                                         Report.Warning (
2215                                                 -24, Location,
2216                                                 ".NET SDK 1.0 does not permit to set custom attributes to the return type of a method");
2217                                 }
2218                         }
2219                 }
2220         }
2221         
2222         public class Method : MethodCore {
2223                 public MethodBuilder MethodBuilder;
2224                 public MethodData MethodData;
2225
2226                 /// <summary>
2227                 ///   Modifiers allowed in a class declaration
2228                 /// </summary>
2229                 const int AllowedModifiers =
2230                         Modifiers.NEW |
2231                         Modifiers.PUBLIC |
2232                         Modifiers.PROTECTED |
2233                         Modifiers.INTERNAL |
2234                         Modifiers.PRIVATE |
2235                         Modifiers.STATIC |
2236                         Modifiers.VIRTUAL |
2237                         Modifiers.SEALED |
2238                         Modifiers.OVERRIDE |
2239                         Modifiers.ABSTRACT |
2240                         Modifiers.UNSAFE |
2241                         Modifiers.EXTERN;
2242
2243                 //
2244                 // return_type can be "null" for VOID values.
2245                 //
2246                 public Method (Expression return_type, int mod, string name, Parameters parameters,
2247                                Attributes attrs, Location l)
2248                         : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2249                 { }
2250
2251                 //
2252                 // Returns the `System.Type' for the ReturnType of this
2253                 // function.  Provides a nice cache.  (used between semantic analysis
2254                 // and actual code generation
2255                 //
2256                 public Type GetReturnType ()
2257                 {
2258                         return MemberType;
2259                 }
2260
2261                 // Whether this is an operator method.
2262                 public bool IsOperator;
2263
2264                 void DuplicateEntryPoint (MethodInfo b, Location location)
2265                 {
2266                         Report.Error (
2267                                 17, location,
2268                                 "Program `" + CodeGen.FileName +
2269                                 "'  has more than one entry point defined: `" +
2270                                 TypeManager.CSharpSignature(b) + "'");
2271                 }
2272
2273                 void Report28 (MethodInfo b)
2274                 {
2275                         if (RootContext.WarningLevel < 4) 
2276                                 return;
2277                                 
2278                         Report.Warning (
2279                                 28, Location,
2280                                 "`" + TypeManager.CSharpSignature(b) +
2281                                 "' has the wrong signature to be an entry point");
2282                 }
2283
2284                 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2285                 {
2286                         if (b.ReturnType != TypeManager.void_type &&
2287                             b.ReturnType != TypeManager.int32_type)
2288                                 return false;
2289
2290                         if (pinfo.Count == 0)
2291                                 return true;
2292
2293                         if (pinfo.Count > 1)
2294                                 return false;
2295
2296                         Type t = pinfo.ParameterType(0);
2297                         if (t.IsArray &&
2298                             (t.GetArrayRank() == 1) &&
2299                             (t.GetElementType() == TypeManager.string_type) &&
2300                             (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2301                                 return true;
2302                         else
2303                                 return false;
2304                 }
2305
2306                 //
2307                 // Checks our base implementation if any
2308                 //
2309                 protected override bool CheckBase (TypeContainer parent)
2310                 {
2311                         // Check whether arguments were correct.
2312                         if (!DoDefineParameters (parent))
2313                                 return false;
2314
2315                         MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2316                         if (IsOperator) {
2317                                 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2318                         } else {
2319                                 MemberList mi_this;
2320
2321                                 mi_this = TypeContainer.FindMembers (
2322                                         parent.TypeBuilder, MemberTypes.Method,
2323                                         BindingFlags.NonPublic | BindingFlags.Public |
2324                                         BindingFlags.Static | BindingFlags.Instance |
2325                                         BindingFlags.DeclaredOnly,
2326                                         MethodSignature.method_signature_filter, ms);
2327
2328                                 if (mi_this.Count > 0) {
2329                                         Report.Error (111, Location, "Class `" + parent.Name + "' " +
2330                                                       "already defines a member called `" + Name + "' " +
2331                                                       "with the same parameter types");
2332                                         return false;
2333                                 }
2334                         } 
2335
2336                         //
2337                         // Verify if the parent has a type with the same name, and then
2338                         // check whether we have to create a new slot for it or not.
2339                         //
2340                         Type ptype = parent.TypeBuilder.BaseType;
2341
2342                         // ptype is only null for System.Object while compiling corlib.
2343                         if (ptype != null){
2344                                 MemberList mi, mi_static, mi_instance;
2345
2346                                 mi_static = TypeContainer.FindMembers (
2347                                         ptype, MemberTypes.Method,
2348                                         BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2349                                         MethodSignature.inheritable_method_signature_filter, ms);
2350
2351                                 mi_instance = TypeContainer.FindMembers (
2352                                         ptype, MemberTypes.Method,
2353                                         BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2354                                         MethodSignature.inheritable_method_signature_filter,
2355                                         ms);
2356
2357                                 if (mi_instance.Count > 0){
2358                                         mi = mi_instance;
2359                                 } else if (mi_static.Count > 0)
2360                                         mi = mi_static;
2361                                 else
2362                                         mi = null;
2363
2364                                 if (mi != null && mi.Count > 0){
2365                                         parent_method = (MethodInfo) mi [0];
2366                                         string name = parent_method.DeclaringType.Name + "." +
2367                                                 parent_method.Name;
2368
2369                                         if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2370                                                 return false;
2371
2372                                         if ((ModFlags & Modifiers.NEW) == 0) {
2373                                                 Type parent_ret = TypeManager.TypeToCoreType (
2374                                                         parent_method.ReturnType);
2375
2376                                                 if (parent_ret != MemberType) {
2377                                                         Report.Error (
2378                                                                 508, Location, parent.MakeName (Name) + ": cannot " +
2379                                                                 "change return type when overriding " +
2380                                                                 "inherited member " + name);
2381                                                         return false;
2382                                                 }
2383                                         }
2384                                 } else {
2385                                         if ((ModFlags & Modifiers.NEW) != 0)
2386                                                 WarningNotHiding (parent);
2387
2388                                         if ((ModFlags & Modifiers.OVERRIDE) != 0){
2389                                                 Report.Error (115, Location,
2390                                                               parent.MakeName (Name) +
2391                                                               " no suitable methods found to override");
2392                                         }
2393                                 }
2394                         } else if ((ModFlags & Modifiers.NEW) != 0)
2395                                 WarningNotHiding (parent);
2396
2397                         return true;
2398                 }
2399
2400                 //
2401                 // Creates the type
2402                 //
2403                 public override bool Define (TypeContainer parent)
2404                 {
2405                         if (!DoDefine (parent))
2406                                 return false;
2407
2408                         if (!CheckBase (parent))
2409                                 return false;
2410
2411                         CallingConventions cc = GetCallingConvention (parent is Class);
2412
2413                         MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2414                                                      ParameterInfo, cc, OptAttributes,
2415                                                      ModFlags, flags, true);
2416
2417                         if (!MethodData.Define (parent))
2418                                 return false;
2419
2420                         MethodBuilder = MethodData.MethodBuilder;
2421                         
2422                         //
2423                         // This is used to track the Entry Point,
2424                         //
2425                         if (Name == "Main" &&
2426                             ((ModFlags & Modifiers.STATIC) != 0) && 
2427                             (RootContext.MainClass == null ||
2428                              RootContext.MainClass == parent.TypeBuilder.FullName)){
2429                                 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2430                                         if (RootContext.EntryPoint == null) {
2431                                                 RootContext.EntryPoint = MethodBuilder;
2432                                                 RootContext.EntryPointLocation = Location;
2433                                         } else {
2434                                                 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2435                                                 DuplicateEntryPoint (MethodBuilder, Location);
2436                                         }
2437                                 } else                                  
2438                                         Report28(MethodBuilder);
2439                         }
2440
2441                         return true;
2442                 }
2443
2444                 //
2445                 // Emits the code
2446                 // 
2447                 public void Emit (TypeContainer parent)
2448                 {
2449                         MethodData.Emit (parent, Block, this);
2450                 }
2451         }
2452
2453         public abstract class ConstructorInitializer {
2454                 ArrayList argument_list;
2455                 ConstructorInfo parent_constructor;
2456                 Parameters parameters;
2457                 Location loc;
2458                 
2459                 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2460                                                Location loc)
2461                 {
2462                         this.argument_list = argument_list;
2463                         this.parameters = parameters;
2464                         this.loc = loc;
2465                 }
2466
2467                 public ArrayList Arguments {
2468                         get {
2469                                 return argument_list;
2470                         }
2471                 }
2472
2473                 public bool Resolve (EmitContext ec)
2474                 {
2475                         Expression parent_constructor_group;
2476                         Type t;
2477
2478                         ec.CurrentBlock = new Block (null, true, parameters);
2479
2480                         if (argument_list != null){
2481                                 foreach (Argument a in argument_list){
2482                                         if (!a.Resolve (ec, loc))
2483                                                 return false;
2484                                 }
2485                         }
2486
2487                         ec.CurrentBlock = null;
2488
2489                         if (this is ConstructorBaseInitializer) {
2490                                 if (ec.ContainerType.BaseType == null)
2491                                         return true;
2492
2493                                 t = ec.ContainerType.BaseType;
2494                                 if (ec.ContainerType.IsValueType) {
2495                                         Report.Error (522, loc,
2496                                                 "structs cannot call base class constructors");
2497                                         return false;
2498                                 }
2499                         } else
2500                                 t = ec.ContainerType;
2501
2502                         parent_constructor_group = Expression.MemberLookup (
2503                                 ec, t, null, t, ".ctor", 
2504                                 MemberTypes.Constructor,
2505                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2506                                 loc);
2507                         
2508                         if (parent_constructor_group == null){
2509                                 Report.Error (1501, loc,
2510                                        "Can not find a constructor for this argument list");
2511                                 return false;
2512                         }
2513                         
2514                         parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
2515                                 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2516                         
2517                         if (parent_constructor == null){
2518                                 Report.Error (1501, loc,
2519                                        "Can not find a constructor for this argument list");
2520                                 return false;
2521                         }
2522                         
2523                         return true;
2524                 }
2525
2526                 public void Emit (EmitContext ec)
2527                 {
2528                         if (parent_constructor != null){
2529                                 ec.Mark (loc);
2530                                 if (ec.IsStatic)
2531                                         Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2532                                 else
2533                                         Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2534                         }
2535                 }
2536         }
2537
2538         public class ConstructorBaseInitializer : ConstructorInitializer {
2539                 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2540                         base (argument_list, pars, l)
2541                 {
2542                 }
2543         }
2544
2545         public class ConstructorThisInitializer : ConstructorInitializer {
2546                 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2547                         base (argument_list, pars, l)
2548                 {
2549                 }
2550         }
2551         
2552         public class Constructor : MethodCore {
2553                 public ConstructorBuilder ConstructorBuilder;
2554                 public ConstructorInitializer Initializer;
2555                 new public Attributes OptAttributes;
2556
2557                 // <summary>
2558                 //   Modifiers allowed for a constructor.
2559                 // </summary>
2560                 public const int AllowedModifiers =
2561                         Modifiers.PUBLIC |
2562                         Modifiers.PROTECTED |
2563                         Modifiers.INTERNAL |
2564                         Modifiers.STATIC |
2565                         Modifiers.UNSAFE |
2566                         Modifiers.EXTERN |              
2567                         Modifiers.PRIVATE;
2568
2569                 //
2570                 // The spec claims that static is not permitted, but
2571                 // my very own code has static constructors.
2572                 //
2573                 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2574                         : base (null, 0, AllowedModifiers, name, null, args, l)
2575                 {
2576                         Initializer = init;
2577                 }
2578
2579                 //
2580                 // Returns true if this is a default constructor
2581                 //
2582                 public bool IsDefault ()
2583                 {
2584                         if ((ModFlags & Modifiers.STATIC) != 0)
2585                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2586                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2587                         
2588                         else
2589                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2590                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2591                                         (Initializer is ConstructorBaseInitializer) &&
2592                                         (Initializer.Arguments == null);
2593                 }
2594
2595                 //
2596                 // Creates the ConstructorBuilder
2597                 //
2598                 public override bool Define (TypeContainer parent)
2599                 {
2600                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
2601                                                MethodAttributes.SpecialName);
2602
2603                         // Check if arguments were correct.
2604                         if (!DoDefineParameters (parent))
2605                                 return false;
2606
2607                         if ((ModFlags & Modifiers.STATIC) != 0)
2608                                 ca |= MethodAttributes.Static;
2609                         else {
2610                                 if (parent is Struct && ParameterTypes.Length == 0){
2611                                         Report.Error (
2612                                                 568, Location, 
2613                                                 "Structs can not contain explicit parameterless " +
2614                                                 "constructors");
2615                                         return false;
2616                                 }
2617                                 ca |= MethodAttributes.HideBySig;
2618
2619                                 if ((ModFlags & Modifiers.PUBLIC) != 0)
2620                                         ca |= MethodAttributes.Public;
2621                                 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2622                                         if ((ModFlags & Modifiers.INTERNAL) != 0)
2623                                                 ca |= MethodAttributes.FamORAssem;
2624                                         else 
2625                                                 ca |= MethodAttributes.Family;
2626                                 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2627                                         ca |= MethodAttributes.Assembly;
2628                                 else if (IsDefault ())
2629                                         ca |= MethodAttributes.Public;
2630                                 else
2631                                         ca |= MethodAttributes.Private;
2632                         }
2633
2634                         ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2635                                 ca, GetCallingConvention (parent is Class), ParameterTypes);
2636
2637                         //
2638                         // HACK because System.Reflection.Emit is lame
2639                         //
2640                         if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2641                                 Report.Error (
2642                                         111, Location,
2643                                         "Class `" +parent.Name+ "' already contains a definition with the " +
2644                                         "same return value and parameter types for constructor `" + Name
2645                                         + "'");
2646                                 return false;
2647                         }
2648
2649                         return true;
2650                 }
2651
2652                 //
2653                 // Emits the code
2654                 //
2655                 public void Emit (TypeContainer parent)
2656                 {
2657                         ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2658                         EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2659
2660                         //
2661                         // extern methods have no bodies
2662                         //
2663                         if ((ModFlags & Modifiers.EXTERN) != 0) {
2664                                 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
2665                                         Report.Error (
2666                                                 179, Location, "External constructor `" +
2667                                                 TypeManager.CSharpSignature (ConstructorBuilder) +
2668                                                 "' can not have a body");
2669                                         return;
2670                                 }
2671                         } else if (block == null) {
2672                                 Report.Error (
2673                                         501, Location, "Constructor `" +
2674                                         TypeManager.CSharpSignature (ConstructorBuilder) +
2675                                         "' must declare a body since it is not marked extern");
2676                                 return;
2677                         }
2678
2679                         if ((ModFlags & Modifiers.STATIC) == 0){
2680                                 if (parent is Class && Initializer == null)
2681                                         Initializer = new ConstructorBaseInitializer (
2682                                                 null, Parameters.EmptyReadOnlyParameters, Location.Null);
2683
2684
2685                                 //
2686                                 // Spec mandates that Initializers will not have
2687                                 // `this' access
2688                                 //
2689                                 ec.IsStatic = true;
2690                                 if (Initializer != null && !Initializer.Resolve (ec))
2691                                         return;
2692                                 ec.IsStatic = false;
2693                         }
2694
2695                         LabelParameters (ec, ConstructorBuilder, OptAttributes);
2696                         
2697                         SymbolWriter sw = CodeGen.SymbolWriter;
2698                         bool generate_debugging = false;
2699
2700                         if ((sw != null) && (block != null) &&
2701                                 !Location.IsNull (Location) &&
2702                                 !Location.IsNull (block.EndLocation)) {
2703
2704                                 sw.OpenMethod (parent, ConstructorBuilder, Location, block.EndLocation);
2705
2706                                 generate_debugging = true;
2707                         }
2708
2709                         //
2710                         // Classes can have base initializers and instance field initializers.
2711                         //
2712                         if (parent is Class){
2713                                 if ((ModFlags & Modifiers.STATIC) == 0)
2714                                         parent.EmitFieldInitializers (ec);
2715                         }
2716                         if (Initializer != null)
2717                                 Initializer.Emit (ec);
2718                         
2719                         if ((ModFlags & Modifiers.STATIC) != 0)
2720                                 parent.EmitFieldInitializers (ec);
2721
2722                         Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
2723
2724                         // If this is a non-static `struct' constructor and doesn't have any
2725                         // initializer, it must initialize all of the struct's fields.
2726                         if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2727                             (Initializer == null))
2728                                 Block.AddThisVariable (parent, Location);
2729
2730                         ec.EmitTopBlock (block, ParameterInfo, Location);
2731
2732                         if (generate_debugging)
2733                                 sw.CloseMethod ();
2734                 }
2735         }
2736
2737         public class MethodData {
2738                 //
2739                 // The return type of this method
2740                 //
2741                 public readonly Type ReturnType;
2742                 public readonly Type[] ParameterTypes;
2743                 public readonly InternalParameters ParameterInfo;
2744                 public readonly CallingConventions CallingConventions;
2745                 public readonly Attributes OptAttributes;
2746                 public readonly Location Location;
2747
2748                 //
2749                 // Are we implementing an interface ?
2750                 //
2751                 public bool IsImplementing = false;
2752
2753                 //
2754                 // Protected data.
2755                 //
2756                 protected MemberBase member;
2757                 protected int modifiers;
2758                 protected MethodAttributes flags;
2759                 protected bool is_method;
2760                 protected string accessor_name;
2761                 ArrayList conditionals;
2762
2763                 MethodBuilder builder = null;
2764                 public MethodBuilder MethodBuilder {
2765                         get {
2766                                 return builder;
2767                         }
2768                 }
2769
2770                 public MethodData (MemberBase member, string name, Type return_type,
2771                                    Type [] parameter_types, InternalParameters parameters,
2772                                    CallingConventions cc, Attributes opt_attrs,
2773                                    int modifiers, MethodAttributes flags, bool is_method)
2774                 {
2775                         this.member = member;
2776                         this.accessor_name = name;
2777                         this.ReturnType = return_type;
2778                         this.ParameterTypes = parameter_types;
2779                         this.ParameterInfo = parameters;
2780                         this.CallingConventions = cc;
2781                         this.OptAttributes = opt_attrs;
2782                         this.modifiers = modifiers;
2783                         this.flags = flags;
2784                         this.is_method = is_method;
2785                         this.Location = member.Location;
2786                         this.conditionals = new ArrayList ();
2787                 }
2788
2789                 //
2790                 // Attributes.
2791                 //
2792                 Attribute dllimport_attribute = null;
2793                 string obsolete = null;
2794                 bool obsolete_error = false;
2795
2796                 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2797                 {
2798                         if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2799                                 return true;
2800
2801                         foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2802                                 if (asec.Attributes == null)
2803                                         continue;
2804                                         
2805                                 foreach (Attribute a in asec.Attributes) {
2806                                         if (a.Name == "Conditional") {
2807                                                 if (!ApplyConditionalAttribute (a))
2808                                                         return false;
2809                                         } else if (a.Name == "Obsolete") {
2810                                                 if (!ApplyObsoleteAttribute (a))
2811                                                         return false;
2812                                         } else if (a.Name.IndexOf ("DllImport") != -1) {
2813                                                 if (!is_method) {
2814                                                         a.Type = TypeManager.dllimport_type;
2815                                                         Attribute.Error_AttributeNotValidForElement (a, Location);
2816                                                         return false;
2817                                                 }
2818                                                 if (!ApplyDllImportAttribute (a))
2819                                                         return false;
2820                                         }
2821                                 }
2822                         }
2823
2824                         return true;
2825                 }
2826
2827                 //
2828                 // Applies the `DllImport' attribute to the method.
2829                 //
2830                 protected virtual bool ApplyDllImportAttribute (Attribute a)
2831                 {
2832                         const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2833                         if ((modifiers & extern_static) != extern_static) {
2834                                 Report.Error (601, Location,
2835                                               "The DllImport attribute must be specified on a method " +
2836                                               "marked `static' and `extern'.");
2837                                 return false;
2838                         }
2839
2840                         flags |= MethodAttributes.PinvokeImpl;
2841                         dllimport_attribute = a;
2842                         return true;
2843                 }
2844
2845                 //
2846                 // Applies the `Obsolete' attribute to the method.
2847                 //
2848                 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2849                 {
2850                         if (obsolete != null) {
2851                                 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2852                                 return false;
2853                         }
2854
2855                         obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2856                         return obsolete != null;
2857                 }
2858
2859                 //
2860                 // Applies the `Conditional' attribute to the method.
2861                 //
2862                 protected virtual bool ApplyConditionalAttribute (Attribute a)
2863                 {
2864                         // The Conditional attribute is only valid on methods.
2865                         if (!is_method) {
2866                                 Attribute.Error_AttributeNotValidForElement (a, Location);
2867                                 return false;
2868                         }
2869
2870                         string condition = a.Conditional_GetConditionName ();
2871
2872                         if (condition == null)
2873                                 return false;
2874
2875                         if (ReturnType != TypeManager.void_type) {
2876                                 Report.Error (578, Location,
2877                                               "Conditional not valid on `" + member.Name + "' " +
2878                                               "because its return type is not void");
2879                                 return false;
2880                         }
2881
2882                         if ((modifiers & Modifiers.OVERRIDE) != 0) {
2883                                 Report.Error (243, Location,
2884                                               "Conditional not valid on `" + member.Name + "' " +
2885                                               "because it is an override method");
2886                                 return false;
2887                         }
2888
2889                         if (member.IsExplicitImpl) {
2890                                 Report.Error (577, Location,
2891                                               "Conditional not valid on `" + member.Name + "' " +
2892                                               "because it is an explicit interface implementation");
2893                                 return false;
2894                         }
2895
2896                         if (IsImplementing) {
2897                                 Report.Error (623, Location,
2898                                               "Conditional not valid on `" + member.Name + "' " +
2899                                               "because it is an interface method");
2900                                 return false;
2901                         }
2902
2903                         conditionals.Add (condition);
2904
2905                         return true;
2906                 }
2907
2908                 //
2909                 // Checks whether this method should be ignored due to its Conditional attributes.
2910                 //
2911                 bool ShouldIgnore (Location loc)
2912                 {
2913                         // When we're overriding a virtual method, we implicitly inherit the
2914                         // Conditional attributes from our parent.
2915                         if (member.ParentMethod != null) {
2916                                 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2917                                         member.ParentMethod, loc);
2918
2919                                 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2920                                         return true;
2921                         }
2922
2923                         foreach (string condition in conditionals)
2924                                 if (RootContext.AllDefines [condition] == null)
2925                                         return true;
2926
2927                         return false;
2928                 }
2929
2930                 //
2931                 // Returns the TypeManager.MethodFlags for this method.
2932                 // This emits an error 619 / warning 618 if the method is obsolete.
2933                 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2934                 //
2935                 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2936                 {
2937                         TypeManager.MethodFlags flags = 0;
2938
2939                         if (obsolete != null) {
2940                                 if (obsolete_error) {
2941                                         Report.Error (619, loc, "Method `" + member.Name +
2942                                                       "' is obsolete: `" + obsolete + "'");
2943                                         return TypeManager.MethodFlags.IsObsoleteError;
2944                                 } else
2945                                         Report.Warning (618, loc, "Method `" + member.Name +
2946                                                         "' is obsolete: `" + obsolete + "'");
2947
2948                                 flags |= TypeManager.MethodFlags.IsObsolete;
2949                         }
2950
2951                         if (ShouldIgnore (loc))
2952                             flags |= TypeManager.MethodFlags.ShouldIgnore;
2953
2954                         return flags;
2955                 }
2956
2957                 public virtual bool Define (TypeContainer parent)
2958                 {
2959                         MethodInfo implementing = null;
2960                         string method_name, name, prefix;
2961
2962                         if (OptAttributes != null)
2963                                 if (!ApplyAttributes (OptAttributes, is_method))
2964                                         return false;
2965
2966                         if (member.IsExplicitImpl)
2967                                 prefix = member.InterfaceType.FullName + ".";
2968                         else
2969                                 prefix = "";
2970
2971                         if (accessor_name != null)
2972                                 name = accessor_name + "_" + member.ShortName;
2973                         else
2974                                 name = member.ShortName;
2975                         method_name = prefix + name;
2976
2977                         if (parent.Pending != null){
2978                                 if (member is Indexer)
2979                                         implementing = parent.Pending.IsInterfaceIndexer (
2980                                                 member.InterfaceType, ReturnType, ParameterTypes);
2981                                 else
2982                                         implementing = parent.Pending.IsInterfaceMethod (
2983                                                 member.InterfaceType, name, ReturnType, ParameterTypes);
2984
2985                                 if (member.InterfaceType != null && implementing == null){
2986                                         TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2987                                                 Location, name);
2988                                         return false;
2989                                 }
2990                         }
2991
2992                         //
2993                         // For implicit implementations, make sure we are public, for
2994                         // explicit implementations, make sure we are private.
2995                         //
2996                         if (implementing != null){
2997                                 //
2998                                 // Setting null inside this block will trigger a more
2999                                 // verbose error reporting for missing interface implementations
3000                                 //
3001                                 // The "candidate" function has been flagged already
3002                                 // but it wont get cleared
3003                                 //
3004                                 if (member.IsExplicitImpl){
3005                                         if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3006                                                 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3007                                                 implementing = null;
3008                                         }
3009                                 } else {
3010                                         //
3011                                         // We already catch different accessibility settings
3012                                         // so we just need to check that we are not private
3013                                         //
3014                                         if ((modifiers & Modifiers.PRIVATE) != 0)
3015                                                 implementing = null;
3016                                 } 
3017                                         
3018                                 //
3019                                 // Static is not allowed
3020                                 //
3021                                 if ((modifiers & Modifiers.STATIC) != 0){
3022                                         implementing = null;
3023                                         Modifiers.Error_InvalidModifier (Location, "static");
3024                                 }
3025                         }
3026                         
3027                         //
3028                         // If implementing is still valid, set flags
3029                         //
3030                         if (implementing != null){
3031                                 //
3032                                 // When implementing interface methods, set NewSlot.
3033                                 //
3034                                 if (implementing.DeclaringType.IsInterface)
3035                                         flags |= MethodAttributes.NewSlot;
3036
3037                                 flags |=
3038                                         MethodAttributes.Virtual |
3039                                         MethodAttributes.HideBySig;
3040
3041                                 // Get the method name from the explicit interface.
3042                                 if (member.InterfaceType != null) {
3043                                         name = implementing.Name;
3044                                         method_name = prefix + name;
3045                                 }
3046
3047                                 IsImplementing = true;
3048                         }
3049
3050                         //
3051                         // Create the MethodBuilder for the method
3052                         //
3053                         if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3054                                 if ((modifiers & Modifiers.STATIC) == 0) {
3055                                         Report.Error (601, Location,
3056                                                       "The DllImport attribute must be specified on " +
3057                                                       "a method marked 'static' and 'extern'.");
3058                                         return false;
3059                                 }
3060                                 
3061                                 EmitContext ec = new EmitContext (
3062                                         parent, Location, null, ReturnType, modifiers);
3063                                 
3064                                 builder = dllimport_attribute.DefinePInvokeMethod (
3065                                         ec, parent.TypeBuilder, method_name, flags,
3066                                         ReturnType, ParameterTypes);
3067                         } else
3068                                 builder = parent.TypeBuilder.DefineMethod (
3069                                         method_name, flags, CallingConventions,
3070                                         ReturnType, ParameterTypes);
3071
3072                         if (builder == null)
3073                                 return false;
3074
3075                         if (IsImplementing) {
3076                                 //
3077                                 // clear the pending implemntation flag
3078                                 //
3079                                 if (member is Indexer) {
3080                                         parent.Pending.ImplementIndexer (
3081                                                 member.InterfaceType, builder, ReturnType,
3082                                                 ParameterTypes, true);
3083                                 } else
3084                                         parent.Pending.ImplementMethod (
3085                                                 member.InterfaceType, name, ReturnType,
3086                                                 ParameterTypes, member.IsExplicitImpl);
3087
3088                                 if (member.IsExplicitImpl)
3089                                         parent.TypeBuilder.DefineMethodOverride (
3090                                                 builder, implementing);
3091                         }
3092
3093                         if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3094                                 Report.Error (111, Location,
3095                                               "Class `" + parent.Name +
3096                                               "' already contains a definition with the " +
3097                                               "same return value and parameter types as the " +
3098                                               "'get' method of property `" + member.Name + "'");
3099                                 return false;
3100                         }
3101
3102                         TypeManager.AddMethod (builder, this);
3103
3104                         return true;
3105                 }
3106
3107                 //
3108                 // Emits the code
3109                 // 
3110                 public virtual void Emit (TypeContainer parent, Block block, object kind)
3111                 {
3112                         ILGenerator ig;
3113                         EmitContext ec;
3114
3115                         if ((flags & MethodAttributes.PinvokeImpl) == 0)
3116                                 ig = builder.GetILGenerator ();
3117                         else
3118                                 ig = null;
3119
3120                         ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3121
3122                         if (OptAttributes != null)
3123                                 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3124
3125                         if (member is MethodCore)
3126                                 ((MethodCore) member).LabelParameters (ec, MethodBuilder, OptAttributes);
3127
3128                         //
3129                         // abstract or extern methods have no bodies
3130                         //
3131                         if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3132                                 if (block == null) {
3133                                         SymbolWriter sw = CodeGen.SymbolWriter;
3134
3135                                         if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0)) {
3136                                                 sw.OpenMethod (parent, MethodBuilder, Location, Location);
3137                                                 sw.CloseMethod ();
3138                                         }
3139
3140                                         return;
3141                                 }
3142
3143                                 //
3144                                 // abstract or extern methods have no bodies.
3145                                 //
3146                                 if ((modifiers & Modifiers.ABSTRACT) != 0)
3147                                         Report.Error (
3148                                                 500, Location, "Abstract method `" +
3149                                                 TypeManager.CSharpSignature (builder) +
3150                                                 "' can not have a body");
3151
3152                                 if ((modifiers & Modifiers.EXTERN) != 0)
3153                                         Report.Error (
3154                                                 179, Location, "External method `" +
3155                                                 TypeManager.CSharpSignature (builder) +
3156                                                 "' can not have a body");
3157
3158                                 return;
3159                         }
3160
3161                         //
3162                         // Methods must have a body unless they're extern or abstract
3163                         //
3164                         if (block == null) {
3165                                 Report.Error (
3166                                         501, Location, "Method `" +
3167                                         TypeManager.CSharpSignature (builder) +
3168                                         "' must declare a body since it is not marked " +
3169                                         "abstract or extern");
3170                                 return;
3171                         }
3172
3173                         //
3174                         // Handle destructors specially
3175                         //
3176                         // FIXME: This code generates buggy code
3177                         //
3178                         if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3179                                 EmitDestructor (ec, block);
3180                         else {
3181                                 SymbolWriter sw = CodeGen.SymbolWriter;
3182
3183                                 if ((sw != null) && !Location.IsNull (Location) &&
3184                                     !Location.IsNull (block.EndLocation)) {
3185                                         sw.OpenMethod (parent, MethodBuilder, Location, block.EndLocation);
3186
3187                                         ec.EmitTopBlock (block, ParameterInfo, Location);
3188
3189                                         sw.CloseMethod ();
3190                                 } else
3191                                         ec.EmitTopBlock (block, ParameterInfo, Location);
3192                         }
3193                 }
3194
3195                 void EmitDestructor (EmitContext ec, Block block)
3196                 {
3197                         ILGenerator ig = ec.ig;
3198                         
3199                         Label finish = ig.DefineLabel ();
3200                         bool old_in_try = ec.InTry;
3201                         
3202                         ig.BeginExceptionBlock ();
3203                         ec.InTry = true;
3204                         ec.ReturnLabel = finish;
3205                         ec.HasReturnLabel = true;
3206                         ec.EmitTopBlock (block, null, Location);
3207                         ec.InTry = old_in_try;
3208                         
3209                         // ig.MarkLabel (finish);
3210                         bool old_in_finally = ec.InFinally;
3211                         ec.InFinally = true;
3212                         ig.BeginFinallyBlock ();
3213                         
3214                         if (ec.ContainerType.BaseType != null) {
3215                                 Expression member_lookup = Expression.MemberLookup (
3216                                         ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3217                                         "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
3218
3219                                 if (member_lookup != null){
3220                                         MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3221                                 
3222                                         ig.Emit (OpCodes.Ldarg_0);
3223                                         ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3224                                 }
3225                         }
3226                         ec.InFinally = old_in_finally;
3227                         
3228                         ig.EndExceptionBlock ();
3229                         //ig.MarkLabel (ec.ReturnLabel);
3230                         ig.Emit (OpCodes.Ret);
3231                 }
3232         }
3233
3234         abstract public class MemberBase : MemberCore {
3235                 public Expression Type;
3236                 public readonly Attributes OptAttributes;
3237
3238                 protected MethodAttributes flags;
3239
3240                 //
3241                 // The "short" name of this property / indexer / event.  This is the
3242                 // name without the explicit interface.
3243                 //
3244                 public string ShortName;
3245
3246                 //
3247                 // The type of this property / indexer / event
3248                 //
3249                 public Type MemberType;
3250
3251                 //
3252                 // If true, this is an explicit interface implementation
3253                 //
3254                 public bool IsExplicitImpl = false;
3255
3256                 //
3257                 // The name of the interface we are explicitly implementing
3258                 //
3259                 public string ExplicitInterfaceName = null;
3260
3261                 //
3262                 // If true, the interface type we are explicitly implementing
3263                 //
3264                 public Type InterfaceType = null;
3265
3266                 //
3267                 // The method we're overriding if this is an override method.
3268                 //
3269                 protected MethodInfo parent_method = null;
3270                 public MethodInfo ParentMethod {
3271                         get {
3272                                 return parent_method;
3273                         }
3274                 }
3275
3276                 //
3277                 // The constructor is only exposed to our children
3278                 //
3279                 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3280                                       Attributes attrs, Location loc)
3281                         : base (name, loc)
3282                 {
3283                         Type = type;
3284                         ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
3285                         OptAttributes = attrs;
3286                 }
3287
3288                 protected virtual bool CheckBase (TypeContainer parent)
3289                 {
3290                         return true;
3291                 }
3292
3293                 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3294                 {
3295                         bool error = false;
3296
3297                         foreach (Type partype in parameters){
3298                                 if (partype.IsPointer){
3299                                         if (!UnsafeOK (parent))
3300                                                 error = true;
3301                                         if (!TypeManager.VerifyUnManaged (partype.GetElementType (), Location))
3302                                                 error = true;
3303                                 }
3304
3305                                 if (parent.AsAccessible (partype, ModFlags))
3306                                         continue;
3307
3308                                 if (this is Indexer)
3309                                         Report.Error (55, Location,
3310                                                       "Inconsistent accessibility: parameter type `" +
3311                                                       TypeManager.CSharpName (partype) + "' is less " +
3312                                                       "accessible than indexer `" + Name + "'");
3313                                 else
3314                                         Report.Error (51, Location,
3315                                                       "Inconsistent accessibility: parameter type `" +
3316                                                       TypeManager.CSharpName (partype) + "' is less " +
3317                                                       "accessible than method `" + Name + "'");
3318                                 error = true;
3319                         }
3320
3321                         return !error;
3322                 }
3323
3324                 protected virtual bool DoDefine (TypeContainer parent)
3325                 {
3326                         if (Name == null)
3327                                 Name = "this";
3328
3329                         if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3330                                 return false;
3331
3332                         flags = Modifiers.MethodAttr (ModFlags);
3333
3334                         // Lookup Type, verify validity
3335                         MemberType = parent.ResolveType (Type, false, Location);
3336                         if (MemberType == null)
3337                                 return false;
3338
3339                         if ((parent.ModFlags & Modifiers.SEALED) != 0){
3340                                 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
3341                                         Report.Error (549, Location, "Virtual method can not be contained in sealed class");
3342                                         return false;
3343                                 }
3344                         }
3345                         
3346                         // verify accessibility
3347                         if (!parent.AsAccessible (MemberType, ModFlags)) {
3348                                 if (this is Property)
3349                                         Report.Error (53, Location,
3350                                                       "Inconsistent accessibility: property type `" +
3351                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3352                                                       "accessible than property `" + Name + "'");
3353                                 else if (this is Indexer)
3354                                         Report.Error (54, Location,
3355                                                       "Inconsistent accessibility: indexer return type `" +
3356                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3357                                                       "accessible than indexer `" + Name + "'");
3358                                 else if (this is Method)
3359                                         Report.Error (50, Location,
3360                                                       "Inconsistent accessibility: return type `" +
3361                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3362                                                       "accessible than method `" + Name + "'");
3363                                 else
3364                                         Report.Error (52, Location,
3365                                                       "Inconsistent accessibility: field type `" +
3366                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3367                                                       "accessible than field `" + Name + "'");
3368                                 return false;
3369                         }
3370
3371                         if (MemberType.IsPointer && !UnsafeOK (parent))
3372                                 return false;
3373                         
3374                         //
3375                         // Check for explicit interface implementation
3376                         //
3377                         if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3378                                 int pos = Name.LastIndexOf (".");
3379
3380                                 ExplicitInterfaceName = Name.Substring (0, pos);
3381                                 ShortName = Name.Substring (pos + 1);
3382                         } else
3383                                 ShortName = Name;
3384
3385                         if (ExplicitInterfaceName != null) {
3386                                 InterfaceType  = RootContext.LookupType (
3387                                         parent, ExplicitInterfaceName, false, Location);
3388                                 if (InterfaceType == null)
3389                                         return false;
3390
3391                                 // Compute the full name that we need to export.
3392                                 Name = InterfaceType.FullName + "." + ShortName;
3393                                 
3394                                 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3395                                         return false;
3396                                 
3397                                 IsExplicitImpl = true;
3398                         } else
3399                                 IsExplicitImpl = false;
3400
3401                         return true;
3402                 }
3403         }
3404
3405         //
3406         // Fields and Events both generate FieldBuilders, we use this to share 
3407         // their common bits.  This is also used to flag usage of the field
3408         //
3409         abstract public class FieldBase : MemberBase {
3410                 public FieldBuilder  FieldBuilder;
3411                 public Status status;
3412
3413                 [Flags]
3414                 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3415
3416                 //
3417                 // The constructor is only exposed to our children
3418                 //
3419                 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3420                                      object init, Attributes attrs, Location loc)
3421                         : base (type, mod, allowed_mod, name, attrs, loc)
3422                 {
3423                         this.init = init;
3424                 }
3425
3426                 //
3427                 // Whether this field has an initializer.
3428                 //
3429                 public bool HasInitializer {
3430                         get {
3431                                 return init != null;
3432                         }
3433                 }
3434
3435                 // Private.
3436                 readonly Object init;
3437                 Expression init_expr;
3438                 bool init_expr_initialized = false;
3439
3440                 //
3441                 // Resolves and returns the field initializer.
3442                 //
3443                 public Expression GetInitializerExpression (EmitContext ec)
3444                 {
3445                         if (init_expr_initialized)
3446                                 return init_expr;
3447
3448                         Expression e;
3449                         if (init is Expression)
3450                                 e = (Expression) init;
3451                         else
3452                                 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3453
3454                         ec.IsFieldInitializer = true;
3455                         e = e.DoResolve (ec);
3456                         ec.IsFieldInitializer = false;
3457
3458                         init_expr = e;
3459                         init_expr_initialized = true;
3460
3461                         return init_expr;
3462                 }
3463         }
3464
3465         //
3466         // The Field class is used to represents class/struct fields during parsing.
3467         //
3468         public class Field : FieldBase {
3469                 // <summary>
3470                 //   Modifiers allowed in a class declaration
3471                 // </summary>
3472                 const int AllowedModifiers =
3473                         Modifiers.NEW |
3474                         Modifiers.PUBLIC |
3475                         Modifiers.PROTECTED |
3476                         Modifiers.INTERNAL |
3477                         Modifiers.PRIVATE |
3478                         Modifiers.STATIC |
3479                         Modifiers.VOLATILE |
3480                         Modifiers.UNSAFE |
3481                         Modifiers.READONLY;
3482
3483                 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3484                               Attributes attrs, Location loc)
3485                         : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3486                 {
3487                 }
3488
3489                 public override bool Define (TypeContainer parent)
3490                 {
3491                         Type t = parent.ResolveType (Type, false, Location);
3492                         
3493                         if (t == null)
3494                                 return false;
3495
3496                         if (!parent.AsAccessible (t, ModFlags)) {
3497                                 Report.Error (52, Location,
3498                                               "Inconsistent accessibility: field type `" +
3499                                               TypeManager.CSharpName (t) + "' is less " +
3500                                               "accessible than field `" + Name + "'");
3501                                 return false;
3502                         }
3503
3504                         if (RootContext.WarningLevel > 1){
3505                                 Type ptype = parent.TypeBuilder.BaseType;
3506
3507                                 // ptype is only null for System.Object while compiling corlib.
3508                                 if (ptype != null){
3509                                         TypeContainer.FindMembers (
3510                                                 ptype, MemberTypes.Method,
3511                                                 BindingFlags.Public |
3512                                                 BindingFlags.Static | BindingFlags.Instance,
3513                                                 System.Type.FilterName, Name);
3514                                 }
3515                         }
3516
3517                         if ((ModFlags & Modifiers.VOLATILE) != 0){
3518                                 if (!t.IsClass){
3519                                         Type vt = t;
3520                                         
3521                                         if (TypeManager.IsEnumType (vt))
3522                                                 vt = TypeManager.EnumToUnderlying (t);
3523
3524                                         if (!((vt == TypeManager.bool_type) ||
3525                                               (vt == TypeManager.sbyte_type) ||
3526                                               (vt == TypeManager.byte_type) ||
3527                                               (vt == TypeManager.short_type) ||    
3528                                               (vt == TypeManager.ushort_type) ||
3529                                               (vt == TypeManager.int32_type) ||    
3530                                               (vt == TypeManager.uint32_type) ||    
3531                                               (vt == TypeManager.char_type) ||    
3532                                               (vt == TypeManager.float_type))){
3533                                                 Report.Error (
3534                                                         677, Location, parent.MakeName (Name) +
3535                                                         " A volatile field can not be of type `" +
3536                                                         TypeManager.CSharpName (vt) + "'");
3537                                                 return false;
3538                                         }
3539                                 }
3540                         }
3541
3542                         FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3543
3544                         if (parent is Struct && 
3545                             ((fa & FieldAttributes.Static) == 0) &&
3546                             t == parent.TypeBuilder &&
3547                             !TypeManager.IsBuiltinType (t)){
3548                                 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name + 
3549                                               "' causes a cycle in the structure layout");
3550                                 return false;
3551                         }
3552                         FieldBuilder = parent.TypeBuilder.DefineField (
3553                                 Name, t, Modifiers.FieldAttr (ModFlags));
3554
3555                         TypeManager.RegisterFieldBase (FieldBuilder, this);
3556                         return true;
3557                 }
3558
3559                 public void Emit (TypeContainer tc)
3560                 {
3561                         EmitContext ec = new EmitContext (tc, Location, null,
3562                                                           FieldBuilder.FieldType, ModFlags);
3563
3564                         Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
3565                 }
3566         }
3567
3568         //
3569         // `set' and `get' accessors are represented with an Accessor.
3570         // 
3571         public class Accessor {
3572                 //
3573                 // Null if the accessor is empty, or a Block if not
3574                 //
3575                 public Block Block;
3576                 public Attributes OptAttributes;
3577                 
3578                 public Accessor (Block b, Attributes attrs)
3579                 {
3580                         Block = b;
3581                         OptAttributes = attrs;
3582                 }
3583         }
3584
3585         //
3586         // Properties and Indexers both generate PropertyBuilders, we use this to share 
3587         // their common bits.
3588         //
3589         abstract public class PropertyBase : MethodCore {
3590                 public Accessor Get, Set;
3591                 public PropertyBuilder PropertyBuilder;
3592                 public MethodBuilder GetBuilder, SetBuilder;
3593                 public MethodData GetData, SetData;
3594
3595                 protected EmitContext ec;
3596
3597                 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3598                                      Parameters parameters, Accessor get_block, Accessor set_block,
3599                                      Attributes attrs, Location loc)
3600                         : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3601                 {
3602                         Get = get_block;
3603                         Set = set_block;
3604                 }
3605
3606                 protected override bool DoDefine (TypeContainer parent)
3607                 {
3608                         if (!base.DoDefine (parent))
3609                                 return false;
3610
3611                         ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3612
3613                         return true;
3614                 }
3615
3616                 //
3617                 // Checks our base implementation if any
3618                 //
3619                 protected override bool CheckBase (TypeContainer parent)
3620                 {
3621                         // Check whether arguments were correct.
3622                         if (!DoDefineParameters (parent))
3623                                 return false;
3624
3625                         if (IsExplicitImpl)
3626                                 return true;
3627
3628                         string report_name;
3629                         MethodSignature ms, base_ms;
3630                         if (this is Indexer) {
3631                                 string name, base_name;
3632
3633                                 report_name = "this";
3634                                 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3635                                 ms = new MethodSignature (name, null, ParameterTypes);
3636                                 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3637                                 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3638                         } else {
3639                                 report_name = Name;
3640                                 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3641                         }
3642
3643                         //
3644                         // Verify if the parent has a type with the same name, and then
3645                         // check whether we have to create a new slot for it or not.
3646                         //
3647                         Type ptype = parent.TypeBuilder.BaseType;
3648
3649                         // ptype is only null for System.Object while compiling corlib.
3650                         if (ptype == null) {
3651                                 if ((ModFlags & Modifiers.NEW) != 0)
3652                                         WarningNotHiding (parent);
3653
3654                                 return true;
3655                         }
3656
3657                         MemberList props_this;
3658
3659                         props_this = TypeContainer.FindMembers (
3660                                 parent.TypeBuilder, MemberTypes.Property,
3661                                 BindingFlags.NonPublic | BindingFlags.Public |
3662                                 BindingFlags.Static | BindingFlags.Instance |
3663                                 BindingFlags.DeclaredOnly,
3664                                 MethodSignature.method_signature_filter, ms);
3665
3666                         if (props_this.Count > 0) {
3667                                 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3668                                               "already defines a member called `" + report_name + "' " +
3669                                               "with the same parameter types");
3670                                 return false;
3671                         }
3672
3673                         MemberList mi_props;
3674
3675                         mi_props = TypeContainer.FindMembers (
3676                                 ptype, MemberTypes.Property,
3677                                 BindingFlags.NonPublic | BindingFlags.Public |
3678                                 BindingFlags.Instance | BindingFlags.Static,
3679                                 MethodSignature.inheritable_method_signature_filter, base_ms);
3680
3681                         if (mi_props.Count > 0){
3682                                 PropertyInfo parent_property = (PropertyInfo) mi_props [0];
3683                                 string name = parent_property.DeclaringType.Name + "." +
3684                                         parent_property.Name;
3685
3686                                 MethodInfo get, set, parent_method;
3687                                 get = parent_property.GetGetMethod (true);
3688                                 set = parent_property.GetSetMethod (true);
3689
3690                                 if (get != null)
3691                                         parent_method = get;
3692                                 else if (set != null)
3693                                         parent_method = set;
3694                                 else
3695                                         throw new Exception ("Internal error!");
3696
3697                                 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
3698                                         return false;
3699
3700                                 if ((ModFlags & Modifiers.NEW) == 0) {
3701                                         Type parent_type = TypeManager.TypeToCoreType (
3702                                                 parent_property.PropertyType);
3703
3704                                         if (parent_type != MemberType) {
3705                                                 Report.Error (
3706                                                         508, Location, parent.MakeName (Name) + ": cannot " +
3707                                                         "change return type when overriding " +
3708                                                         "inherited member " + name);
3709                                                 return false;
3710                                         }
3711                                 }
3712                         } else {
3713                                 if ((ModFlags & Modifiers.NEW) != 0)
3714                                         WarningNotHiding (parent);
3715
3716                                 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3717                                         if (this is Indexer)
3718                                                 Report.Error (115, Location,
3719                                                               parent.MakeName (Name) +
3720                                                               " no suitable indexers found to override");
3721                                         else
3722                                                 Report.Error (115, Location,
3723                                                               parent.MakeName (Name) +
3724                                                               " no suitable properties found to override");
3725                                         return false;
3726                                 }
3727                         }
3728                         return true;
3729                 }
3730
3731                 public void Emit (TypeContainer tc)
3732                 {
3733                         //
3734                         // The PropertyBuilder can be null for explicit implementations, in that
3735                         // case, we do not actually emit the ".property", so there is nowhere to
3736                         // put the attribute
3737                         //
3738                         if (PropertyBuilder != null)
3739                                 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
3740
3741                         if (GetData != null)
3742                                 GetData.Emit (tc, Get.Block, Get);
3743
3744                         if (SetData != null)
3745                                 SetData.Emit (tc, Set.Block, Set);
3746                 }
3747         }
3748                         
3749         public class Property : PropertyBase {
3750                 const int AllowedModifiers =
3751                         Modifiers.NEW |
3752                         Modifiers.PUBLIC |
3753                         Modifiers.PROTECTED |
3754                         Modifiers.INTERNAL |
3755                         Modifiers.PRIVATE |
3756                         Modifiers.STATIC |
3757                         Modifiers.SEALED |
3758                         Modifiers.OVERRIDE |
3759                         Modifiers.ABSTRACT |
3760                         Modifiers.UNSAFE |
3761                         Modifiers.EXTERN |
3762                         Modifiers.VIRTUAL;
3763
3764                 public Property (Expression type, string name, int mod_flags,
3765                                  Accessor get_block, Accessor set_block,
3766                                  Attributes attrs, Location loc)
3767                         : base (type, name, mod_flags, AllowedModifiers,
3768                                 Parameters.EmptyReadOnlyParameters,
3769                                 get_block, set_block, attrs, loc)
3770                 {
3771                 }
3772
3773                 public override bool Define (TypeContainer parent)
3774                 {
3775                         if (!DoDefine (parent))
3776                                 return false;
3777
3778                         if (!CheckBase (parent))
3779                                 return false;
3780
3781                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3782
3783                         if (Get != null) {
3784                                 Type [] parameters = TypeManager.NoTypes;
3785
3786                                 InternalParameters ip = new InternalParameters (
3787                                         parent, Parameters.EmptyReadOnlyParameters);
3788
3789                                 GetData = new MethodData (this, "get", MemberType,
3790                                                           parameters, ip, CallingConventions.Standard,
3791                                                           Get.OptAttributes, ModFlags, flags, false);
3792                                 
3793                                 if (!GetData.Define (parent))
3794                                         return false;
3795
3796                                 GetBuilder = GetData.MethodBuilder;
3797                         }
3798
3799                         if (Set != null) {
3800                                 Type [] parameters = new Type [1];
3801                                 parameters [0] = MemberType;
3802
3803                                 Parameter [] parms = new Parameter [1];
3804                                 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3805                                 InternalParameters ip = new InternalParameters (
3806                                         parent, new Parameters (parms, null, Location));
3807
3808                                 SetData = new MethodData (this, "set", TypeManager.void_type,
3809                                                           parameters, ip, CallingConventions.Standard,
3810                                                           Set.OptAttributes, ModFlags, flags, false);
3811
3812                                 if (!SetData.Define (parent))
3813                                         return false;
3814
3815                                 SetBuilder = SetData.MethodBuilder;
3816                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
3817                         }
3818
3819                         // FIXME - PropertyAttributes.HasDefault ?
3820                         
3821                         PropertyAttributes prop_attr =
3822                         PropertyAttributes.RTSpecialName |
3823                         PropertyAttributes.SpecialName;
3824
3825                         if (!IsExplicitImpl){
3826                                 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3827                                         Name, prop_attr, MemberType, null);
3828                                 
3829                                 if (Get != null)
3830                                         PropertyBuilder.SetGetMethod (GetBuilder);
3831                                 
3832                                 if (Set != null)
3833                                         PropertyBuilder.SetSetMethod (SetBuilder);
3834
3835                                 //
3836                                 // HACK for the reasons exposed above
3837                                 //
3838                                 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3839                                         Report.Error (
3840                                                 111, Location,
3841                                                 "Class `" + parent.Name +
3842                                                 "' already contains a definition for the property `" +
3843                                                 Name + "'");
3844                                         return false;
3845                                 }
3846                         }
3847                         return true;
3848                 }
3849         }
3850
3851         /// </summary>
3852         ///  Gigantic workaround  for lameness in SRE follows :
3853         ///  This class derives from EventInfo and attempts to basically
3854         ///  wrap around the EventBuilder so that FindMembers can quickly
3855         ///  return this in it search for members
3856         /// </summary>
3857         public class MyEventBuilder : EventInfo {
3858                 
3859                 //
3860                 // We use this to "point" to our Builder which is
3861                 // not really a MemberInfo
3862                 //
3863                 EventBuilder MyBuilder;
3864                 
3865                 //
3866                 // We "catch" and wrap these methods
3867                 //
3868                 MethodInfo raise, remove, add;
3869
3870                 EventAttributes attributes;
3871                 Type declaring_type, reflected_type, event_type;
3872                 string name;
3873
3874                 Event my_event;
3875
3876                 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3877                 {
3878                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3879
3880                         // And now store the values in our own fields.
3881                         
3882                         declaring_type = type_builder;
3883
3884                         reflected_type = type_builder;
3885                         
3886                         attributes = event_attr;
3887                         this.name = name;
3888                         my_event = ev;
3889                         this.event_type = event_type;
3890                 }
3891                 
3892                 //
3893                 // Methods that you have to override.  Note that you only need 
3894                 // to "implement" the variants that take the argument (those are
3895                 // the "abstract" methods, the others (GetAddMethod()) are 
3896                 // regular.
3897                 //
3898                 public override MethodInfo GetAddMethod (bool nonPublic)
3899                 {
3900                         return add;
3901                 }
3902                 
3903                 public override MethodInfo GetRemoveMethod (bool nonPublic)
3904                 {
3905                         return remove;
3906                 }
3907                 
3908                 public override MethodInfo GetRaiseMethod (bool nonPublic)
3909                 {
3910                         return raise;
3911                 }
3912                 
3913                 //
3914                 // These methods make "MyEventInfo" look like a Builder
3915                 //
3916                 public void SetRaiseMethod (MethodBuilder raiseMethod)
3917                 {
3918                         raise = raiseMethod;
3919                         MyBuilder.SetRaiseMethod (raiseMethod);
3920                 }
3921
3922                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3923                 {
3924                         remove = removeMethod;
3925                         MyBuilder.SetRemoveOnMethod (removeMethod);
3926                 }
3927
3928                 public void SetAddOnMethod (MethodBuilder addMethod)
3929                 {
3930                         add = addMethod;
3931                         MyBuilder.SetAddOnMethod (addMethod);
3932                 }
3933
3934                 public void SetCustomAttribute (CustomAttributeBuilder cb)
3935                 {
3936                         MyBuilder.SetCustomAttribute (cb);
3937                 }
3938                 
3939                 public override object [] GetCustomAttributes (bool inherit)
3940                 {
3941                         // FIXME : There's nothing which can be seemingly done here because
3942                         // we have no way of getting at the custom attribute objects of the
3943                         // EventBuilder !
3944                         return null;
3945                 }
3946
3947                 public override object [] GetCustomAttributes (Type t, bool inherit)
3948                 {
3949                         // FIXME : Same here !
3950                         return null;
3951                 }
3952
3953                 public override bool IsDefined (Type t, bool b)
3954                 {
3955                         return true;
3956                 }
3957
3958                 public override EventAttributes Attributes {
3959                         get {
3960                                 return attributes;
3961                         }
3962                 }
3963
3964                 public override string Name {
3965                         get {
3966                                 return name;
3967                         }
3968                 }
3969
3970                 public override Type DeclaringType {
3971                         get {
3972                                 return declaring_type;
3973                         }
3974                 }
3975
3976                 public override Type ReflectedType {
3977                         get {
3978                                 return reflected_type;
3979                         }
3980                 }
3981
3982                 public Type EventType {
3983                         get {
3984                                 return event_type;
3985                         }
3986                 }
3987                 
3988                 public void SetUsed ()
3989                 {
3990                         if (my_event != null)
3991                                 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
3992                 }
3993         }
3994         
3995         public class Event : FieldBase {
3996                 const int AllowedModifiers =
3997                         Modifiers.NEW |
3998                         Modifiers.PUBLIC |
3999                         Modifiers.PROTECTED |
4000                         Modifiers.INTERNAL |
4001                         Modifiers.PRIVATE |
4002                         Modifiers.STATIC |
4003                         Modifiers.VIRTUAL |
4004                         Modifiers.SEALED |
4005                         Modifiers.OVERRIDE |
4006                         Modifiers.UNSAFE |
4007                         Modifiers.ABSTRACT;
4008
4009                 public readonly Accessor  Add;
4010                 public readonly Accessor  Remove;
4011                 public MyEventBuilder     EventBuilder;
4012
4013                 MethodBuilder AddBuilder, RemoveBuilder;
4014                 MethodData AddData, RemoveData;
4015                 
4016                 public Event (Expression type, string name, Object init, int mod, Accessor add,
4017                               Accessor remove, Attributes attrs, Location loc)
4018                         : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4019                 {
4020                         Add = add;
4021                         Remove = remove;
4022                 }
4023
4024                 public override bool Define (TypeContainer parent)
4025                 {
4026                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4027
4028                         if (!DoDefine (parent))
4029                                 return false;
4030
4031                         if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4032                                 Report.Error (66, Location, "'" + parent.Name + "." + Name +
4033                                               "' : event must be of a delegate type");
4034                                 return false;
4035                         }
4036
4037                         Type [] parameter_types = new Type [1];
4038                         parameter_types [0] = MemberType;
4039
4040                         Parameter [] parms = new Parameter [1];
4041                         parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4042                         InternalParameters ip = new InternalParameters (
4043                                 parent, new Parameters (parms, null, Location)); 
4044
4045                         if (!CheckBase (parent))
4046                                 return false;
4047
4048                         //
4049                         // Now define the accessors
4050                         //
4051                         AddData = new MethodData (this, "add", TypeManager.void_type,
4052                                                   parameter_types, ip, CallingConventions.Standard,
4053                                                   (Add != null) ? Add.OptAttributes : null,
4054                                                   ModFlags, flags, false);
4055
4056                         if (!AddData.Define (parent))
4057                                 return false;
4058
4059                         AddBuilder = AddData.MethodBuilder;
4060                         AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4061
4062                         RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4063                                                      parameter_types, ip, CallingConventions.Standard,
4064                                                      (Remove != null) ? Remove.OptAttributes : null,
4065                                                      ModFlags, flags, false);
4066
4067                         if (!RemoveData.Define (parent))
4068                                 return false;
4069
4070                         RemoveBuilder = RemoveData.MethodBuilder;
4071                         RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4072
4073                         if (!IsExplicitImpl){
4074                                 EventBuilder = new MyEventBuilder (this,
4075                                         parent.TypeBuilder, Name, e_attr, MemberType);
4076                                         
4077                                 if (Add == null && Remove == null) {
4078                                         FieldBuilder = parent.TypeBuilder.DefineField (
4079                                                 Name, MemberType,
4080                                                 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4081                                         TypeManager.RegisterPrivateFieldOfEvent (
4082                                                 (EventInfo) EventBuilder, FieldBuilder);
4083                                         TypeManager.RegisterFieldBase (FieldBuilder, this);
4084                                 }
4085                         
4086                                 EventBuilder.SetAddOnMethod (AddBuilder);
4087                                 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4088
4089                                 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4090                                         Report.Error (111, Location,
4091                                                       "Class `" + parent.Name +
4092                                                       "' already contains a definition for the event `" +
4093                                                       Name + "'");
4094                                         return false;
4095                                 }
4096                         }
4097                         
4098                         return true;
4099                 }
4100
4101                 void EmitDefaultMethod (EmitContext ec, bool is_add)
4102                 {
4103                         ILGenerator ig = ec.ig;
4104                         MethodInfo method = null;
4105                         
4106                         if (is_add)
4107                                 method = TypeManager.delegate_combine_delegate_delegate;
4108                         else
4109                                 method = TypeManager.delegate_remove_delegate_delegate;
4110
4111                         if ((ModFlags & Modifiers.STATIC) != 0) {
4112                                 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4113                                 ig.Emit (OpCodes.Ldarg_0);
4114                                 ig.Emit (OpCodes.Call, method);
4115                                 ig.Emit (OpCodes.Castclass, MemberType);
4116                                 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4117                         } else {
4118                                 ig.Emit (OpCodes.Ldarg_0);
4119                                 ig.Emit (OpCodes.Ldarg_0);
4120                                 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4121                                 ig.Emit (OpCodes.Ldarg_1);
4122                                 ig.Emit (OpCodes.Call, method);
4123                                 ig.Emit (OpCodes.Castclass, MemberType);
4124                                 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4125                         }
4126                         ig.Emit (OpCodes.Ret);
4127                 }
4128
4129                 public void Emit (TypeContainer tc)
4130                 {
4131                         EmitContext ec;
4132
4133                         ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4134                         Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
4135
4136                         if (Add != null)
4137                                 AddData.Emit (tc, Add.Block, Add);
4138                         else {
4139                                 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4140                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4141                                 EmitDefaultMethod (ec, true);
4142                         }
4143
4144                         if (Remove != null)
4145                                 RemoveData.Emit (tc, Remove.Block, Remove);
4146                         else {
4147                                 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4148                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4149                                 EmitDefaultMethod (ec, false);
4150                         }
4151                 }
4152                 
4153         }
4154
4155         //
4156         // FIXME: This does not handle:
4157         //
4158         //   int INTERFACENAME [ args ]
4159         //   Does not 
4160         //
4161         // Only:
4162         // 
4163         // int this [ args ]
4164  
4165         public class Indexer : PropertyBase {
4166
4167                 const int AllowedModifiers =
4168                         Modifiers.NEW |
4169                         Modifiers.PUBLIC |
4170                         Modifiers.PROTECTED |
4171                         Modifiers.INTERNAL |
4172                         Modifiers.PRIVATE |
4173                         Modifiers.VIRTUAL |
4174                         Modifiers.SEALED |
4175                         Modifiers.OVERRIDE |
4176                         Modifiers.UNSAFE |
4177                         Modifiers.EXTERN |
4178                         Modifiers.ABSTRACT;
4179
4180                 public string IndexerName;
4181                 public string InterfaceIndexerName;
4182
4183                 //
4184                 // Are we implementing an interface ?
4185                 //
4186                 bool IsImplementing = false;
4187                 
4188                 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4189                                 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4190                         : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4191                                 attrs, loc)
4192                 {
4193                         ExplicitInterfaceName = int_type;
4194                 }
4195
4196                 public override bool Define (TypeContainer parent)
4197                 {
4198                         PropertyAttributes prop_attr =
4199                                 PropertyAttributes.RTSpecialName |
4200                                 PropertyAttributes.SpecialName;
4201                         
4202                         if (!DoDefine (parent))
4203                                 return false;
4204
4205                         IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4206                         if (IndexerName == null)
4207                                 IndexerName = "Item";
4208                         else if (IsExplicitImpl)
4209                                 Report.Error (592, Location,
4210                                               "Attribute 'IndexerName' is not valid on this declaration " +
4211                                               "type. It is valid on `property' declarations only.");
4212
4213                         ShortName = IndexerName;
4214                         if (IsExplicitImpl) {
4215                                 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4216                                 Name = InterfaceType.FullName + "." + IndexerName;
4217                         } else {
4218                                 InterfaceIndexerName = IndexerName;
4219                                 Name = ShortName;
4220                         }
4221
4222                         if (!CheckBase (parent))
4223                                 return false;
4224
4225                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4226                         if (Get != null){
4227                                 InternalParameters ip = new InternalParameters (parent, Parameters);
4228
4229                                 GetData = new MethodData (this, "get", MemberType,
4230                                                           ParameterTypes, ip, CallingConventions.Standard,
4231                                                           Get.OptAttributes, ModFlags, flags, false);
4232
4233                                 if (!GetData.Define (parent))
4234                                         return false;
4235
4236                                 GetBuilder = GetData.MethodBuilder;
4237                         }
4238                         
4239                         if (Set != null){
4240                                 int top = ParameterTypes.Length;
4241                                 Type [] set_pars = new Type [top + 1];
4242                                 ParameterTypes.CopyTo (set_pars, 0);
4243                                 set_pars [top] = MemberType;
4244
4245                                 Parameter [] fixed_parms = Parameters.FixedParameters;
4246
4247                                 if (fixed_parms == null){
4248                                         throw new Exception ("We currently do not support only array arguments in an indexer");
4249                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4250                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4251                                         //
4252                                         // Here is the problem: the `value' parameter has
4253                                         // to come *after* the array parameter in the declaration
4254                                         // like this:
4255                                         // X (object [] x, Type value)
4256                                         // .param [0]
4257                                         //
4258                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4259                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4260                                         
4261                                 }
4262                                 
4263                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4264
4265
4266                                 fixed_parms.CopyTo (tmp, 0);
4267                                 tmp [fixed_parms.Length] = new Parameter (
4268                                         Type, "value", Parameter.Modifier.NONE, null);
4269
4270                                 Parameters set_formal_params = new Parameters (tmp, null, Location);
4271                                 
4272                                 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4273
4274                                 SetData = new MethodData (this, "set", TypeManager.void_type,
4275                                                           set_pars, ip, CallingConventions.Standard,
4276                                                           Set.OptAttributes, ModFlags, flags, false);
4277
4278                                 if (!SetData.Define (parent))
4279                                         return false;
4280
4281                                 SetBuilder = SetData.MethodBuilder;
4282                         }
4283
4284                         //
4285                         // Now name the parameters
4286                         //
4287                         Parameter [] p = Parameters.FixedParameters;
4288                         if (p != null) {
4289                                 int i;
4290                                 
4291                                 for (i = 0; i < p.Length; ++i) {
4292                                         if (Get != null)
4293                                                 GetBuilder.DefineParameter (
4294                                                         i + 1, p [i].Attributes, p [i].Name);
4295
4296                                         if (Set != null)
4297                                                 SetBuilder.DefineParameter (
4298                                                         i + 1, p [i].Attributes, p [i].Name);
4299                                 }
4300
4301                                 if (Set != null)
4302                                         SetBuilder.DefineParameter (
4303                                                 i + 1, ParameterAttributes.None, "value");
4304                                         
4305                                 if (i != ParameterTypes.Length) {
4306                                         Parameter array_param = Parameters.ArrayParameter;
4307                                         SetBuilder.DefineParameter (
4308                                                 i + 1, array_param.Attributes, array_param.Name);
4309                                 }
4310                         }
4311
4312                         if (GetData != null)
4313                                 IsImplementing = GetData.IsImplementing;
4314                         else if (SetData != null)
4315                                 IsImplementing = SetData.IsImplementing;
4316
4317                         //
4318                         // Define the PropertyBuilder if one of the following conditions are met:
4319                         // a) we're not implementing an interface indexer.
4320                         // b) the indexer has a different IndexerName and this is no
4321                         //    explicit interface implementation.
4322                         //
4323                         if (!IsExplicitImpl) {
4324                                 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4325                                         IndexerName, prop_attr, MemberType, ParameterTypes);
4326
4327                                 if (GetData != null)
4328                                         PropertyBuilder.SetGetMethod (GetBuilder);
4329
4330                                 if (SetData != null)
4331                                         PropertyBuilder.SetSetMethod (SetBuilder);
4332                                 
4333                                 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4334                                                              ParameterTypes);
4335                         }
4336
4337                         return true;
4338                 }
4339         }
4340
4341         public class Operator : MemberCore {
4342
4343                 const int AllowedModifiers =
4344                         Modifiers.PUBLIC |
4345                         Modifiers.UNSAFE |
4346                         Modifiers.EXTERN |
4347                         Modifiers.STATIC;
4348
4349                 const int RequiredModifiers =
4350                         Modifiers.PUBLIC |
4351                         Modifiers.STATIC;
4352
4353                 public enum OpType : byte {
4354
4355                         // Unary operators
4356                         LogicalNot,
4357                         OnesComplement,
4358                         Increment,
4359                         Decrement,
4360                         True,
4361                         False,
4362
4363                         // Unary and Binary operators
4364                         Addition,
4365                         Subtraction,
4366
4367                         UnaryPlus,
4368                         UnaryNegation,
4369                         
4370                         // Binary operators
4371                         Multiply,
4372                         Division,
4373                         Modulus,
4374                         BitwiseAnd,
4375                         BitwiseOr,
4376                         ExclusiveOr,
4377                         LeftShift,
4378                         RightShift,
4379                         Equality,
4380                         Inequality,
4381                         GreaterThan,
4382                         LessThan,
4383                         GreaterThanOrEqual,
4384                         LessThanOrEqual,
4385
4386                         // Implicit and Explicit
4387                         Implicit,
4388                         Explicit
4389                 };
4390
4391                 public readonly OpType OperatorType;
4392                 public readonly Expression ReturnType;
4393                 public readonly Expression FirstArgType, SecondArgType;
4394                 public readonly string FirstArgName, SecondArgName;
4395                 public readonly Block  Block;
4396                 public Attributes      OptAttributes;
4397                 public MethodBuilder   OperatorMethodBuilder;
4398                 
4399                 public string MethodName;
4400                 public Method OperatorMethod;
4401
4402                 public Operator (OpType type, Expression ret_type, int flags,
4403                                  Expression arg1type, string arg1name,
4404                                  Expression arg2type, string arg2name,
4405                                  Block block, Attributes attrs, Location loc)
4406                         : base ("", loc)
4407                 {
4408                         OperatorType = type;
4409                         ReturnType = ret_type;
4410                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4411                         FirstArgType = arg1type;
4412                         FirstArgName = arg1name;
4413                         SecondArgType = arg2type;
4414                         SecondArgName = arg2name;
4415                         Block = block;
4416                         OptAttributes = attrs;
4417                 }
4418
4419                 string Prototype (TypeContainer parent)
4420                 {
4421                         return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4422                                 SecondArgType + ")";
4423                 }
4424                 
4425                 public override bool Define (TypeContainer parent)
4426                 {
4427                         int length = 1;
4428                         MethodName = "op_" + OperatorType;
4429                         
4430                         if (SecondArgType != null)
4431                                 length = 2;
4432                         
4433                         Parameter [] param_list = new Parameter [length];
4434
4435                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4436                                 Report.Error (
4437                                         558, Location, 
4438                                         "User defined operators `" +
4439                                         Prototype (parent) +
4440                                         "' must be declared static and public");
4441                                 return false;
4442                         }
4443
4444                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
4445                                                        Parameter.Modifier.NONE, null);
4446                         if (SecondArgType != null)
4447                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4448                                                                Parameter.Modifier.NONE, null);
4449                         
4450                         OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4451                                                      new Parameters (param_list, null, Location),
4452                                                      OptAttributes, Mono.CSharp.Location.Null);
4453
4454                         OperatorMethod.IsOperator = true;                       
4455                         OperatorMethod.Define (parent);
4456
4457                         if (OperatorMethod.MethodBuilder == null)
4458                                 return false;
4459                         
4460                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4461
4462                         Type [] param_types = OperatorMethod.ParameterTypes;
4463                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
4464                         Type return_type = OperatorMethod.GetReturnType ();
4465                         Type first_arg_type = param_types [0];
4466
4467                         // Rules for conversion operators
4468                         
4469                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4470                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
4471                                         Report.Error (
4472                                                 555, Location,
4473                                                 "User-defined conversion cannot take an object of the " +
4474                                                 "enclosing type and convert to an object of the enclosing" +
4475                                                 " type");
4476                                         return false;
4477                                 }
4478                                 
4479                                 if (first_arg_type != declaring_type && return_type != declaring_type){
4480                                         Report.Error (
4481                                                 556, Location, 
4482                                                 "User-defined conversion must convert to or from the " +
4483                                                 "enclosing type");
4484                                         return false;
4485                                 }
4486                                 
4487                                 if (first_arg_type == TypeManager.object_type ||
4488                                     return_type == TypeManager.object_type){
4489                                         Report.Error (
4490                                                 -8, Location,
4491                                                 "User-defined conversion cannot convert to or from " +
4492                                                 "object type");
4493                                         return false;
4494                                 }
4495
4496                                 if (first_arg_type.IsInterface || return_type.IsInterface){
4497                                         Report.Error (
4498                                                 552, Location,
4499                                                 "User-defined conversion cannot convert to or from an " +
4500                                                 "interface type");
4501                                         return false;
4502                                 }
4503                                 
4504                                 if (first_arg_type.IsSubclassOf (return_type) ||
4505                                     return_type.IsSubclassOf (first_arg_type)){
4506                                         Report.Error (
4507                                                 -10, Location,
4508                                                 "User-defined conversion cannot convert between types " +
4509                                                 "that derive from each other");
4510                                         return false;
4511                                 }
4512                         } else if (SecondArgType == null) {
4513                                 // Checks for Unary operators
4514                                 
4515                                 if (first_arg_type != declaring_type){
4516                                         Report.Error (
4517                                                 562, Location,
4518                                                 "The parameter of a unary operator must be the " +
4519                                                 "containing type");
4520                                         return false;
4521                                 }
4522                                 
4523                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4524                                         if (return_type != declaring_type){
4525                                                 Report.Error (
4526                                                         559, Location,
4527                                                         "The parameter and return type for ++ and -- " +
4528                                                         "must be the containing type");
4529                                                 return false;
4530                                         }
4531                                         
4532                                 }
4533                                 
4534                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4535                                         if (return_type != TypeManager.bool_type){
4536                                                 Report.Error (
4537                                                         215, Location,
4538                                                         "The return type of operator True or False " +
4539                                                         "must be bool");
4540                                                 return false;
4541                                         }
4542                                 }
4543                                 
4544                         } else {
4545                                 // Checks for Binary operators
4546                                 
4547                                 if (first_arg_type != declaring_type &&
4548                                     param_types [1] != declaring_type){
4549                                         Report.Error (
4550                                                 563, Location,
4551                                                 "One of the parameters of a binary operator must " +
4552                                                 "be the containing type");
4553                                         return false;
4554                                 }
4555                         }
4556
4557                         return true;
4558                 }
4559                 
4560                 public void Emit (TypeContainer parent)
4561                 {
4562                         EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4563                         Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes);
4564
4565                         //
4566                         // abstract or extern methods have no bodies
4567                         //
4568                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4569                                 return;
4570                         
4571                         OperatorMethod.Block = Block;
4572                         OperatorMethod.Emit (parent);
4573                 }
4574
4575                 public static string GetName (OpType ot)
4576                 {
4577                         switch (ot){
4578                         case OpType.LogicalNot:
4579                                 return "!";
4580                         case OpType.OnesComplement:
4581                                 return "~";
4582                         case OpType.Increment:
4583                                 return "++";
4584                         case OpType.Decrement:
4585                                 return "--";
4586                         case OpType.True:
4587                                 return "true";
4588                         case OpType.False:
4589                                 return "false";
4590                         case OpType.Addition:
4591                                 return "+";
4592                         case OpType.Subtraction:
4593                                 return "-";
4594                         case OpType.UnaryPlus:
4595                                 return "+";
4596                         case OpType.UnaryNegation:
4597                                 return "-";
4598                         case OpType.Multiply:
4599                                 return "*";
4600                         case OpType.Division:
4601                                 return "/";
4602                         case OpType.Modulus:
4603                                 return "%";
4604                         case OpType.BitwiseAnd:
4605                                 return "&";
4606                         case OpType.BitwiseOr:
4607                                 return "|";
4608                         case OpType.ExclusiveOr:
4609                                 return "^";
4610                         case OpType.LeftShift:
4611                                 return "<<";
4612                         case OpType.RightShift:
4613                                 return ">>";
4614                         case OpType.Equality:
4615                                 return "==";
4616                         case OpType.Inequality:
4617                                 return "!=";
4618                         case OpType.GreaterThan:
4619                                 return ">";
4620                         case OpType.LessThan:
4621                                 return "<";
4622                         case OpType.GreaterThanOrEqual:
4623                                 return ">=";
4624                         case OpType.LessThanOrEqual:
4625                                 return "<=";
4626                         case OpType.Implicit:
4627                                 return "implicit";
4628                         case OpType.Explicit:
4629                                 return "explicit";
4630                         default: return "";
4631                         }
4632                 }
4633                 
4634                 public override string ToString ()
4635                 {
4636                         Type return_type = OperatorMethod.GetReturnType();
4637                         Type [] param_types = OperatorMethod.ParameterTypes;
4638                         
4639                         if (SecondArgType == null)
4640                                 return String.Format (
4641                                         "{0} operator {1}({2})",
4642                                         TypeManager.CSharpName (return_type),
4643                                         GetName (OperatorType),
4644                                         param_types [0]);
4645                         else
4646                                 return String.Format (
4647                                         "{0} operator {1}({2}, {3})",
4648                                         TypeManager.CSharpName (return_type),
4649                                         GetName (OperatorType),
4650                                         param_types [0], param_types [1]);
4651                 }
4652         }
4653
4654         //
4655         // This is used to compare method signatures
4656         //
4657         struct MethodSignature {
4658                 public string Name;
4659                 public Type RetType;
4660                 public Type [] Parameters;
4661                 
4662                 /// <summary>
4663                 ///    This delegate is used to extract methods which have the
4664                 ///    same signature as the argument
4665                 /// </summary>
4666                 public static MemberFilter method_signature_filter;
4667
4668                 /// <summary>
4669                 ///   This delegate is used to extract inheritable methods which
4670                 ///   have the same signature as the argument.  By inheritable,
4671                 ///   this means that we have permissions to override the method
4672                 ///   from the current assembly and class
4673                 /// </summary>
4674                 public static MemberFilter inheritable_method_signature_filter;
4675
4676                 static MethodSignature ()
4677                 {
4678                         method_signature_filter = new MemberFilter (MemberSignatureCompare);
4679                         inheritable_method_signature_filter = new MemberFilter (
4680                                 InheritableMemberSignatureCompare);
4681                 }
4682                 
4683                 public MethodSignature (string name, Type ret_type, Type [] parameters)
4684                 {
4685                         Name = name;
4686                         RetType = ret_type;
4687
4688                         if (parameters == null)
4689                                 Parameters = TypeManager.NoTypes;
4690                         else
4691                                 Parameters = parameters;
4692                 }
4693                 
4694                 public override int GetHashCode ()
4695                 {
4696                         return Name.GetHashCode ();
4697                 }
4698
4699                 public override bool Equals (Object o)
4700                 {
4701                         MethodSignature other = (MethodSignature) o;
4702
4703                         if (other.Name != Name)
4704                                 return false;
4705
4706                         if (other.RetType != RetType)
4707                                 return false;
4708                         
4709                         if (Parameters == null){
4710                                 if (other.Parameters == null)
4711                                         return true;
4712                                 return false;
4713                         }
4714
4715                         if (other.Parameters == null)
4716                                 return false;
4717                         
4718                         int c = Parameters.Length;
4719                         if (other.Parameters.Length != c)
4720                                 return false;
4721
4722                         for (int i = 0; i < c; i++)
4723                                 if (other.Parameters [i] != Parameters [i])
4724                                         return false;
4725
4726                         return true;
4727                 }
4728
4729                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4730                 {
4731                         MethodSignature sig = (MethodSignature) filter_criteria;
4732
4733                         if (m.Name != sig.Name)
4734                                 return false;
4735
4736                         Type ReturnType;
4737                         MethodInfo mi = m as MethodInfo;
4738                         PropertyInfo pi = m as PropertyInfo;
4739
4740                         if (mi != null)
4741                                 ReturnType = mi.ReturnType;
4742                         else if (pi != null)
4743                                 ReturnType = pi.PropertyType;
4744                         else
4745                                 return false;
4746                         
4747                         //
4748                         // we use sig.RetType == null to mean `do not check the
4749                         // method return value.  
4750                         //
4751                         if (sig.RetType != null)
4752                                 if (ReturnType != sig.RetType)
4753                                         return false;
4754
4755                         Type [] args;
4756                         if (mi != null)
4757                                 args = TypeManager.GetArgumentTypes (mi);
4758                         else
4759                                 args = TypeManager.GetArgumentTypes (pi);
4760                         Type [] sigp = sig.Parameters;
4761
4762                         if (args.Length != sigp.Length)
4763                                 return false;
4764
4765                         for (int i = args.Length; i > 0; ){
4766                                 i--;
4767                                 if (args [i] != sigp [i])
4768                                         return false;
4769                         }
4770                         return true;
4771                 }
4772
4773                 //
4774                 // This filter should be used when we are requesting methods that
4775                 // we want to override.
4776                 //
4777                 // This makes a number of assumptions, for example
4778                 // that the methods being extracted are of a parent
4779                 // class (this means we know implicitly that we are
4780                 // being called to find out about members by a derived
4781                 // class).
4782                 // 
4783                 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4784                 {
4785                         if (!MemberSignatureCompare (m, filter_criteria))
4786                                 return false;
4787
4788                         MethodInfo mi;
4789                         PropertyInfo pi = m as PropertyInfo;
4790
4791                         if (pi != null) {
4792                                 mi = pi.GetGetMethod (true);
4793                                 if (mi == null)
4794                                         mi = pi.GetSetMethod (true);
4795                         } else
4796                                 mi = m as MethodInfo;
4797
4798                         if (mi == null){
4799                                 Console.WriteLine ("Nothing found");
4800                         }
4801                         
4802                         MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4803
4804                         // If only accessible to the current class.
4805                         if (prot == MethodAttributes.Private)
4806                                 return false;
4807
4808                         // If only accessible to the defining assembly or 
4809                         if (prot == MethodAttributes.FamANDAssem ||
4810                             prot == MethodAttributes.Assembly){
4811                                 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4812                                         return true;
4813                                 else
4814                                         return false;
4815                         }
4816
4817                         // Anything else (FamOrAssembly and Public) is fine
4818                         return true;
4819                 }
4820         }
4821 }