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