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