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