2002-08-15 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, IMemberFinder {
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 Define (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.Define (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                 /// <summary>
1057                 ///   This function is based by a delegate to the FindMembers routine
1058                 /// </summary>
1059                 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1060                 {
1061                         return true;
1062                 }
1063
1064                 /// <summary>
1065                 ///   This filter is used by FindMembers, and we just keep
1066                 ///   a global for the filter to `AlwaysAccept'
1067                 /// </summary>
1068                 static MemberFilter accepting_filter;
1069
1070                 
1071                 /// <summary>
1072                 ///   A member comparission method based on name only
1073                 /// </summary>
1074                 static IComparer mif_compare;
1075
1076                 static TypeContainer ()
1077                 {
1078                         accepting_filter = new MemberFilter (AlwaysAccept);
1079                         mif_compare = new MemberInfoCompare ();
1080                 }
1081                 
1082                 /// <summary>
1083                 ///   This method returns the members of this type just like Type.FindMembers would
1084                 ///   Only, we need to use this for types which are _being_ defined because MS' 
1085                 ///   implementation can't take care of that.
1086                 /// </summary>
1087                 //
1088                 // FIXME: return an empty static array instead of null, that cleans up
1089                 // some code and is consistent with some coding conventions I just found
1090                 // out existed ;-)
1091                 //
1092                 //
1093                 // Notice that in various cases we check if our field is non-null,
1094                 // something that would normally mean that there was a bug elsewhere.
1095                 //
1096                 // The problem happens while we are defining p-invoke methods, as those
1097                 // will trigger a FindMembers, but this happens before things are defined
1098                 //
1099                 // Since the whole process is a no-op, it is fine to check for null here.
1100                 //
1101                 public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1102                                                MemberFilter filter, object criteria)
1103                 {
1104                         ArrayList members = new ArrayList ();
1105                         bool priv = (bf & BindingFlags.NonPublic) != 0;
1106
1107                         if (filter == null)
1108                                 filter = accepting_filter; 
1109
1110                         if ((mt & MemberTypes.Field) != 0) {
1111                                 if (fields != null) {
1112                                         foreach (Field f in fields) {
1113                                                 if ((f.ModFlags & Modifiers.PRIVATE) != 0)
1114                                                         if (!priv)
1115                                                                 continue;
1116
1117                                                 FieldBuilder fb = f.FieldBuilder;
1118                                                 if (fb != null && filter (fb, criteria) == true)
1119                                                         members.Add (fb);
1120                                         }
1121                                 }
1122
1123                                 if (constants != null) {
1124                                         foreach (Const con in constants) {
1125                                                 if ((con.ModFlags & Modifiers.PRIVATE) != 0)
1126                                                         if (!priv)
1127                                                                 continue;
1128                                                 
1129                                                 FieldBuilder fb = con.FieldBuilder;
1130                                                 if (fb != null && filter (fb, criteria) == true)
1131                                                         members.Add (fb);
1132                                         }
1133                                 }
1134                         }
1135
1136                         if ((mt & MemberTypes.Method) != 0) {
1137                                 if (methods != null) {
1138                                         foreach (Method m in methods) {
1139                                                 if ((m.ModFlags & Modifiers.PRIVATE) != 0)
1140                                                         if (!priv)
1141                                                                 continue;
1142                                                 
1143                                                 MethodBuilder mb = m.MethodBuilder;
1144
1145                                                 if (mb != null && filter (mb, criteria) == true)
1146                                                         members.Add (mb);
1147                                         }
1148                                 }
1149
1150                                 if (operators != null){
1151                                         foreach (Operator o in operators) {
1152                                                 if ((o.ModFlags & Modifiers.PRIVATE) != 0)
1153                                                         if (!priv)
1154                                                                 continue;
1155                                                 
1156                                                 MethodBuilder ob = o.OperatorMethodBuilder;
1157                                                 if (ob != null && filter (ob, criteria) == true)
1158                                                         members.Add (ob);
1159                                         }
1160                                 }
1161
1162                                 if (properties != null){
1163                                         foreach (Property p in properties){
1164                                                 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1165                                                         if (!priv)
1166                                                                 continue;
1167                                                 
1168                                                 MethodBuilder b;
1169
1170                                                 b = p.GetBuilder;
1171                                                 if (b != null && filter (b, criteria) == true)
1172                                                         members.Add (b);
1173
1174                                                 b = p.SetBuilder;
1175                                                 if (b != null && filter (b, criteria) == true)
1176                                                         members.Add (b);
1177                                         }
1178                                 }
1179                         }
1180
1181                         if ((mt & MemberTypes.Event) != 0) {
1182                                 if (events != null)
1183                                         foreach (Event e in events) {
1184                                                 if ((e.ModFlags & Modifiers.PRIVATE) != 0)
1185                                                         if (!priv)
1186                                                                 continue;
1187
1188                                                 MemberInfo eb = e.EventBuilder;
1189                                                 if (eb != null && filter (eb, criteria) == true)
1190                                                         members.Add (e.EventBuilder);
1191                                         }
1192                         }
1193                         
1194                         if ((mt & MemberTypes.Property) != 0){
1195                                 if (properties != null)
1196                                         foreach (Property p in properties) {
1197                                                 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1198                                                         if (!priv)
1199                                                                 continue;
1200
1201                                                 MemberInfo pb = p.PropertyBuilder;
1202                                                 if (pb != null && filter (pb, criteria) == true) {
1203                                                         members.Add (p.PropertyBuilder);
1204                                                 }
1205                                         }
1206
1207                                 if (indexers != null)
1208                                         foreach (Indexer ix in indexers) {
1209                                                 if ((ix.ModFlags & Modifiers.PRIVATE) != 0)
1210                                                         if (!priv)
1211                                                                 continue;
1212
1213                                                 MemberInfo ib = ix.PropertyBuilder;
1214                                                 if (ib != null && filter (ib, criteria) == true) {
1215                                                         members.Add (ix.PropertyBuilder);
1216                                                 }
1217                                         }
1218                         }
1219                         
1220                         if ((mt & MemberTypes.NestedType) != 0) {
1221                                 if (types != null){
1222                                         foreach (TypeContainer t in types) {
1223                                                 TypeBuilder tb = t.TypeBuilder;
1224
1225                                                 if (tb != null && (filter (tb, criteria) == true))
1226                                                                 members.Add (tb);
1227                                         }
1228                                 }
1229
1230                                 if (enums != null){
1231                                         foreach (Enum en in enums){
1232                                                 TypeBuilder tb = en.TypeBuilder;
1233
1234                                                 if (tb != null && (filter (tb, criteria) == true))
1235                                                         members.Add (tb);
1236                                         }
1237                                 }
1238                                 
1239                                 if (delegates != null){
1240                                         foreach (Delegate d in delegates){
1241                                                 TypeBuilder tb = d.TypeBuilder;
1242                                                 
1243                                                 if (tb != null && (filter (tb, criteria) == true))
1244                                                         members.Add (tb);
1245                                         }
1246                                 }
1247                         }
1248
1249                         if ((mt & MemberTypes.Constructor) != 0){
1250                                 if (instance_constructors != null){
1251                                         foreach (Constructor c in instance_constructors){
1252                                                 ConstructorBuilder cb = c.ConstructorBuilder;
1253
1254                                                 if (cb != null)
1255                                                         if (filter (cb, criteria) == true)
1256                                                                 members.Add (cb);
1257                                         }
1258                                 }
1259
1260                                 if (default_static_constructor != null){
1261                                         ConstructorBuilder cb =
1262                                                 default_static_constructor.ConstructorBuilder;
1263                                         
1264                                         if (cb != null)
1265                                         if (filter (cb, criteria) == true)
1266                                                 members.Add (cb);
1267                                 }
1268                         }
1269
1270                         //
1271                         // Lookup members in parent if requested.
1272                         //
1273                         if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1274                                 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1275                                 members.AddRange (list);
1276                         }
1277
1278                         return new MemberList (members);
1279                 }
1280
1281                 
1282
1283                 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1284                                                       MemberFilter filter, object criteria)
1285                 {
1286                         TypeContainer tc = TypeManager.LookupTypeContainer (t);
1287
1288                         if (tc != null)
1289                                 return tc.FindMembers (mt, bf, filter, criteria);
1290                         else
1291                                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1292                 }
1293
1294                 //
1295                 // FindMethods will look for methods not only in the type `t', but in
1296                 // any interfaces implemented by the type.
1297                 //
1298                 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1299                                                          MemberFilter filter, object criteria)
1300                 {
1301                         return null;
1302                 }
1303
1304                 /// <summary>
1305                 ///   Emits the values for the constants
1306                 /// </summary>
1307                 public void EmitConstants ()
1308                 {
1309                         if (constants != null)
1310                                 foreach (Const con in constants)
1311                                         con.EmitConstant (this);
1312                         return;
1313                 }
1314
1315                 /// <summary>
1316                 ///   Emits the code, this step is performed after all
1317                 ///   the types, enumerations, constructors
1318                 /// </summary>
1319                 public void Emit ()
1320                 {
1321                         if (instance_constructors != null)
1322                                 foreach (Constructor c in instance_constructors)
1323                                         c.Emit (this);
1324
1325                         if (default_static_constructor != null)
1326                                 default_static_constructor.Emit (this);
1327                         
1328                         if (methods != null)
1329                                 foreach (Method m in methods)
1330                                         m.Emit (this);
1331
1332                         if (operators != null)
1333                                 foreach (Operator o in operators)
1334                                         o.Emit (this);
1335
1336                         if (properties != null)
1337                                 foreach (Property p in properties)
1338                                         p.Emit (this);
1339
1340                         if (indexers != null){
1341                                 foreach (Indexer ix in indexers)
1342                                         ix.Emit (this);
1343                                 
1344                                 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1345                                         this, IndexerName, ModFlags, Location);
1346                                 TypeBuilder.SetCustomAttribute (cb);
1347                         }
1348                         
1349                         if (fields != null)
1350                                 foreach (Field f in fields)
1351                                         f.Emit (this);
1352
1353                         if (events != null){
1354                                 foreach (Event e in Events)
1355                                         e.Emit (this);
1356                         }
1357
1358                         if (Pending != null)
1359                                 if (Pending.VerifyPendingMethods ())
1360                                         return;
1361                         
1362                         Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1363
1364                         //
1365                         // Check for internal or private fields that were never assigned
1366                         //
1367                         if (fields != null && RootContext.WarningLevel >= 3) {
1368                                 foreach (Field f in fields) {
1369                                         if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1370                                                 continue;
1371
1372                                         if (f.status == 0){
1373                                                 Report.Warning (
1374                                                         169, f.Location, "Private field " +
1375                                                         MakeName (f.Name) + " is never used");
1376                                                 continue;
1377                                         }
1378
1379                                         //
1380                                         // Only report 649 on level 4
1381                                         //
1382                                         if (RootContext.WarningLevel < 4)
1383                                                 continue;
1384
1385                                         if ((f.status & Field.Status.ASSIGNED) != 0)
1386                                                 continue;
1387
1388                                         Report.Warning (
1389                                                 649, f.Location,
1390                                                 "Field " + MakeName (f.Name) + " is never assigned " +
1391                                                 " to and will always have its default value");
1392                                 }
1393                         }
1394                         
1395 //                      if (types != null)
1396 //                              foreach (TypeContainer tc in types)
1397 //                                      tc.Emit ();
1398                 }
1399                 
1400                 public override void CloseType ()
1401                 {
1402                         try {
1403                                 if (!Created){
1404                                         Created = true;
1405                                         TypeBuilder.CreateType ();
1406                                 }
1407                         } catch (TypeLoadException){
1408                                 //
1409                                 // This is fine, the code still created the type
1410                                 //
1411 //                              Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1412 //                              Console.WriteLine (e.Message);
1413                         } catch {
1414                                 Console.WriteLine ("In type: " + Name);
1415                                 throw;
1416                         }
1417                         
1418                         if (Enums != null)
1419                                 foreach (Enum en in Enums)
1420                                         en.CloseType ();
1421
1422                         if (interface_order != null){
1423                                 foreach (Interface iface in interface_order)
1424                                         iface.CloseType ();
1425                         }
1426                         
1427                         if (Types != null){
1428                                 foreach (TypeContainer tc in Types)
1429                                         if (tc is Struct)
1430                                                 tc.CloseType ();
1431
1432                                 foreach (TypeContainer tc in Types)
1433                                         if (!(tc is Struct))
1434                                                 tc.CloseType ();
1435                         }
1436
1437                         if (Delegates != null)
1438                                 foreach (Delegate d in Delegates)
1439                                         d.CloseDelegate ();
1440                 }
1441
1442                 public string MakeName (string n)
1443                 {
1444                         return "`" + Name + "." + n + "'";
1445                 }
1446
1447                 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1448                 {
1449                         Report.Warning (
1450                                 108, l, "The keyword new is required on " + 
1451                                 MakeName (mi.Name) + " because it hides `" +
1452                                 mi.ReflectedType.Name + "." + mi.Name + "'");
1453                 }
1454
1455                 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1456                 {
1457                         Report.Warning (
1458                                 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1459                                 "inherited member, the keyword new is not required");
1460                 }
1461                 
1462                 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1463                 {
1464                         return 0;
1465                 }
1466
1467                 //
1468                 // Performs the validation on a Method's modifiers (properties have
1469                 // the same properties).
1470                 //
1471                 public bool MethodModifiersValid (int flags, string n, Location loc)
1472                 {
1473                         const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1474                         const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1475                         const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1476                         bool ok = true;
1477                         string name = MakeName (n);
1478                         
1479                         //
1480                         // At most one of static, virtual or override
1481                         //
1482                         if ((flags & Modifiers.STATIC) != 0){
1483                                 if ((flags & vao) != 0){
1484                                         Report.Error (
1485                                                 112, loc, "static method " + name + "can not be marked " +
1486                                                 "as virtual, abstract or override");
1487                                         ok = false;
1488                                 }
1489                         }
1490
1491                         if (this is Struct){
1492                                 if ((flags & va) != 0){
1493                                         Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1494                                         ok = false;
1495                                 }
1496                         }
1497
1498                         if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1499                                 Report.Error (
1500                                         113, loc, name +
1501                                         " marked as override cannot be marked as new or virtual");
1502                                 ok = false;
1503                         }
1504
1505                         //
1506                         // If the declaration includes the abstract modifier, then the
1507                         // declaration does not include static, virtual or extern
1508                         //
1509                         if ((flags & Modifiers.ABSTRACT) != 0){
1510                                 if ((flags & Modifiers.EXTERN) != 0){
1511                                         Report.Error (
1512                                                 180, loc, name + " can not be both abstract and extern");
1513                                         ok = false;
1514                                 }
1515
1516                                 if ((flags & Modifiers.VIRTUAL) != 0){
1517                                         Report.Error (
1518                                                 503, loc, name + " can not be both abstract and virtual");
1519                                         ok = false;
1520                                 }
1521
1522                                 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1523                                         Report.Error (
1524                                                 513, loc, name +
1525                                                 " is abstract but its container class is not");
1526                                         ok = false;
1527
1528                                 }
1529                         }
1530
1531                         if ((flags & Modifiers.PRIVATE) != 0){
1532                                 if ((flags & vao) != 0){
1533                                         Report.Error (
1534                                                 621, loc, name +
1535                                                 " virtual or abstract members can not be private");
1536                                         ok = false;
1537                                 }
1538                         }
1539
1540                         if ((flags & Modifiers.SEALED) != 0){
1541                                 if ((flags & Modifiers.OVERRIDE) == 0){
1542                                         Report.Error (
1543                                                 238, loc, name +
1544                                                 " cannot be sealed because it is not an override");
1545                                         ok = false;
1546                                 }
1547                         }
1548
1549                         return ok;
1550                 }
1551
1552                 // Access level of a type.
1553                 enum AccessLevel {
1554                         Public                  = 0,
1555                         ProtectedInternal       = 1,
1556                         Internal                = 2,
1557                         Protected               = 3,
1558                         Private                 = 4
1559                 }
1560
1561                 // Check whether `flags' denotes a more restricted access than `level'
1562                 // and return the new level.
1563                 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1564                 {
1565                         AccessLevel old_level = level;
1566
1567                         if ((flags & Modifiers.INTERNAL) != 0) {
1568                                 if ((flags & Modifiers.PROTECTED) != 0) {
1569                                         if ((int) level < (int) AccessLevel.ProtectedInternal)
1570                                                 level = AccessLevel.ProtectedInternal;
1571                                 } else {
1572                                         if ((int) level < (int) AccessLevel.Internal)
1573                                                 level = AccessLevel.Internal;
1574                                 }
1575                         } else if ((flags & Modifiers.PROTECTED) != 0) {
1576                                 if ((int) level < (int) AccessLevel.Protected)
1577                                         level = AccessLevel.Protected;
1578                         } else if ((flags & Modifiers.PRIVATE) != 0)
1579                                 level = AccessLevel.Private;
1580
1581                         return level;
1582                 }
1583
1584                 // Return the access level for a new member which is defined in the current
1585                 // TypeContainer with access modifiers `flags'.
1586                 AccessLevel GetAccessLevel (int flags)
1587                 {
1588                         if ((flags & Modifiers.PRIVATE) != 0)
1589                                 return AccessLevel.Private;
1590
1591                         AccessLevel level;
1592                         if (!IsTopLevel && (Parent != null))
1593                                 level = Parent.GetAccessLevel (flags);
1594                         else
1595                                 level = AccessLevel.Public;
1596
1597                         return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1598                 }
1599
1600                 // Return the access level for type `t', but don't give more access than `flags'.
1601                 static AccessLevel GetAccessLevel (Type t, int flags)
1602                 {
1603                         if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1604                                 return AccessLevel.Private;
1605
1606                         AccessLevel level;
1607                         if (TypeManager.IsBuiltinType (t))
1608                                 return AccessLevel.Public;
1609                         else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1610                                 level = GetAccessLevel (t.DeclaringType, flags);
1611                         else {
1612                                 level = CheckAccessLevel (AccessLevel.Public, flags);
1613                         }
1614
1615                         if (t.IsNestedPublic)
1616                                 return level;
1617
1618                         if (t.IsNestedAssembly || t.IsNotPublic) {
1619                                 if ((int) level < (int) AccessLevel.Internal)
1620                                         level = AccessLevel.Internal;
1621                         }
1622
1623                         if (t.IsNestedFamily) {
1624                                 if ((int) level < (int) AccessLevel.Protected)
1625                                         level = AccessLevel.Protected;
1626                         }
1627
1628                         if (t.IsNestedFamORAssem) {
1629                                 if ((int) level < (int) AccessLevel.ProtectedInternal)
1630                                         level = AccessLevel.ProtectedInternal;
1631                         }
1632
1633                         return level;
1634                 }
1635
1636                 //
1637                 // Returns true if `parent' is as accessible as the flags `flags'
1638                 // given for this member.
1639                 //
1640                 public bool AsAccessible (Type parent, int flags)
1641                 {
1642                         while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1643                                 parent = parent.GetElementType ();
1644
1645                         AccessLevel level = GetAccessLevel (flags);
1646                         AccessLevel level2 = GetAccessLevel (parent, flags);
1647
1648                         return (int) level >= (int) level2;
1649                 }
1650
1651                 Hashtable builder_and_args;
1652                 
1653                 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1654                 {
1655                         if (builder_and_args == null)
1656                                 builder_and_args = new Hashtable ();
1657                         return true;
1658                 }
1659
1660                 /// <summary>
1661                 ///   Performs checks for an explicit interface implementation.  First it
1662                 ///   checks whether the `interface_type' is a base inteface implementation.
1663                 ///   Then it checks whether `name' exists in the interface type.
1664                 /// </summary>
1665                 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1666                 {
1667                         bool found = false;
1668
1669                         if (ifaces != null){
1670                                 foreach (Type t in ifaces){
1671                                         if (t == interface_type){
1672                                                 found = true;
1673                                                 break;
1674                                         }
1675                                 }
1676                         }
1677                         
1678                         if (!found){
1679                                 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1680                                 return false;
1681                         }
1682
1683                         return true;
1684                 }
1685
1686                 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1687                 {
1688                         Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1689                 }
1690         }
1691
1692         public class Class : TypeContainer {
1693                 // <summary>
1694                 //   Modifiers allowed in a class declaration
1695                 // </summary>
1696                 public const int AllowedModifiers =
1697                         Modifiers.NEW |
1698                         Modifiers.PUBLIC |
1699                         Modifiers.PROTECTED |
1700                         Modifiers.INTERNAL |
1701                         Modifiers.PRIVATE |
1702                         Modifiers.ABSTRACT |
1703                         Modifiers.SEALED |
1704                         Modifiers.UNSAFE;
1705
1706                 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1707                         : base (parent, name, l)
1708                 {
1709                         int accmods;
1710
1711                         if (parent.Parent == null)
1712                                 accmods = Modifiers.INTERNAL;
1713                         else
1714                                 accmods = Modifiers.PRIVATE;
1715
1716                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1717                         this.attributes = attrs;
1718                 }
1719
1720                 //
1721                 // FIXME: How do we deal with the user specifying a different
1722                 // layout?
1723                 //
1724                 public override TypeAttributes TypeAttr {
1725                         get {
1726                                 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1727                         }
1728                 }
1729         }
1730
1731         public class Struct : TypeContainer {
1732                 // <summary>
1733                 //   Modifiers allowed in a struct declaration
1734                 // </summary>
1735                 public const int AllowedModifiers =
1736                         Modifiers.NEW       |
1737                         Modifiers.PUBLIC    |
1738                         Modifiers.PROTECTED |
1739                         Modifiers.INTERNAL  |
1740                         Modifiers.UNSAFE    |
1741                         Modifiers.PRIVATE;
1742
1743                 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1744                         : base (parent, name, l)
1745                 {
1746                         int accmods;
1747                         
1748                         if (parent.Parent == null)
1749                                 accmods = Modifiers.INTERNAL;
1750                         else
1751                                 accmods = Modifiers.PRIVATE;
1752                         
1753                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1754
1755                         this.ModFlags |= Modifiers.SEALED;
1756                         this.attributes = attrs;
1757                         
1758                 }
1759
1760                 //
1761                 // FIXME: Allow the user to specify a different set of attributes
1762                 // in some cases (Sealed for example is mandatory for a class,
1763                 // but what SequentialLayout can be changed
1764                 //
1765                 public override TypeAttributes TypeAttr {
1766                         get {
1767                                 return base.TypeAttr |
1768                                         TypeAttributes.SequentialLayout |
1769                                         TypeAttributes.Sealed |
1770                                         TypeAttributes.BeforeFieldInit;
1771                         }
1772                 }
1773         }
1774
1775         public abstract class MethodCore : MemberBase {
1776                 public readonly Parameters Parameters;
1777                 Block block;
1778                 
1779                 //
1780                 // Parameters, cached for semantic analysis.
1781                 //
1782                 protected InternalParameters parameter_info;
1783                 protected Type [] parameter_types;
1784
1785                 public MethodCore (Expression type, int mod, int allowed_mod, string name,
1786                                    Attributes attrs, Parameters parameters, Location loc)
1787                         : base (type, mod, allowed_mod, name, attrs, loc)
1788                 {
1789                         Parameters = parameters;
1790                 }
1791                 
1792                 //
1793                 //  Returns the System.Type array for the parameters of this method
1794                 //
1795                 public Type [] ParameterTypes {
1796                         get {
1797                                 return parameter_types;
1798                         }
1799                 }
1800
1801                 public InternalParameters ParameterInfo
1802                 {
1803                         get {
1804                                 return parameter_info;
1805                         }
1806                 }
1807                 
1808                 public Block Block {
1809                         get {
1810                                 return block;
1811                         }
1812
1813                         set {
1814                                 block = value;
1815                         }
1816                 }
1817
1818                 protected virtual bool DoDefineParameters (TypeContainer parent)
1819                 {
1820                         // Check if arguments were correct
1821                         parameter_types = Parameters.GetParameterInfo (parent);
1822                         if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
1823                                 return false;
1824
1825                         parameter_info = new InternalParameters (parent, Parameters);
1826
1827                         return true;
1828                 }
1829
1830                 public CallingConventions GetCallingConvention (bool is_class)
1831                 {
1832                         CallingConventions cc = 0;
1833                         
1834                         cc = Parameters.GetCallingConvention ();
1835
1836                         if (is_class)
1837                                 if ((ModFlags & Modifiers.STATIC) == 0)
1838                                         cc |= CallingConventions.HasThis;
1839
1840                         // FIXME: How is `ExplicitThis' used in C#?
1841                         
1842                         return cc;
1843                 }
1844
1845                 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
1846                 {
1847                         //
1848                         // Define each type attribute (in/out/ref) and
1849                         // the argument names.
1850                         //
1851                         Parameter [] p = Parameters.FixedParameters;
1852                         int i = 0;
1853                         
1854                         MethodBuilder mb = null;
1855                         ConstructorBuilder cb = null;
1856
1857                         if (builder is MethodBuilder)
1858                                 mb = (MethodBuilder) builder;
1859                         else
1860                                 cb = (ConstructorBuilder) builder;
1861
1862                         if (p != null){
1863                                 for (i = 0; i < p.Length; i++) {
1864                                         ParameterBuilder pb;
1865                                         
1866                                         if (mb == null)
1867                                                 pb = cb.DefineParameter (
1868                                                         i + 1, p [i].Attributes, p [i].Name);
1869                                         else 
1870                                                 pb = mb.DefineParameter (
1871                                                         i + 1, p [i].Attributes, p [i].Name);
1872                                         
1873                                         Attributes attr = p [i].OptAttributes;
1874                                         if (attr != null)
1875                                                 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
1876                                 }
1877                         }
1878
1879                         if (Parameters.ArrayParameter != null){
1880                                 ParameterBuilder pb;
1881                                 Parameter array_param = Parameters.ArrayParameter;
1882                                 
1883                                 if (mb == null)
1884                                         pb = cb.DefineParameter (
1885                                                 i + 1, array_param.Attributes,
1886                                                 array_param.Name);
1887                                 else
1888                                         pb = mb.DefineParameter (
1889                                                 i + 1, array_param.Attributes,
1890                                                 array_param.Name);
1891                                         
1892                                 CustomAttributeBuilder a = new CustomAttributeBuilder (
1893                                         TypeManager.cons_param_array_attribute, new object [0]);
1894                                 
1895                                 pb.SetCustomAttribute (a);
1896                         }
1897                 }
1898         }
1899         
1900         public class Method : MethodCore {
1901                 public MethodBuilder MethodBuilder;
1902                 public MethodData MethodData;
1903
1904                 /// <summary>
1905                 ///   Modifiers allowed in a class declaration
1906                 /// </summary>
1907                 const int AllowedModifiers =
1908                         Modifiers.NEW |
1909                         Modifiers.PUBLIC |
1910                         Modifiers.PROTECTED |
1911                         Modifiers.INTERNAL |
1912                         Modifiers.PRIVATE |
1913                         Modifiers.STATIC |
1914                         Modifiers.VIRTUAL |
1915                         Modifiers.SEALED |
1916                         Modifiers.OVERRIDE |
1917                         Modifiers.ABSTRACT |
1918                         Modifiers.UNSAFE |
1919                         Modifiers.EXTERN;
1920
1921                 //
1922                 // return_type can be "null" for VOID values.
1923                 //
1924                 public Method (Expression return_type, int mod, string name, Parameters parameters,
1925                                Attributes attrs, Location l)
1926                         : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
1927                 { }
1928
1929                 //
1930                 // Returns the `System.Type' for the ReturnType of this
1931                 // function.  Provides a nice cache.  (used between semantic analysis
1932                 // and actual code generation
1933                 //
1934                 public Type GetReturnType (TypeContainer parent)
1935                 {
1936                         return MemberType;
1937                 }
1938
1939                 // Whether this is an operator method.
1940                 public bool IsOperator;
1941
1942                 void DuplicateEntryPoint (MethodInfo b, Location location)
1943                 {
1944                         Report.Error (
1945                                 17, location,
1946                                 "Program `" + CodeGen.FileName +
1947                                 "'  has more than one entry point defined: `" +
1948                                 TypeManager.CSharpSignature(b) + "'");
1949                 }
1950
1951                 void Report28 (MethodInfo b)
1952                 {
1953                         if (RootContext.WarningLevel < 4) 
1954                                 return;
1955                                 
1956                         Report.Warning (
1957                                 28, Location,
1958                                 "`" + TypeManager.CSharpSignature(b) +
1959                                 "' has the wrong signature to be an entry point");
1960                 }
1961
1962                 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
1963                 {
1964                         if (b.ReturnType != TypeManager.void_type &&
1965                             b.ReturnType != TypeManager.int32_type)
1966                                 return false;
1967
1968                         if (pinfo.Count == 0)
1969                                 return true;
1970
1971                         if (pinfo.Count > 1)
1972                                 return false;
1973
1974                         Type t = pinfo.ParameterType(0);
1975                         if (t.IsArray &&
1976                             (t.GetArrayRank() == 1) &&
1977                             (t.GetElementType() == TypeManager.string_type) &&
1978                             (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
1979                                 return true;
1980                         else
1981                                 return false;
1982                 }
1983
1984                 //
1985                 // Checks our base implementation if any
1986                 //
1987                 protected override bool CheckBase (TypeContainer parent)
1988                 {
1989                         // Check whether arguments were correct.
1990                         if (!DoDefineParameters (parent))
1991                                 return false;
1992
1993                         MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
1994                         if (!IsOperator) {
1995                                 MemberList mi_this;
1996
1997                                 mi_this = TypeContainer.FindMembers (
1998                                         parent.TypeBuilder, MemberTypes.Method,
1999                                         BindingFlags.NonPublic | BindingFlags.Public |
2000                                         BindingFlags.Static | BindingFlags.Instance |
2001                                         BindingFlags.DeclaredOnly,
2002                                         MethodSignature.method_signature_filter, ms);
2003
2004                                 if (mi_this.Count > 0) {
2005                                         Report.Error (111, Location, "Class `" + parent.Name + "' " +
2006                                                       "already defines a member called `" + Name + "' " +
2007                                                       "with the same parameter types");
2008                                         return false;
2009                                 }
2010                         }
2011
2012                         //
2013                         // Verify if the parent has a type with the same name, and then
2014                         // check whether we have to create a new slot for it or not.
2015                         //
2016                         Type ptype = parent.TypeBuilder.BaseType;
2017
2018                         // ptype is only null for System.Object while compiling corlib.
2019                         if (ptype != null){
2020                                 MemberList mi, mi_static, mi_instance;
2021
2022                                 mi_static = TypeContainer.FindMembers (
2023                                         ptype, MemberTypes.Method,
2024                                         BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2025                                         MethodSignature.inheritable_method_signature_filter, ms);
2026
2027                                 mi_instance = TypeContainer.FindMembers (
2028                                         ptype, MemberTypes.Method,
2029                                         BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2030                                         MethodSignature.inheritable_method_signature_filter,
2031                                         ms);
2032
2033                                 if (mi_instance.Count > 0){
2034                                         mi = mi_instance;
2035                                 } else if (mi_static.Count > 0)
2036                                         mi = mi_static;
2037                                 else
2038                                         mi = null;
2039
2040                                 if (mi != null && mi.Count > 0){
2041                                         parent_method = (MethodInfo) mi [0];
2042                                         string name = parent_method.DeclaringType.Name + "." +
2043                                                 parent_method.Name;
2044
2045                                         if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2046                                                 return false;
2047
2048                                         if ((ModFlags & Modifiers.NEW) == 0) {
2049                                                 Type parent_ret = TypeManager.TypeToCoreType (
2050                                                         parent_method.ReturnType);
2051
2052                                                 if (parent_ret != MemberType) {
2053                                                         Report.Error (
2054                                                                 508, parent.MakeName (Name) + ": cannot " +
2055                                                                 "change return type when overriding " +
2056                                                                 "inherited member " + name);
2057                                                         return false;
2058                                                 }
2059                                         }
2060                                 } else {
2061                                         if ((ModFlags & Modifiers.NEW) != 0)
2062                                                 WarningNotHiding (parent);
2063
2064                                         if ((ModFlags & Modifiers.OVERRIDE) != 0){
2065                                                 Report.Error (115, Location,
2066                                                               parent.MakeName (Name) +
2067                                                               " no suitable methods found to override");
2068                                         }
2069                                 }
2070                         } else if ((ModFlags & Modifiers.NEW) != 0)
2071                                 WarningNotHiding (parent);
2072
2073                         return true;
2074                 }
2075
2076                 //
2077                 // Creates the type
2078                 //
2079                 public override bool Define (TypeContainer parent)
2080                 {
2081                         if (!DoDefine (parent))
2082                                 return false;
2083
2084                         if (!CheckBase (parent))
2085                                 return false;
2086
2087                         CallingConventions cc = GetCallingConvention (parent is Class);
2088
2089                         MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2090                                                      ParameterInfo, cc, OptAttributes,
2091                                                      ModFlags, flags, true);
2092
2093                         if (!MethodData.Define (parent))
2094                                 return false;
2095
2096                         MethodBuilder = MethodData.MethodBuilder;
2097                         
2098                         //
2099                         // This is used to track the Entry Point,
2100                         //
2101                         if (Name == "Main" &&
2102                             ((ModFlags & Modifiers.STATIC) != 0) && 
2103                             (RootContext.MainClass == null ||
2104                              RootContext.MainClass == parent.TypeBuilder.FullName)){
2105                                 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2106                                         if (RootContext.EntryPoint == null) {
2107                                                 RootContext.EntryPoint = MethodBuilder;
2108                                                 RootContext.EntryPointLocation = Location;
2109                                         } else {
2110                                                 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2111                                                 DuplicateEntryPoint (MethodBuilder, Location);
2112                                         }
2113                                 } else                                  
2114                                         Report28(MethodBuilder);
2115                         }
2116
2117                         return true;
2118                 }
2119
2120                 //
2121                 // Emits the code
2122                 // 
2123                 public void Emit (TypeContainer parent)
2124                 {
2125                         MethodData.Emit (parent, Block, this);
2126                 }
2127         }
2128
2129         public abstract class ConstructorInitializer {
2130                 ArrayList argument_list;
2131                 ConstructorInfo parent_constructor;
2132                 Parameters parameters;
2133                 Location loc;
2134                 
2135                 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2136                                                Location loc)
2137                 {
2138                         this.argument_list = argument_list;
2139                         this.parameters = parameters;
2140                         this.loc = loc;
2141                 }
2142
2143                 public ArrayList Arguments {
2144                         get {
2145                                 return argument_list;
2146                         }
2147                 }
2148
2149                 public bool Resolve (EmitContext ec)
2150                 {
2151                         Expression parent_constructor_group;
2152                         Type t;
2153
2154                         ec.CurrentBlock = new Block (null, true, parameters);
2155
2156                         if (argument_list != null){
2157                                 foreach (Argument a in argument_list){
2158                                         if (!a.Resolve (ec, loc))
2159                                                 return false;
2160                                 }
2161                         }
2162
2163                         ec.CurrentBlock = null;
2164
2165                         if (this is ConstructorBaseInitializer) {
2166                                 if (ec.ContainerType.BaseType == null)
2167                                         return true;
2168
2169                                 t = ec.ContainerType.BaseType;
2170                                 if (ec.ContainerType.IsValueType) {
2171                                         Report.Error (522, loc,
2172                                                 "structs cannot call base class constructors");
2173                                         return false;
2174                                 }
2175                         } else
2176                                 t = ec.ContainerType;
2177
2178                         parent_constructor_group = Expression.MemberLookup (
2179                                 ec, t, t, ".ctor", 
2180                                 MemberTypes.Constructor,
2181                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2182                                 loc);
2183                         
2184                         if (parent_constructor_group == null){
2185                                 Report.Error (1501, loc,
2186                                        "Can not find a constructor for this argument list");
2187                                 return false;
2188                         }
2189                         
2190                         parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
2191                                 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2192                         
2193                         if (parent_constructor == null){
2194                                 Report.Error (1501, loc,
2195                                        "Can not find a constructor for this argument list");
2196                                 return false;
2197                         }
2198                         
2199                         return true;
2200                 }
2201
2202                 public void Emit (EmitContext ec)
2203                 {
2204                         if (parent_constructor != null)
2205                                 ec.ig.Emit (OpCodes.Ldarg_0);
2206                         if (argument_list != null)
2207                                 Invocation.EmitArguments (ec, null, argument_list);
2208                         if (parent_constructor != null)
2209                                 ec.ig.Emit (OpCodes.Call, parent_constructor);
2210                 }
2211         }
2212
2213         public class ConstructorBaseInitializer : ConstructorInitializer {
2214                 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2215                         base (argument_list, pars, l)
2216                 {
2217                 }
2218         }
2219
2220         public class ConstructorThisInitializer : ConstructorInitializer {
2221                 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2222                         base (argument_list, pars, l)
2223                 {
2224                 }
2225         }
2226         
2227         public class Constructor : MethodCore {
2228                 public ConstructorBuilder ConstructorBuilder;
2229                 public ConstructorInitializer Initializer;
2230                 new public Attributes OptAttributes;
2231
2232                 // <summary>
2233                 //   Modifiers allowed for a constructor.
2234                 // </summary>
2235                 const int AllowedModifiers =
2236                         Modifiers.PUBLIC |
2237                         Modifiers.PROTECTED |
2238                         Modifiers.INTERNAL |
2239                         Modifiers.STATIC |
2240                         Modifiers.UNSAFE |
2241                         Modifiers.PRIVATE;
2242
2243                 //
2244                 // The spec claims that static is not permitted, but
2245                 // my very own code has static constructors.
2246                 //
2247                 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2248                         : base (null, 0, AllowedModifiers, name, null, args, l)
2249                 {
2250                         Initializer = init;
2251                 }
2252
2253                 //
2254                 // Returns true if this is a default constructor
2255                 //
2256                 public bool IsDefault ()
2257                 {
2258                         if ((ModFlags & Modifiers.STATIC) != 0)
2259                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2260                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2261                         
2262                         else
2263                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2264                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2265                                         (Initializer is ConstructorBaseInitializer) &&
2266                                         (Initializer.Arguments == null);
2267                 }
2268
2269                 //
2270                 // Creates the ConstructorBuilder
2271                 //
2272                 public override bool Define (TypeContainer parent)
2273                 {
2274                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
2275                                                MethodAttributes.SpecialName);
2276
2277                         // Check if arguments were correct.
2278                         if (!DoDefineParameters (parent))
2279                                 return false;
2280
2281                         if ((ModFlags & Modifiers.STATIC) != 0)
2282                                 ca |= MethodAttributes.Static;
2283                         else {
2284                                 if (parent is Struct && ParameterTypes.Length == 0){
2285                                         Report.Error (
2286                                                 568, Location, 
2287                                                 "Structs can not contain explicit parameterless " +
2288                                                 "constructors");
2289                                         return false;
2290                                 }
2291                                 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2292                         }
2293
2294                         ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2295                                 ca, GetCallingConvention (parent is Class), ParameterTypes);
2296
2297                         //
2298                         // HACK because System.Reflection.Emit is lame
2299                         //
2300                         if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2301                                 Report.Error (
2302                                         111, Location,
2303                                         "Class `" +parent.Name+ "' already contains a definition with the " +
2304                                         "same return value and parameter types for constructor `" + Name
2305                                         + "'");
2306                                 return false;
2307                         }
2308
2309                         return true;
2310                 }
2311
2312                 //
2313                 // Emits the code
2314                 //
2315                 public void Emit (TypeContainer parent)
2316                 {
2317                         ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2318                         EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2319
2320                         if ((ModFlags & Modifiers.STATIC) == 0){
2321                                 if (parent is Class && Initializer == null)
2322                                         Initializer = new ConstructorBaseInitializer (
2323                                                 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2324
2325
2326                                 //
2327                                 // Spec mandates that Initializers will not have
2328                                 // `this' access
2329                                 //
2330                                 ec.IsStatic = true;
2331                                 if (Initializer != null && !Initializer.Resolve (ec))
2332                                         return;
2333                                 ec.IsStatic = false;
2334                         }
2335
2336                         LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2337                         
2338                         //
2339                         // Classes can have base initializers and instance field initializers.
2340                         //
2341                         if (parent is Class){
2342                                 if ((ModFlags & Modifiers.STATIC) == 0)
2343                                         parent.EmitFieldInitializers (ec);
2344                         }
2345                         if (Initializer != null)
2346                                 Initializer.Emit (ec);
2347                         
2348                         if ((ModFlags & Modifiers.STATIC) != 0)
2349                                 parent.EmitFieldInitializers (ec);
2350
2351                         Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2352
2353                         // If this is a non-static `struct' constructor and doesn't have any
2354                         // initializer, it must initialize all of the struct's fields.
2355                         if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2356                             (Initializer == null))
2357                                 Block.AddThisVariable (parent, Location);
2358
2359                         ec.EmitTopBlock (Block, ParameterInfo, Location);
2360                 }
2361         }
2362
2363         public class MethodData {
2364                 //
2365                 // The return type of this method
2366                 //
2367                 public readonly Type ReturnType;
2368                 public readonly Type[] ParameterTypes;
2369                 public readonly InternalParameters ParameterInfo;
2370                 public readonly CallingConventions CallingConventions;
2371                 public readonly Attributes OptAttributes;
2372                 public readonly Location Location;
2373
2374                 //
2375                 // Are we implementing an interface ?
2376                 //
2377                 public bool IsImplementing = false;
2378
2379                 //
2380                 // Protected data.
2381                 //
2382                 protected MemberBase member;
2383                 protected int modifiers;
2384                 protected MethodAttributes flags;
2385                 protected bool is_method;
2386                 protected string accessor_name;
2387                 ArrayList conditionals;
2388
2389                 MethodBuilder builder = null;
2390                 public MethodBuilder MethodBuilder {
2391                         get {
2392                                 return builder;
2393                         }
2394                 }
2395
2396                 public MethodData (MemberBase member, string name, Type return_type,
2397                                    Type [] parameter_types, InternalParameters parameters,
2398                                    CallingConventions cc, Attributes opt_attrs,
2399                                    int modifiers, MethodAttributes flags, bool is_method)
2400                 {
2401                         this.member = member;
2402                         this.accessor_name = name;
2403                         this.ReturnType = return_type;
2404                         this.ParameterTypes = parameter_types;
2405                         this.ParameterInfo = parameters;
2406                         this.CallingConventions = cc;
2407                         this.OptAttributes = opt_attrs;
2408                         this.modifiers = modifiers;
2409                         this.flags = flags;
2410                         this.is_method = is_method;
2411                         this.Location = member.Location;
2412                         this.conditionals = new ArrayList ();
2413                 }
2414
2415                 //
2416                 // Attributes.
2417                 //
2418                 Attribute dllimport_attribute = null;
2419                 string obsolete = null;
2420                 bool obsolete_error = false;
2421
2422                 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2423                 {
2424                         if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2425                                 return true;
2426
2427                         foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2428                                 if (asec.Attributes == null)
2429                                         continue;
2430                                         
2431                                 foreach (Attribute a in asec.Attributes) {
2432                                         if (a.Name == "Conditional") {
2433                                                 if (!ApplyConditionalAttribute (a))
2434                                                         return false;
2435                                         } else if (a.Name == "Obsolete") {
2436                                                 if (!ApplyObsoleteAttribute (a))
2437                                                         return false;
2438                                         } else if (a.Name.IndexOf ("DllImport") != -1) {
2439                                                 if (!is_method) {
2440                                                         a.Type = TypeManager.dllimport_type;
2441                                                         Attribute.Error_AttributeNotValidForElement (a, Location);
2442                                                         return false;
2443                                                 }
2444                                                 if (!ApplyDllImportAttribute (a))
2445                                                         return false;
2446                                         }
2447                                 }
2448                         }
2449
2450                         return true;
2451                 }
2452
2453                 //
2454                 // Applies the `DllImport' attribute to the method.
2455                 //
2456                 protected virtual bool ApplyDllImportAttribute (Attribute a)
2457                 {
2458                         const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2459                         if ((modifiers & extern_static) != extern_static) {
2460                                 Report.Error (601, Location,
2461                                               "The DllImport attribute must be specified on a method " +
2462                                               "marked `static' and `extern'.");
2463                                 return false;
2464                         }
2465
2466                         flags |= MethodAttributes.PinvokeImpl;
2467                         dllimport_attribute = a;
2468                         return true;
2469                 }
2470
2471                 //
2472                 // Applies the `Obsolete' attribute to the method.
2473                 //
2474                 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2475                 {
2476                         if (obsolete != null) {
2477                                 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2478                                 return false;
2479                         }
2480
2481                         obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2482                         return obsolete != null;
2483                 }
2484
2485                 //
2486                 // Applies the `Conditional' attribute to the method.
2487                 //
2488                 protected virtual bool ApplyConditionalAttribute (Attribute a)
2489                 {
2490                         // The Conditional attribute is only valid on methods.
2491                         if (!is_method) {
2492                                 Attribute.Error_AttributeNotValidForElement (a, Location);
2493                                 return false;
2494                         }
2495
2496                         string condition = a.Conditional_GetConditionName ();
2497
2498                         if (condition == null)
2499                                 return false;
2500
2501                         if (ReturnType != TypeManager.void_type) {
2502                                 Report.Error (578, Location,
2503                                               "Conditional not valid on `" + member.Name + "' " +
2504                                               "because its return type is not void");
2505                                 return false;
2506                         }
2507
2508                         if ((modifiers & Modifiers.OVERRIDE) != 0) {
2509                                 Report.Error (243, Location,
2510                                               "Conditional not valid on `" + member.Name + "' " +
2511                                               "because it is an override method");
2512                                 return false;
2513                         }
2514
2515                         if (member.IsExplicitImpl) {
2516                                 Report.Error (577, Location,
2517                                               "Conditional not valid on `" + member.Name + "' " +
2518                                               "because it is an explicit interface implementation");
2519                                 return false;
2520                         }
2521
2522                         if (IsImplementing) {
2523                                 Report.Error (623, Location,
2524                                               "Conditional not valid on `" + member.Name + "' " +
2525                                               "because it is an interface method");
2526                                 return false;
2527                         }
2528
2529                         conditionals.Add (condition);
2530
2531                         return true;
2532                 }
2533
2534                 //
2535                 // Checks whether this method should be ignored due to its Conditional attributes.
2536                 //
2537                 bool ShouldIgnore (Location loc)
2538                 {
2539                         // When we're overriding a virtual method, we implicitly inherit the
2540                         // Conditional attributes from our parent.
2541                         if (member.ParentMethod != null) {
2542                                 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2543                                         member.ParentMethod, loc);
2544
2545                                 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2546                                         return true;
2547                         }
2548
2549                         foreach (string condition in conditionals)
2550                                 if (RootContext.AllDefines [condition] == null)
2551                                         return true;
2552
2553                         return false;
2554                 }
2555
2556                 //
2557                 // Returns the TypeManager.MethodFlags for this method.
2558                 // This emits an error 619 / warning 618 if the method is obsolete.
2559                 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2560                 //
2561                 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2562                 {
2563                         TypeManager.MethodFlags flags = 0;
2564
2565                         if (obsolete != null) {
2566                                 if (obsolete_error) {
2567                                         Report.Error (619, loc, "Method `" + member.Name +
2568                                                       "' is obsolete: `" + obsolete + "'");
2569                                         return TypeManager.MethodFlags.IsObsoleteError;
2570                                 } else
2571                                         Report.Warning (618, loc, "Method `" + member.Name +
2572                                                         "' is obsolete: `" + obsolete + "'");
2573
2574                                 flags |= TypeManager.MethodFlags.IsObsolete;
2575                         }
2576
2577                         if (ShouldIgnore (loc))
2578                             flags |= TypeManager.MethodFlags.ShouldIgnore;
2579
2580                         return flags;
2581                 }
2582
2583                 public virtual bool Define (TypeContainer parent)
2584                 {
2585                         MethodInfo implementing = null;
2586                         string method_name, name, prefix;
2587
2588                         if (OptAttributes != null)
2589                                 if (!ApplyAttributes (OptAttributes, is_method))
2590                                         return false;
2591
2592                         if (member.IsExplicitImpl)
2593                                 prefix = member.InterfaceType.FullName + ".";
2594                         else
2595                                 prefix = "";
2596
2597                         if (accessor_name != null)
2598                                 name = accessor_name + "_" + member.ShortName;
2599                         else
2600                                 name = member.ShortName;
2601                         method_name = prefix + name;
2602                                 
2603                         if (parent.Pending != null){
2604                                 if (member is Indexer)
2605                                         implementing = parent.Pending.IsInterfaceIndexer (
2606                                                 member.InterfaceType, ReturnType, ParameterTypes);
2607                                 else
2608                                         implementing = parent.Pending.IsInterfaceMethod (
2609                                                 member.InterfaceType, name, ReturnType, ParameterTypes);
2610
2611                                 if (member.InterfaceType != null && implementing == null){
2612                                         TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2613                                                 Location, name);
2614                                         return false;
2615                                 }
2616                         }
2617
2618                         //
2619                         // For implicit implementations, make sure we are public, for
2620                         // explicit implementations, make sure we are private.
2621                         //
2622                         if (implementing != null){
2623                                 //
2624                                 // Setting null inside this block will trigger a more
2625                                 // verbose error reporting for missing interface implementations
2626                                 //
2627                                 // The "candidate" function has been flagged already
2628                                 // but it wont get cleared
2629                                 //
2630                                 if (!member.IsExplicitImpl){
2631                                         //
2632                                         // We already catch different accessibility settings
2633                                         // so we just need to check that we are not private
2634                                         //
2635                                         if ((modifiers & Modifiers.PRIVATE) != 0)
2636                                                 implementing = null;
2637                                         
2638                                         //
2639                                         // Static is not allowed
2640                                         //
2641                                         if ((modifiers & Modifiers.STATIC) != 0)
2642                                                 implementing = null;
2643                                 } else {
2644                                         if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2645                                                 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2646                                                 implementing = null;
2647                                         }
2648                                 }
2649                         }
2650                         
2651                         //
2652                         // If implementing is still valid, set flags
2653                         //
2654                         if (implementing != null){
2655                                 //
2656                                 // When implementing interface methods, set NewSlot.
2657                                 //
2658                                 if (implementing.DeclaringType.IsInterface)
2659                                         flags |= MethodAttributes.NewSlot;
2660                                 
2661                                 flags |=
2662                                         MethodAttributes.Virtual |
2663                                         MethodAttributes.HideBySig;
2664
2665                                 // Get the method name from the explicit interface.
2666                                 if (member.InterfaceType != null) {
2667                                         name = implementing.Name;
2668                                         method_name = prefix + name;
2669                                 }
2670
2671                                 IsImplementing = true;
2672                         }
2673
2674                         //
2675                         // Create the MethodBuilder for the method
2676                         //
2677                         if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2678                                 if ((modifiers & Modifiers.STATIC) == 0) {
2679                                         Report.Error (601, Location,
2680                                                       "The DllImport attribute must be specified on " +
2681                                                       "a method marked 'static' and 'extern'.");
2682                                         return false;
2683                                 }
2684                                 
2685                                 EmitContext ec = new EmitContext (
2686                                         parent, Location, null, ReturnType, modifiers);
2687                                 
2688                                 builder = dllimport_attribute.DefinePInvokeMethod (
2689                                         ec, parent.TypeBuilder, method_name, flags,
2690                                         ReturnType, ParameterTypes);
2691                         } else
2692                                 builder = parent.TypeBuilder.DefineMethod (
2693                                         method_name, flags, CallingConventions,
2694                                         ReturnType, ParameterTypes);
2695
2696                         if (builder == null)
2697                                 return false;
2698
2699                         if (IsImplementing) {
2700                                 //
2701                                 // clear the pending implemntation flag
2702                                 //
2703                                 if (member is Indexer) {
2704                                         parent.Pending.ImplementIndexer (
2705                                                 member.InterfaceType, builder, ReturnType,
2706                                                 ParameterTypes, true);
2707                                 } else
2708                                         parent.Pending.ImplementMethod (
2709                                                 member.InterfaceType, name, ReturnType,
2710                                                 ParameterTypes, member.IsExplicitImpl);
2711
2712                                 if (member.IsExplicitImpl)
2713                                         parent.TypeBuilder.DefineMethodOverride (
2714                                                 builder, implementing);
2715                         }
2716
2717                         if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
2718                                 Report.Error (111, Location,
2719                                               "Class `" + parent.Name +
2720                                               "' already contains a definition with the " +
2721                                               "same return value and parameter types as the " +
2722                                               "'get' method of property `" + member.Name + "'");
2723                                 return false;
2724                         }
2725
2726                         TypeManager.AddMethod (builder, this);
2727
2728                         return true;
2729                 }
2730
2731                 //
2732                 // Emits the code
2733                 // 
2734                 public virtual void Emit (TypeContainer parent, Block block, object kind)
2735                 {
2736                         ILGenerator ig;
2737                         EmitContext ec;
2738
2739                         if ((flags & MethodAttributes.PinvokeImpl) == 0)
2740                                 ig = builder.GetILGenerator ();
2741                         else
2742                                 ig = null;
2743
2744                         ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
2745
2746                         if (OptAttributes != null)
2747                                 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
2748
2749                         if (member is MethodCore)
2750                                 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
2751
2752                         //
2753                         // abstract or extern methods have no bodies
2754                         //
2755                         if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
2756                                 if (block == null)
2757                                         return;
2758
2759                                 //
2760                                 // abstract or extern methods have no bodies.
2761                                 //
2762                                 if ((modifiers & Modifiers.ABSTRACT) != 0)
2763                                         Report.Error (
2764                                                 500, Location, "Abstract method `" +
2765                                                 TypeManager.CSharpSignature (builder) +
2766                                                 "' can not have a body");
2767
2768                                 if ((modifiers & Modifiers.EXTERN) != 0)
2769                                         Report.Error (
2770                                                 179, Location, "External method `" +
2771                                                 TypeManager.CSharpSignature (builder) +
2772                                                 "' can not have a body");
2773
2774                                 return;
2775                         }
2776
2777                         //
2778                         // Methods must have a body unless they're extern or abstract
2779                         //
2780                         if (block == null) {
2781                                 Report.Error (
2782                                         501, Location, "Method `" +
2783                                         TypeManager.CSharpSignature (builder) +
2784                                         "' must declare a body since it is not marked " +
2785                                         "abstract or extern");
2786                                 return;
2787                         }
2788
2789                         //
2790                         // Handle destructors specially
2791                         //
2792                         // FIXME: This code generates buggy code
2793                         //
2794                         if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
2795                                 EmitDestructor (ec, block);
2796                         else {
2797                                 ISymbolWriter sw = CodeGen.SymbolWriter;
2798
2799                                 if ((sw != null) && !Location.IsNull (Location) &&
2800                                     !Location.IsNull (block.EndLocation)) {
2801                                         Location end = block.EndLocation;
2802                                         MethodToken token = MethodBuilder.GetToken ();
2803                                         sw.OpenMethod (new SymbolToken (token.Token));
2804                                         sw.SetMethodSourceRange (Location.SymbolDocument,
2805                                                                  Location.Row, 0,
2806                                                                  end.SymbolDocument,
2807                                                                  end.Row, 0);
2808
2809                                         ec.EmitTopBlock (block, ParameterInfo, Location);
2810
2811                                         sw.CloseMethod ();
2812                                 } else
2813                                         ec.EmitTopBlock (block, ParameterInfo, Location);
2814                         }
2815                 }
2816
2817                 void EmitDestructor (EmitContext ec, Block block)
2818                 {
2819                         ILGenerator ig = ec.ig;
2820                         
2821                         Label finish = ig.DefineLabel ();
2822                         bool old_in_try = ec.InTry;
2823                         
2824                         ig.BeginExceptionBlock ();
2825                         ec.InTry = true;
2826                         ec.ReturnLabel = finish;
2827                         ec.HasReturnLabel = true;
2828                         ec.EmitTopBlock (block, null, Location);
2829                         ec.InTry = old_in_try;
2830                         
2831                         // ig.MarkLabel (finish);
2832                         bool old_in_finally = ec.InFinally;
2833                         ec.InFinally = true;
2834                         ig.BeginFinallyBlock ();
2835                         
2836                         if (ec.ContainerType.BaseType != null) {
2837                                 Expression member_lookup = Expression.MemberLookup (
2838                                         ec, ec.ContainerType.BaseType, "Finalize",
2839                                         MemberTypes.Method, Expression.AllBindingFlags, Location);
2840
2841                                 if (member_lookup != null){
2842                                         MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
2843                                 
2844                                         ig.Emit (OpCodes.Ldarg_0);
2845                                         ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
2846                                 }
2847                         }
2848                         ec.InFinally = old_in_finally;
2849                         
2850                         ig.EndExceptionBlock ();
2851                         //ig.MarkLabel (ec.ReturnLabel);
2852                         ig.Emit (OpCodes.Ret);
2853                 }
2854         }
2855
2856         abstract public class MemberBase : MemberCore {
2857                 public Expression Type;
2858                 public readonly Attributes OptAttributes;
2859
2860                 protected MethodAttributes flags;
2861
2862                 //
2863                 // The "short" name of this property / indexer / event.  This is the
2864                 // name without the explicit interface.
2865                 //
2866                 public string ShortName;
2867
2868                 //
2869                 // The type of this property / indexer / event
2870                 //
2871                 public Type MemberType;
2872
2873                 //
2874                 // If true, this is an explicit interface implementation
2875                 //
2876                 public bool IsExplicitImpl = false;
2877
2878                 //
2879                 // The name of the interface we are explicitly implementing
2880                 //
2881                 public string ExplicitInterfaceName = null;
2882
2883                 //
2884                 // If true, the interface type we are explicitly implementing
2885                 //
2886                 public Type InterfaceType = null;
2887
2888                 //
2889                 // The method we're overriding if this is an override method.
2890                 //
2891                 protected MethodInfo parent_method = null;
2892                 public MethodInfo ParentMethod {
2893                         get {
2894                                 return parent_method;
2895                         }
2896                 }
2897
2898                 //
2899                 // The constructor is only exposed to our children
2900                 //
2901                 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
2902                                       Attributes attrs, Location loc)
2903                         : base (name, loc)
2904                 {
2905                         Type = type;
2906                         ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
2907                         OptAttributes = attrs;
2908                 }
2909
2910                 protected virtual bool CheckBase (TypeContainer parent)
2911                 {
2912                         return true;
2913                 }
2914
2915                 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
2916                 {
2917                         bool error = false;
2918
2919                         foreach (Type partype in parameters){
2920                                 if (partype.IsPointer && !UnsafeOK (parent))
2921                                         error = true;
2922
2923                                 if (parent.AsAccessible (partype, ModFlags))
2924                                         continue;
2925
2926                                 if (this is Indexer)
2927                                         Report.Error (55, Location,
2928                                                       "Inconsistent accessibility: parameter type `" +
2929                                                       TypeManager.CSharpName (partype) + "' is less " +
2930                                                       "accessible than indexer `" + Name + "'");
2931                                 else
2932                                         Report.Error (51, Location,
2933                                                       "Inconsistent accessibility: parameter type `" +
2934                                                       TypeManager.CSharpName (partype) + "' is less " +
2935                                                       "accessible than method `" + Name + "'");
2936                                 error = true;
2937                         }
2938
2939                         return !error;
2940                 }
2941
2942                 protected virtual bool DoDefine (TypeContainer parent)
2943                 {
2944                         if (Name == null)
2945                                 Name = "this";
2946
2947                         if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2948                                 return false;
2949
2950                         flags = Modifiers.MethodAttr (ModFlags);
2951
2952                         // Lookup Type, verify validity
2953                         MemberType = parent.ResolveType (Type, false, Location);
2954                         if (MemberType == null)
2955                                 return false;
2956
2957                         // verify accessibility
2958                         if (!parent.AsAccessible (MemberType, ModFlags)) {
2959                                 if (this is Property)
2960                                         Report.Error (53, Location,
2961                                                       "Inconsistent accessibility: property type `" +
2962                                                       TypeManager.CSharpName (MemberType) + "' is less " +
2963                                                       "accessible than property `" + Name + "'");
2964                                 else if (this is Indexer)
2965                                         Report.Error (54, Location,
2966                                                       "Inconsistent accessibility: indexer return type `" +
2967                                                       TypeManager.CSharpName (MemberType) + "' is less " +
2968                                                       "accessible than indexer `" + Name + "'");
2969                                 else if (this is Method)
2970                                         Report.Error (50, Location,
2971                                                       "Inconsistent accessibility: return type `" +
2972                                                       TypeManager.CSharpName (MemberType) + "' is less " +
2973                                                       "accessible than method `" + Name + "'");
2974                                 else
2975                                         Report.Error (52, Location,
2976                                                       "Inconsistent accessibility: field type `" +
2977                                                       TypeManager.CSharpName (MemberType) + "' is less " +
2978                                                       "accessible than field `" + Name + "'");
2979                                 return false;
2980                         }
2981
2982                         if (MemberType.IsPointer && !UnsafeOK (parent))
2983                                 return false;
2984                         
2985                         //
2986                         // Check for explicit interface implementation
2987                         //
2988                         if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
2989                                 int pos = Name.LastIndexOf (".");
2990
2991                                 ExplicitInterfaceName = Name.Substring (0, pos);
2992                                 ShortName = Name.Substring (pos + 1);
2993                         } else
2994                                 ShortName = Name;
2995
2996                         if (ExplicitInterfaceName != null) {
2997                                 InterfaceType  = RootContext.LookupType (
2998                                         parent, ExplicitInterfaceName, false, Location);
2999                                 if (InterfaceType == null)
3000                                         return false;
3001
3002                                 // Compute the full name that we need to export.
3003                                 Name = InterfaceType.FullName + "." + ShortName;
3004                                 
3005                                 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3006                                         return false;
3007                                 
3008                                 IsExplicitImpl = true;
3009                         } else
3010                                 IsExplicitImpl = false;
3011
3012                         return true;
3013                 }
3014         }
3015
3016         //
3017         // Fields and Events both generate FieldBuilders, we use this to share 
3018         // their common bits.  This is also used to flag usage of the field
3019         //
3020         abstract public class FieldBase : MemberBase {
3021                 public FieldBuilder  FieldBuilder;
3022                 public Status status;
3023
3024                 [Flags]
3025                 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3026
3027                 //
3028                 // The constructor is only exposed to our children
3029                 //
3030                 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3031                                      object init, Attributes attrs, Location loc)
3032                         : base (type, mod, allowed_mod, name, attrs, loc)
3033                 {
3034                         this.init = init;
3035                 }
3036
3037                 //
3038                 // Whether this field has an initializer.
3039                 //
3040                 public bool HasInitializer {
3041                         get {
3042                                 return init != null;
3043                         }
3044                 }
3045
3046                 // Private.
3047                 readonly Object init;
3048                 Expression init_expr;
3049                 bool init_expr_initialized = false;
3050
3051                 //
3052                 // Resolves and returns the field initializer.
3053                 //
3054                 public Expression GetInitializerExpression (EmitContext ec)
3055                 {
3056                         if (init_expr_initialized)
3057                                 return init_expr;
3058
3059                         Expression e;
3060                         if (init is Expression)
3061                                 e = (Expression) init;
3062                         else
3063                                 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3064
3065                         ec.IsFieldInitializer = true;
3066                         e = e.DoResolve (ec);
3067                         ec.IsFieldInitializer = false;
3068
3069                         init_expr = e;
3070                         init_expr_initialized = true;
3071
3072                         return init_expr;
3073                 }
3074         }
3075
3076         //
3077         // The Field class is used to represents class/struct fields during parsing.
3078         //
3079         public class Field : FieldBase {
3080                 // <summary>
3081                 //   Modifiers allowed in a class declaration
3082                 // </summary>
3083                 const int AllowedModifiers =
3084                         Modifiers.NEW |
3085                         Modifiers.PUBLIC |
3086                         Modifiers.PROTECTED |
3087                         Modifiers.INTERNAL |
3088                         Modifiers.PRIVATE |
3089                         Modifiers.STATIC |
3090                         Modifiers.VOLATILE |
3091                         Modifiers.UNSAFE |
3092                         Modifiers.READONLY;
3093
3094                 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3095                               Attributes attrs, Location loc)
3096                         : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3097                 {
3098                 }
3099
3100                 public override bool Define (TypeContainer parent)
3101                 {
3102                         Type t = parent.ResolveType (Type, false, Location);
3103                         
3104                         if (t == null)
3105                                 return false;
3106
3107                         if (!parent.AsAccessible (t, ModFlags)) {
3108                                 Report.Error (52, Location,
3109                                               "Inconsistent accessibility: field type `" +
3110                                               TypeManager.CSharpName (t) + "' is less " +
3111                                               "accessible than field `" + Name + "'");
3112                                 return false;
3113                         }
3114
3115                         if (t.IsPointer && !UnsafeOK (parent))
3116                                 return false;
3117                                 
3118                         if (RootContext.WarningLevel > 1){
3119                                 Type ptype = parent.TypeBuilder.BaseType;
3120
3121                                 // ptype is only null for System.Object while compiling corlib.
3122                                 if (ptype != null){
3123                                         TypeContainer.FindMembers (
3124                                                 ptype, MemberTypes.Method,
3125                                                 BindingFlags.Public |
3126                                                 BindingFlags.Static | BindingFlags.Instance,
3127                                                 System.Type.FilterName, Name);
3128                                 }
3129                         }
3130
3131                         if ((ModFlags & Modifiers.VOLATILE) != 0){
3132                                 if (!t.IsClass){
3133                                         if (TypeManager.IsEnumType (t))
3134                                                 t = TypeManager.EnumToUnderlying (t);
3135
3136                                         if (!((t == TypeManager.bool_type) ||
3137                                               (t == TypeManager.sbyte_type) ||
3138                                               (t == TypeManager.byte_type) ||
3139                                               (t == TypeManager.short_type) ||    
3140                                               (t == TypeManager.ushort_type) ||
3141                                               (t == TypeManager.int32_type) ||    
3142                                               (t == TypeManager.uint32_type) ||    
3143                                               (t == TypeManager.char_type) ||    
3144                                               (t == TypeManager.float_type))){
3145                                                 Report.Error (
3146                                                         677, Location, parent.MakeName (Name) +
3147                                                         " A volatile field can not be of type `" +
3148                                                         TypeManager.CSharpName (t) + "'");
3149                                                 return false;
3150                                         }
3151                                 }
3152                         }
3153                         
3154                         FieldBuilder = parent.TypeBuilder.DefineField (
3155                                 Name, t, Modifiers.FieldAttr (ModFlags));
3156
3157                         TypeManager.RegisterFieldBase (FieldBuilder, this);
3158                         return true;
3159                 }
3160
3161                 public void Emit (TypeContainer tc)
3162                 {
3163                         EmitContext ec = new EmitContext (tc, Location, null,
3164                                                           FieldBuilder.FieldType, ModFlags);
3165
3166                         Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3167                 }
3168         }
3169
3170         //
3171         // `set' and `get' accessors are represented with an Accessor.
3172         // 
3173         public class Accessor {
3174                 //
3175                 // Null if the accessor is empty, or a Block if not
3176                 //
3177                 public Block Block;
3178                 public Attributes OptAttributes;
3179                 
3180                 public Accessor (Block b, Attributes attrs)
3181                 {
3182                         Block = b;
3183                         OptAttributes = attrs;
3184                 }
3185         }
3186
3187         //
3188         // Properties and Indexers both generate PropertyBuilders, we use this to share 
3189         // their common bits.
3190         //
3191         abstract public class PropertyBase : MethodCore {
3192                 public Accessor Get, Set;
3193                 public PropertyBuilder PropertyBuilder;
3194                 public MethodBuilder GetBuilder, SetBuilder;
3195                 public MethodData GetData, SetData;
3196
3197                 protected EmitContext ec;
3198
3199                 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3200                                      Parameters parameters, Accessor get_block, Accessor set_block,
3201                                      Attributes attrs, Location loc)
3202                         : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3203                 {
3204                         Get = get_block;
3205                         Set = set_block;
3206                 }
3207
3208                 protected override bool DoDefine (TypeContainer parent)
3209                 {
3210                         if (!base.DoDefine (parent))
3211                                 return false;
3212
3213                         ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3214
3215                         return true;
3216                 }
3217
3218                 //
3219                 // Checks our base implementation if any
3220                 //
3221                 protected override bool CheckBase (TypeContainer parent)
3222                 {
3223                         // Check whether arguments were correct.
3224                         if (!DoDefineParameters (parent))
3225                                 return false;
3226
3227                         MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
3228                         MemberList props_this;
3229
3230                         props_this = TypeContainer.FindMembers (
3231                                 parent.TypeBuilder, MemberTypes.Property,
3232                                 BindingFlags.NonPublic | BindingFlags.Public |
3233                                 BindingFlags.Static | BindingFlags.Instance |
3234                                 BindingFlags.DeclaredOnly,
3235                                 MethodSignature.method_signature_filter, ms);
3236
3237                         if (props_this.Count > 0) {
3238                                 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3239                                               "already defines a member called `" + Name + "' " +
3240                                               "with the same parameter types");
3241                                 return false;
3242                         }
3243
3244                         //
3245                         // Find properties with the same name on the base class
3246                         //
3247                         MemberList props;
3248                         MemberList props_static = TypeContainer.FindMembers (
3249                                 parent.TypeBuilder.BaseType, MemberTypes.Property,
3250                                 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3251                                 MethodSignature.inheritable_property_signature_filter, ms);
3252
3253                         MemberList props_instance = TypeContainer.FindMembers (
3254                                 parent.TypeBuilder.BaseType, MemberTypes.Property,
3255                                 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3256                                 MethodSignature.inheritable_property_signature_filter,
3257                                 ms);
3258
3259                         //
3260                         // Find if we have anything
3261                         //
3262                         if (props_static.Count > 0)
3263                                 props = props_static;
3264                         else if (props_instance.Count > 0)
3265                                 props = props_instance;
3266                         else
3267                                 props = null;
3268
3269                         //
3270                         // If we have something on the base.
3271                         if (props != null && props.Count > 0){
3272                                 PropertyInfo pi = (PropertyInfo) props [0];
3273
3274                                 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
3275                                 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
3276
3277                                 MethodInfo reference = inherited_get == null ?
3278                                         inherited_set : inherited_get;
3279                                 
3280                                 if (reference != null) {
3281                                         string name = reference.DeclaringType.Name + "." + Name;
3282
3283                                         if (!CheckMethodAgainstBase (parent, flags, reference, name))
3284                                                 return false;
3285                                 }
3286
3287                                 if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
3288                                         Report.Error (508, parent.MakeName (Name) + ": cannot " +
3289                                                       "change return type when overriding inherited " +
3290                                                       "member `" + pi.DeclaringType + "." + pi.Name + "'");
3291                                         return false;
3292                                 }
3293                         } else {
3294                                 if ((ModFlags & Modifiers.NEW) != 0)
3295                                         WarningNotHiding (parent);
3296                                 
3297                                 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3298                                         if (this is Indexer)
3299                                                 Report.Error (115, Location,
3300                                                               parent.MakeName (Name) +
3301                                                               " no suitable indexers found to override");
3302                                         else
3303                                                 Report.Error (115, Location,
3304                                                               parent.MakeName (Name) +
3305                                                               " no suitable properties found to override");
3306                                         return false;
3307                                 }
3308                         }
3309                         return true;
3310                 }
3311
3312                 public void Emit (TypeContainer tc)
3313                 {
3314                         //
3315                         // The PropertyBuilder can be null for explicit implementations, in that
3316                         // case, we do not actually emit the ".property", so there is nowhere to
3317                         // put the attribute
3318                         //
3319                         if (PropertyBuilder != null)
3320                                 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3321
3322                         if (GetData != null)
3323                                 GetData.Emit (tc, Get.Block, Get);
3324
3325                         if (SetData != null)
3326                                 SetData.Emit (tc, Set.Block, Set);
3327                 }
3328         }
3329                         
3330         public class Property : PropertyBase {
3331                 const int AllowedModifiers =
3332                         Modifiers.NEW |
3333                         Modifiers.PUBLIC |
3334                         Modifiers.PROTECTED |
3335                         Modifiers.INTERNAL |
3336                         Modifiers.PRIVATE |
3337                         Modifiers.STATIC |
3338                         Modifiers.SEALED |
3339                         Modifiers.OVERRIDE |
3340                         Modifiers.ABSTRACT |
3341                         Modifiers.UNSAFE |
3342                         Modifiers.EXTERN |
3343                         Modifiers.VIRTUAL;
3344
3345                 public Property (Expression type, string name, int mod_flags,
3346                                  Accessor get_block, Accessor set_block,
3347                                  Attributes attrs, Location loc)
3348                         : base (type, name, mod_flags, AllowedModifiers,
3349                                 Parameters.EmptyReadOnlyParameters,
3350                                 get_block, set_block, attrs, loc)
3351                 {
3352                 }
3353
3354                 public override bool Define (TypeContainer parent)
3355                 {
3356                         if (!DoDefine (parent))
3357                                 return false;
3358
3359                         if (!CheckBase (parent))
3360                                 return false;
3361
3362                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3363
3364                         if (Get != null) {
3365                                 Type [] parameters = TypeManager.NoTypes;
3366
3367                                 InternalParameters ip = new InternalParameters (
3368                                         parent, Parameters.EmptyReadOnlyParameters);
3369
3370                                 GetData = new MethodData (this, "get", MemberType,
3371                                                           parameters, ip, CallingConventions.Standard,
3372                                                           Get.OptAttributes, ModFlags, flags, false);
3373
3374                                 if (!GetData.Define (parent))
3375                                         return false;
3376
3377                                 GetBuilder = GetData.MethodBuilder;
3378                         }
3379
3380                         if (Set != null) {
3381                                 Type [] parameters = new Type [1];
3382                                 parameters [0] = MemberType;
3383
3384                                 Parameter [] parms = new Parameter [1];
3385                                 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3386                                 InternalParameters ip = new InternalParameters (
3387                                         parent, new Parameters (parms, null, Location));
3388
3389                                 SetData = new MethodData (this, "set", TypeManager.void_type,
3390                                                           parameters, ip, CallingConventions.Standard,
3391                                                           Set.OptAttributes, ModFlags, flags, false);
3392
3393                                 if (!SetData.Define (parent))
3394                                         return false;
3395
3396                                 SetBuilder = SetData.MethodBuilder;
3397                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
3398                         }
3399
3400                         // FIXME - PropertyAttributes.HasDefault ?
3401                         
3402                         PropertyAttributes prop_attr =
3403                         PropertyAttributes.RTSpecialName |
3404                         PropertyAttributes.SpecialName;
3405
3406                         if (!IsExplicitImpl){
3407                                 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3408                                         Name, prop_attr, MemberType, null);
3409                                 
3410                                 if (Get != null)
3411                                         PropertyBuilder.SetGetMethod (GetBuilder);
3412                                 
3413                                 if (Set != null)
3414                                         PropertyBuilder.SetSetMethod (SetBuilder);
3415
3416                                 //
3417                                 // HACK for the reasons exposed above
3418                                 //
3419                                 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3420                                         Report.Error (
3421                                                 111, Location,
3422                                                 "Class `" + parent.Name +
3423                                                 "' already contains a definition for the property `" +
3424                                                 Name + "'");
3425                                         return false;
3426                                 }
3427                         }
3428                         return true;
3429                 }
3430         }
3431
3432         /// </summary>
3433         ///  Gigantic workaround  for lameness in SRE follows :
3434         ///  This class derives from EventInfo and attempts to basically
3435         ///  wrap around the EventBuilder so that FindMembers can quickly
3436         ///  return this in it search for members
3437         /// </summary>
3438         public class MyEventBuilder : EventInfo {
3439                 
3440                 //
3441                 // We use this to "point" to our Builder which is
3442                 // not really a MemberInfo
3443                 //
3444                 EventBuilder MyBuilder;
3445                 
3446                 //
3447                 // We "catch" and wrap these methods
3448                 //
3449                 MethodInfo raise, remove, add;
3450
3451                 EventAttributes attributes;
3452                 Type declaring_type, reflected_type, event_type;
3453                 string name;
3454
3455                 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3456                 {
3457                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3458
3459                         // And now store the values in our own fields.
3460                         
3461                         declaring_type = type_builder;
3462
3463                         reflected_type = type_builder;
3464                         
3465                         attributes = event_attr;
3466                         this.name = name;
3467                         this.event_type = event_type;
3468                 }
3469                 
3470                 //
3471                 // Methods that you have to override.  Note that you only need 
3472                 // to "implement" the variants that take the argument (those are
3473                 // the "abstract" methods, the others (GetAddMethod()) are 
3474                 // regular.
3475                 //
3476                 public override MethodInfo GetAddMethod (bool nonPublic)
3477                 {
3478                         return add;
3479                 }
3480                 
3481                 public override MethodInfo GetRemoveMethod (bool nonPublic)
3482                 {
3483                         return remove;
3484                 }
3485                 
3486                 public override MethodInfo GetRaiseMethod (bool nonPublic)
3487                 {
3488                         return raise;
3489                 }
3490                 
3491                 //
3492                 // These methods make "MyEventInfo" look like a Builder
3493                 //
3494                 public void SetRaiseMethod (MethodBuilder raiseMethod)
3495                 {
3496                         raise = raiseMethod;
3497                         MyBuilder.SetRaiseMethod (raiseMethod);
3498                 }
3499
3500                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3501                 {
3502                         remove = removeMethod;
3503                         MyBuilder.SetRemoveOnMethod (removeMethod);
3504                 }
3505
3506                 public void SetAddOnMethod (MethodBuilder addMethod)
3507                 {
3508                         add = addMethod;
3509                         MyBuilder.SetAddOnMethod (addMethod);
3510                 }
3511
3512                 public void SetCustomAttribute (CustomAttributeBuilder cb)
3513                 {
3514                         MyBuilder.SetCustomAttribute (cb);
3515                 }
3516                 
3517                 public override object [] GetCustomAttributes (bool inherit)
3518                 {
3519                         // FIXME : There's nothing which can be seemingly done here because
3520                         // we have no way of getting at the custom attribute objects of the
3521                         // EventBuilder !
3522                         return null;
3523                 }
3524
3525                 public override object [] GetCustomAttributes (Type t, bool inherit)
3526                 {
3527                         // FIXME : Same here !
3528                         return null;
3529                 }
3530
3531                 public override bool IsDefined (Type t, bool b)
3532                 {
3533                         return true;
3534                 }
3535
3536                 public override EventAttributes Attributes {
3537                         get {
3538                                 return attributes;
3539                         }
3540                 }
3541
3542                 public override string Name {
3543                         get {
3544                                 return name;
3545                         }
3546                 }
3547
3548                 public override Type DeclaringType {
3549                         get {
3550                                 return declaring_type;
3551                         }
3552                 }
3553
3554                 public override Type ReflectedType {
3555                         get {
3556                                 return reflected_type;
3557                         }
3558                 }
3559
3560                 public Type EventType {
3561                         get {
3562                                 return event_type;
3563                         }
3564                 }
3565         }
3566         
3567         public class Event : FieldBase {
3568                 const int AllowedModifiers =
3569                         Modifiers.NEW |
3570                         Modifiers.PUBLIC |
3571                         Modifiers.PROTECTED |
3572                         Modifiers.INTERNAL |
3573                         Modifiers.PRIVATE |
3574                         Modifiers.STATIC |
3575                         Modifiers.VIRTUAL |
3576                         Modifiers.SEALED |
3577                         Modifiers.OVERRIDE |
3578                         Modifiers.UNSAFE |
3579                         Modifiers.ABSTRACT;
3580
3581                 public readonly Accessor  Add;
3582                 public readonly Accessor  Remove;
3583                 public MyEventBuilder     EventBuilder;
3584
3585                 MethodBuilder AddBuilder, RemoveBuilder;
3586                 MethodData AddData, RemoveData;
3587                 
3588                 public Event (Expression type, string name, Object init, int mod, Accessor add,
3589                               Accessor remove, Attributes attrs, Location loc)
3590                         : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3591                 {
3592                         Add = add;
3593                         Remove = remove;
3594                 }
3595
3596                 public override bool Define (TypeContainer parent)
3597                 {
3598                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3599
3600                         if (!DoDefine (parent))
3601                                 return false;
3602
3603                         if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
3604                                 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3605                                               "' : event must be of a delegate type");
3606                                 return false;
3607                         }
3608
3609                         Type [] parameter_types = new Type [1];
3610                         parameter_types [0] = MemberType;
3611
3612                         Parameter [] parms = new Parameter [1];
3613                         parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3614                         InternalParameters ip = new InternalParameters (
3615                                 parent, new Parameters (parms, null, Location)); 
3616
3617                         if (!CheckBase (parent))
3618                                 return false;
3619
3620                         //
3621                         // Now define the accessors
3622                         //
3623                         AddData = new MethodData (this, "add", TypeManager.void_type,
3624                                                   parameter_types, ip, CallingConventions.Standard,
3625                                                   (Add != null) ? Add.OptAttributes : null,
3626                                                   ModFlags, flags, false);
3627
3628                         if (!AddData.Define (parent))
3629                                 return false;
3630
3631                         AddBuilder = AddData.MethodBuilder;
3632                         AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3633
3634                         RemoveData = new MethodData (this, "remove", TypeManager.void_type,
3635                                                      parameter_types, ip, CallingConventions.Standard,
3636                                                      (Remove != null) ? Remove.OptAttributes : null,
3637                                                      ModFlags, flags, false);
3638
3639                         if (!RemoveData.Define (parent))
3640                                 return false;
3641
3642                         RemoveBuilder = RemoveData.MethodBuilder;
3643                         RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3644
3645                         if (!IsExplicitImpl){
3646                                 EventBuilder = new MyEventBuilder (
3647                                         parent.TypeBuilder, Name, e_attr, MemberType);
3648                                         
3649                                 if (Add == null && Remove == null) {
3650                                         FieldBuilder = parent.TypeBuilder.DefineField (
3651                                                 Name, MemberType, FieldAttributes.FamANDAssem);
3652                                         TypeManager.RegisterPrivateFieldOfEvent (
3653                                                 (EventInfo) EventBuilder, FieldBuilder);
3654                                         TypeManager.RegisterFieldBase (FieldBuilder, this);
3655                                 }
3656                         
3657                                 EventBuilder.SetAddOnMethod (AddBuilder);
3658                                 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3659
3660                                 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3661                                         Report.Error (111, Location,
3662                                                       "Class `" + parent.Name +
3663                                                       "' already contains a definition for the event `" +
3664                                                       Name + "'");
3665                                         return false;
3666                                 }
3667                         }
3668                         
3669                         return true;
3670                 }
3671
3672                 void EmitDefaultMethod (EmitContext ec, bool is_add)
3673                 {
3674                         ILGenerator ig = ec.ig;
3675                         MethodInfo method = null;
3676                         
3677                         if (is_add)
3678                                 method = TypeManager.delegate_combine_delegate_delegate;
3679                         else
3680                                 method = TypeManager.delegate_remove_delegate_delegate;
3681
3682                         if ((ModFlags & Modifiers.STATIC) != 0) {
3683                                 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
3684                                 ig.Emit (OpCodes.Ldarg_0);
3685                                 ig.Emit (OpCodes.Call, method);
3686                                 ig.Emit (OpCodes.Castclass, MemberType);
3687                                 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
3688                         } else {
3689                                 ig.Emit (OpCodes.Ldarg_0);
3690                                 ig.Emit (OpCodes.Ldarg_0);
3691                                 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3692                                 ig.Emit (OpCodes.Ldarg_1);
3693                                 ig.Emit (OpCodes.Call, method);
3694                                 ig.Emit (OpCodes.Castclass, MemberType);
3695                                 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3696                         }
3697                         ig.Emit (OpCodes.Ret);
3698                 }
3699
3700                 public void Emit (TypeContainer tc)
3701                 {
3702                         EmitContext ec;
3703
3704                         ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
3705                         Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3706
3707                         if (Add != null)
3708                                 AddData.Emit (tc, Add.Block, Add);
3709                         else {
3710                                 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
3711                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3712                                 EmitDefaultMethod (ec, true);
3713                         }
3714
3715                         if (Remove != null)
3716                                 RemoveData.Emit (tc, Remove.Block, Remove);
3717                         else {
3718                                 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
3719                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3720                                 EmitDefaultMethod (ec, false);
3721                         }
3722                 }
3723                 
3724         }
3725
3726         //
3727         // FIXME: This does not handle:
3728         //
3729         //   int INTERFACENAME [ args ]
3730         //   Does not 
3731         //
3732         // Only:
3733         // 
3734         // int this [ args ]
3735  
3736         public class Indexer : PropertyBase {
3737
3738                 const int AllowedModifiers =
3739                         Modifiers.NEW |
3740                         Modifiers.PUBLIC |
3741                         Modifiers.PROTECTED |
3742                         Modifiers.INTERNAL |
3743                         Modifiers.PRIVATE |
3744                         Modifiers.VIRTUAL |
3745                         Modifiers.SEALED |
3746                         Modifiers.OVERRIDE |
3747                         Modifiers.UNSAFE |
3748                         Modifiers.EXTERN |
3749                         Modifiers.ABSTRACT;
3750
3751                 public string IndexerName;
3752                 public string InterfaceIndexerName;
3753
3754                 //
3755                 // Are we implementing an interface ?
3756                 //
3757                 bool IsImplementing = false;
3758                 
3759                 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
3760                                 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
3761                         : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
3762                                 attrs, loc)
3763                 {
3764                         ExplicitInterfaceName = int_type;
3765                 }
3766
3767                 public override bool Define (TypeContainer parent)
3768                 {
3769                         PropertyAttributes prop_attr =
3770                                 PropertyAttributes.RTSpecialName |
3771                                 PropertyAttributes.SpecialName;
3772                         
3773                         if (!DoDefine (parent))
3774                                 return false;
3775
3776                         IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
3777                         if (IndexerName == null)
3778                                 IndexerName = "Item";
3779                         else if (IsExplicitImpl)
3780                                 Report.Error (592, Location,
3781                                               "Attribute 'IndexerName' is not valid on this declaration " +
3782                                               "type. It is valid on `property' declarations only.");
3783
3784                         ShortName = IndexerName;
3785                         if (IsExplicitImpl) {
3786                                 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
3787                                 Name = InterfaceType.FullName + "." + IndexerName;
3788                         } else {
3789                                 InterfaceIndexerName = IndexerName;
3790                                 Name = ShortName;
3791                         }
3792
3793                         if (!CheckBase (parent))
3794                                 return false;
3795
3796                         if (Get != null){
3797                                 InternalParameters ip = new InternalParameters (parent, Parameters);
3798
3799                                 GetData = new MethodData (this, "get", MemberType,
3800                                                           ParameterTypes, ip, CallingConventions.Standard,
3801                                                           Get.OptAttributes, ModFlags, flags, false);
3802
3803                                 if (!GetData.Define (parent))
3804                                         return false;
3805
3806                                 GetBuilder = GetData.MethodBuilder;
3807                         }
3808                         
3809                         if (Set != null){
3810                                 int top = ParameterTypes.Length;
3811                                 Type [] set_pars = new Type [top + 1];
3812                                 ParameterTypes.CopyTo (set_pars, 0);
3813                                 set_pars [top] = MemberType;
3814
3815                                 Parameter [] fixed_parms = Parameters.FixedParameters;
3816
3817                                 if (fixed_parms == null){
3818                                         throw new Exception ("We currently do not support only array arguments in an indexer");
3819                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3820                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3821                                         //
3822                                         // Here is the problem: the `value' parameter has
3823                                         // to come *after* the array parameter in the declaration
3824                                         // like this:
3825                                         // X (object [] x, Type value)
3826                                         // .param [0]
3827                                         //
3828                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3829                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3830                                         
3831                                 }
3832                                 
3833                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3834
3835
3836                                 fixed_parms.CopyTo (tmp, 0);
3837                                 tmp [fixed_parms.Length] = new Parameter (
3838                                         Type, "value", Parameter.Modifier.NONE, null);
3839
3840                                 Parameters set_formal_params = new Parameters (tmp, null, Location);
3841                                 
3842                                 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3843
3844                                 SetData = new MethodData (this, "set", TypeManager.void_type,
3845                                                           set_pars, ip, CallingConventions.Standard,
3846                                                           Set.OptAttributes, ModFlags, flags, false);
3847
3848                                 if (!SetData.Define (parent))
3849                                         return false;
3850
3851                                 SetBuilder = SetData.MethodBuilder;
3852                         }
3853
3854                         //
3855                         // Now name the parameters
3856                         //
3857                         Parameter [] p = Parameters.FixedParameters;
3858                         if (p != null) {
3859                                 int i;
3860                                 
3861                                 for (i = 0; i < p.Length; ++i) {
3862                                         if (Get != null)
3863                                                 GetBuilder.DefineParameter (
3864                                                         i + 1, p [i].Attributes, p [i].Name);
3865
3866                                         if (Set != null)
3867                                                 SetBuilder.DefineParameter (
3868                                                         i + 1, p [i].Attributes, p [i].Name);
3869                                 }
3870
3871                                 if (Set != null)
3872                                         SetBuilder.DefineParameter (
3873                                                 i + 1, ParameterAttributes.None, "value");
3874                                         
3875                                 if (i != ParameterTypes.Length) {
3876                                         Parameter array_param = Parameters.ArrayParameter;
3877                                         SetBuilder.DefineParameter (
3878                                                 i + 1, array_param.Attributes, array_param.Name);
3879                                 }
3880                         }
3881
3882                         if (GetData != null)
3883                                 IsImplementing = GetData.IsImplementing;
3884                         else if (SetData != null)
3885                                 IsImplementing = SetData.IsImplementing;
3886
3887                         //
3888                         // Define the PropertyBuilder if one of the following conditions are met:
3889                         // a) we're not implementing an interface indexer.
3890                         // b) the indexer has a different IndexerName and this is no
3891                         //    explicit interface implementation.
3892                         //
3893                         if (!IsExplicitImpl) {
3894                                 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3895                                         IndexerName, prop_attr, MemberType, ParameterTypes);
3896
3897                                 if (GetData != null)
3898                                         PropertyBuilder.SetGetMethod (GetBuilder);
3899
3900                                 if (SetData != null)
3901                                         PropertyBuilder.SetSetMethod (SetBuilder);
3902                                 
3903                                 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
3904                                                              ParameterTypes);
3905                         }
3906
3907                         return true;
3908                 }
3909         }
3910
3911         public class Operator : MemberCore {
3912
3913                 const int AllowedModifiers =
3914                         Modifiers.PUBLIC |
3915                         Modifiers.UNSAFE |
3916                         Modifiers.EXTERN |
3917                         Modifiers.STATIC;
3918
3919                 const int RequiredModifiers =
3920                         Modifiers.PUBLIC |
3921                         Modifiers.STATIC;
3922
3923                 public enum OpType : byte {
3924
3925                         // Unary operators
3926                         LogicalNot,
3927                         OnesComplement,
3928                         Increment,
3929                         Decrement,
3930                         True,
3931                         False,
3932
3933                         // Unary and Binary operators
3934                         Addition,
3935                         Subtraction,
3936
3937                         UnaryPlus,
3938                         UnaryNegation,
3939                         
3940                         // Binary operators
3941                         Multiply,
3942                         Division,
3943                         Modulus,
3944                         BitwiseAnd,
3945                         BitwiseOr,
3946                         ExclusiveOr,
3947                         LeftShift,
3948                         RightShift,
3949                         Equality,
3950                         Inequality,
3951                         GreaterThan,
3952                         LessThan,
3953                         GreaterThanOrEqual,
3954                         LessThanOrEqual,
3955
3956                         // Implicit and Explicit
3957                         Implicit,
3958                         Explicit
3959                 };
3960
3961                 public readonly OpType OperatorType;
3962                 public readonly Expression ReturnType;
3963                 public readonly Expression FirstArgType, SecondArgType;
3964                 public readonly string FirstArgName, SecondArgName;
3965                 public readonly Block  Block;
3966                 public Attributes      OptAttributes;
3967                 public MethodBuilder   OperatorMethodBuilder;
3968                 
3969                 public string MethodName;
3970                 public Method OperatorMethod;
3971
3972                 public Operator (OpType type, Expression ret_type, int flags,
3973                                  Expression arg1type, string arg1name,
3974                                  Expression arg2type, string arg2name,
3975                                  Block block, Attributes attrs, Location loc)
3976                         : base ("", loc)
3977                 {
3978                         OperatorType = type;
3979                         ReturnType = ret_type;
3980                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
3981                         FirstArgType = arg1type;
3982                         FirstArgName = arg1name;
3983                         SecondArgType = arg2type;
3984                         SecondArgName = arg2name;
3985                         Block = block;
3986                         OptAttributes = attrs;
3987                 }
3988
3989                 string Prototype (TypeContainer parent)
3990                 {
3991                         return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3992                                 SecondArgType + ")";
3993                 }
3994                 
3995                 public override bool Define (TypeContainer parent)
3996                 {
3997                         int length = 1;
3998                         MethodName = "op_" + OperatorType;
3999                         
4000                         if (SecondArgType != null)
4001                                 length = 2;
4002                         
4003                         Parameter [] param_list = new Parameter [length];
4004
4005                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4006                                 Report.Error (
4007                                         558, Location, 
4008                                         "User defined operators `" +
4009                                         Prototype (parent) +
4010                                         "' must be declared static and public");
4011                                 return false;
4012                         }
4013
4014                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
4015                                                        Parameter.Modifier.NONE, null);
4016                         if (SecondArgType != null)
4017                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4018                                                                Parameter.Modifier.NONE, null);
4019                         
4020                         OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4021                                                      new Parameters (param_list, null, Location),
4022                                                      OptAttributes, Mono.CSharp.Location.Null);
4023
4024                         OperatorMethod.IsOperator = true;                       
4025                         OperatorMethod.Define (parent);
4026
4027                         if (OperatorMethod.MethodBuilder == null)
4028                                 return false;
4029                         
4030                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4031
4032                         Type [] param_types = OperatorMethod.ParameterTypes;
4033                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
4034                         Type return_type = OperatorMethod.GetReturnType (parent);
4035                         Type first_arg_type = param_types [0];
4036
4037                         // Rules for conversion operators
4038                         
4039                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4040                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
4041                                         Report.Error (
4042                                                 555, Location,
4043                                                 "User-defined conversion cannot take an object of the " +
4044                                                 "enclosing type and convert to an object of the enclosing" +
4045                                                 " type");
4046                                         return false;
4047                                 }
4048                                 
4049                                 if (first_arg_type != declaring_type && return_type != declaring_type){
4050                                         Report.Error (
4051                                                 556, Location, 
4052                                                 "User-defined conversion must convert to or from the " +
4053                                                 "enclosing type");
4054                                         return false;
4055                                 }
4056                                 
4057                                 if (first_arg_type == TypeManager.object_type ||
4058                                     return_type == TypeManager.object_type){
4059                                         Report.Error (
4060                                                 -8, Location,
4061                                                 "User-defined conversion cannot convert to or from " +
4062                                                 "object type");
4063                                         return false;
4064                                 }
4065
4066                                 if (first_arg_type.IsInterface || return_type.IsInterface){
4067                                         Report.Error (
4068                                                 552, Location,
4069                                                 "User-defined conversion cannot convert to or from an " +
4070                                                 "interface type");
4071                                         return false;
4072                                 }
4073                                 
4074                                 if (first_arg_type.IsSubclassOf (return_type) ||
4075                                     return_type.IsSubclassOf (first_arg_type)){
4076                                         Report.Error (
4077                                                 -10, Location,
4078                                                 "User-defined conversion cannot convert between types " +
4079                                                 "that derive from each other");
4080                                         return false;
4081                                 }
4082                         } else if (SecondArgType == null) {
4083                                 // Checks for Unary operators
4084                                 
4085                                 if (first_arg_type != declaring_type){
4086                                         Report.Error (
4087                                                 562, Location,
4088                                                 "The parameter of a unary operator must be the " +
4089                                                 "containing type");
4090                                         return false;
4091                                 }
4092                                 
4093                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4094                                         if (return_type != declaring_type){
4095                                                 Report.Error (
4096                                                         559, Location,
4097                                                         "The parameter and return type for ++ and -- " +
4098                                                         "must be the containing type");
4099                                                 return false;
4100                                         }
4101                                         
4102                                 }
4103                                 
4104                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4105                                         if (return_type != TypeManager.bool_type){
4106                                                 Report.Error (
4107                                                         215, Location,
4108                                                         "The return type of operator True or False " +
4109                                                         "must be bool");
4110                                                 return false;
4111                                         }
4112                                 }
4113                                 
4114                         } else {
4115                                 // Checks for Binary operators
4116                                 
4117                                 if (first_arg_type != declaring_type &&
4118                                     param_types [1] != declaring_type){
4119                                         Report.Error (
4120                                                 563, Location,
4121                                                 "One of the parameters of a binary operator must " +
4122                                                 "be the containing type");
4123                                         return false;
4124                                 }
4125                         }
4126
4127                         return true;
4128                 }
4129                 
4130                 public void Emit (TypeContainer parent)
4131                 {
4132                         EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4133                         Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4134
4135                         //
4136                         // abstract or extern methods have no bodies
4137                         //
4138                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4139                                 return;
4140                         
4141                         OperatorMethod.Block = Block;
4142                         OperatorMethod.Emit (parent);
4143                 }
4144         }
4145
4146         //
4147         // This is used to compare method signatures
4148         //
4149         struct MethodSignature {
4150                 public string Name;
4151                 public Type RetType;
4152                 public Type [] Parameters;
4153                 
4154                 /// <summary>
4155                 ///    This delegate is used to extract methods which have the
4156                 ///    same signature as the argument
4157                 /// </summary>
4158                 public static MemberFilter method_signature_filter;
4159
4160                 /// <summary>
4161                 ///   This delegate is used to extract inheritable methods which
4162                 ///   have the same signature as the argument.  By inheritable,
4163                 ///   this means that we have permissions to override the method
4164                 ///   from the current assembly and class
4165                 /// </summary>
4166                 public static MemberFilter inheritable_method_signature_filter;
4167
4168                 /// <summary>
4169                 ///   This delegate is used to extract inheritable methods which
4170                 ///   have the same signature as the argument.  By inheritable,
4171                 ///   this means that we have permissions to override the method
4172                 ///   from the current assembly and class
4173                 /// </summary>
4174                 public static MemberFilter inheritable_property_signature_filter;
4175                 
4176                 static MethodSignature ()
4177                 {
4178                         method_signature_filter = new MemberFilter (MemberSignatureCompare);
4179                         inheritable_method_signature_filter = new MemberFilter (
4180                                 InheritableMemberSignatureCompare);
4181                         inheritable_property_signature_filter = new MemberFilter (
4182                                 InheritablePropertySignatureCompare);
4183                 }
4184                 
4185                 public MethodSignature (string name, Type ret_type, Type [] parameters)
4186                 {
4187                         Name = name;
4188                         RetType = ret_type;
4189
4190                         if (parameters == null)
4191                                 Parameters = TypeManager.NoTypes;
4192                         else
4193                                 Parameters = parameters;
4194                 }
4195                 
4196                 public override int GetHashCode ()
4197                 {
4198                         return Name.GetHashCode ();
4199                 }
4200
4201                 public override bool Equals (Object o)
4202                 {
4203                         MethodSignature other = (MethodSignature) o;
4204
4205                         if (other.Name != Name)
4206                                 return false;
4207
4208                         if (other.RetType != RetType)
4209                                 return false;
4210                         
4211                         if (Parameters == null){
4212                                 if (other.Parameters == null)
4213                                         return true;
4214                                 return false;
4215                         }
4216
4217                         if (other.Parameters == null)
4218                                 return false;
4219                         
4220                         int c = Parameters.Length;
4221                         if (other.Parameters.Length != c)
4222                                 return false;
4223
4224                         for (int i = 0; i < c; i++)
4225                                 if (other.Parameters [i] != Parameters [i])
4226                                         return false;
4227
4228                         return true;
4229                 }
4230
4231                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4232                 {
4233                         MethodSignature sig = (MethodSignature) filter_criteria;
4234
4235                         if (m.Name != sig.Name)
4236                                 return false;
4237
4238                         Type ReturnType;
4239                         MethodInfo mi = m as MethodInfo;
4240                         PropertyInfo pi = m as PropertyInfo;
4241
4242                         if (mi != null)
4243                                 ReturnType = mi.ReturnType;
4244                         else if (pi != null)
4245                                 ReturnType = pi.PropertyType;
4246                         else
4247                                 return false;
4248                         
4249                         //
4250                         // we use sig.RetType == null to mean `do not check the
4251                         // method return value.  
4252                         //
4253                         if (sig.RetType != null)
4254                                 if (ReturnType != sig.RetType)
4255                                         return false;
4256
4257                         Type [] args;
4258                         if (mi != null)
4259                                 args = TypeManager.GetArgumentTypes (mi);
4260                         else
4261                                 args = TypeManager.GetArgumentTypes (pi);
4262                         Type [] sigp = sig.Parameters;
4263
4264                         if (args.Length != sigp.Length)
4265                                 return false;
4266
4267                         for (int i = args.Length; i > 0; ){
4268                                 i--;
4269                                 if (args [i] != sigp [i])
4270                                         return false;
4271                         }
4272                         return true;
4273                 }
4274
4275                 //
4276                 // This filter should be used when we are requesting methods that
4277                 // we want to override.
4278                 //
4279                 // This makes a number of assumptions, for example
4280                 // that the methods being extracted are of a parent
4281                 // class (this means we know implicitly that we are
4282                 // being called to find out about members by a derived
4283                 // class).
4284                 // 
4285                 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4286                 {
4287                         if (MemberSignatureCompare (m, filter_criteria)){
4288                                 MethodInfo mi = (MethodInfo) m;
4289                                 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4290
4291                                 // If only accessible to the current class.
4292                                 if (prot == MethodAttributes.Private)
4293                                         return false;
4294
4295                                 // If only accessible to the defining assembly or 
4296                                 if (prot == MethodAttributes.FamANDAssem ||
4297                                     prot == MethodAttributes.Assembly){
4298                                         if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4299                                                 return true;
4300                                         else
4301                                                 return false;
4302                                 }
4303
4304                                 // Anything else (FamOrAssembly and Public) is fine
4305                                 return true;
4306                         }
4307                         return false;
4308                 }
4309
4310                 //
4311                 // This filter should be used when we are requesting properties that
4312                 // we want to override.
4313                 //
4314                 // This makes a number of assumptions, for example
4315                 // that the methods being extracted are of a parent
4316                 // class (this means we know implicitly that we are
4317                 // being called to find out about members by a derived
4318                 // class).
4319                 // 
4320                 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4321                 {
4322                         if (MemberSignatureCompare (m, filter_criteria)){
4323                                 PropertyInfo pi = (PropertyInfo) m;
4324
4325                                 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4326                                 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4327
4328                                 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4329
4330                                 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4331
4332                                 // If only accessible to the current class.
4333                                 if (prot == MethodAttributes.Private)
4334                                         return false;
4335
4336                                 // If only accessible to the defining assembly or 
4337                                 if (prot == MethodAttributes.FamANDAssem ||
4338                                     prot == MethodAttributes.Assembly){
4339                                         if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4340                                                 return true;
4341                                         else
4342                                                 return false;
4343                                 }
4344
4345                                 // Anything else (FamOrAssembly and Public) is fine
4346                                 return true;
4347                         }
4348                         return false;
4349                 }
4350         }
4351 }