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