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