2002-10-09 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                                 if (ec.IsStatic)
2447                                         Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2448                                 else
2449                                         Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2450                         }
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                 public const int AllowedModifiers =
2477                         Modifiers.PUBLIC |
2478                         Modifiers.PROTECTED |
2479                         Modifiers.INTERNAL |
2480                         Modifiers.STATIC |
2481                         Modifiers.UNSAFE |
2482                         Modifiers.EXTERN |              
2483                         Modifiers.PRIVATE;
2484
2485                 //
2486                 // The spec claims that static is not permitted, but
2487                 // my very own code has static constructors.
2488                 //
2489                 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2490                         : base (null, 0, AllowedModifiers, name, null, args, l)
2491                 {
2492                         Initializer = init;
2493                 }
2494
2495                 //
2496                 // Returns true if this is a default constructor
2497                 //
2498                 public bool IsDefault ()
2499                 {
2500                         if ((ModFlags & Modifiers.STATIC) != 0)
2501                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2502                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2503                         
2504                         else
2505                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2506                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2507                                         (Initializer is ConstructorBaseInitializer) &&
2508                                         (Initializer.Arguments == null);
2509                 }
2510
2511                 //
2512                 // Creates the ConstructorBuilder
2513                 //
2514                 public override bool Define (TypeContainer parent)
2515                 {
2516                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
2517                                                MethodAttributes.SpecialName);
2518
2519                         // Check if arguments were correct.
2520                         if (!DoDefineParameters (parent))
2521                                 return false;
2522
2523                         if ((ModFlags & Modifiers.STATIC) != 0)
2524                                 ca |= MethodAttributes.Static;
2525                         else {
2526                                 if (parent is Struct && ParameterTypes.Length == 0){
2527                                         Report.Error (
2528                                                 568, Location, 
2529                                                 "Structs can not contain explicit parameterless " +
2530                                                 "constructors");
2531                                         return false;
2532                                 }
2533                                 ca |= MethodAttributes.HideBySig;
2534
2535                                 if ((ModFlags & Modifiers.PUBLIC) != 0)
2536                                         ca |= MethodAttributes.Public;
2537                                 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2538                                         if ((ModFlags & Modifiers.INTERNAL) != 0)
2539                                                 ca |= MethodAttributes.FamORAssem;
2540                                         else 
2541                                                 ca |= MethodAttributes.Family;
2542                                 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2543                                         ca |= MethodAttributes.Assembly;
2544                                 else if (IsDefault ())
2545                                         ca |= MethodAttributes.Public;
2546                                 else
2547                                         ca |= MethodAttributes.Private;
2548                         }
2549
2550                         ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2551                                 ca, GetCallingConvention (parent is Class), ParameterTypes);
2552
2553                         //
2554                         // HACK because System.Reflection.Emit is lame
2555                         //
2556                         if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2557                                 Report.Error (
2558                                         111, Location,
2559                                         "Class `" +parent.Name+ "' already contains a definition with the " +
2560                                         "same return value and parameter types for constructor `" + Name
2561                                         + "'");
2562                                 return false;
2563                         }
2564
2565                         return true;
2566                 }
2567
2568                 //
2569                 // Emits the code
2570                 //
2571                 public void Emit (TypeContainer parent)
2572                 {
2573                         ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2574                         EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2575
2576                         if ((ModFlags & Modifiers.STATIC) == 0){
2577                                 if (parent is Class && Initializer == null)
2578                                         Initializer = new ConstructorBaseInitializer (
2579                                                 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2580
2581
2582                                 //
2583                                 // Spec mandates that Initializers will not have
2584                                 // `this' access
2585                                 //
2586                                 ec.IsStatic = true;
2587                                 if (Initializer != null && !Initializer.Resolve (ec))
2588                                         return;
2589                                 ec.IsStatic = false;
2590                         }
2591
2592                         LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2593                         
2594                         //
2595                         // Classes can have base initializers and instance field initializers.
2596                         //
2597                         if (parent is Class){
2598                                 if ((ModFlags & Modifiers.STATIC) == 0)
2599                                         parent.EmitFieldInitializers (ec);
2600                         }
2601                         if (Initializer != null)
2602                                 Initializer.Emit (ec);
2603                         
2604                         if ((ModFlags & Modifiers.STATIC) != 0)
2605                                 parent.EmitFieldInitializers (ec);
2606
2607                         Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2608
2609                         // If this is a non-static `struct' constructor and doesn't have any
2610                         // initializer, it must initialize all of the struct's fields.
2611                         if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2612                             (Initializer == null))
2613                                 Block.AddThisVariable (parent, Location);
2614
2615                         ec.EmitTopBlock (Block, ParameterInfo, Location);
2616                 }
2617         }
2618
2619         public class MethodData {
2620                 //
2621                 // The return type of this method
2622                 //
2623                 public readonly Type ReturnType;
2624                 public readonly Type[] ParameterTypes;
2625                 public readonly InternalParameters ParameterInfo;
2626                 public readonly CallingConventions CallingConventions;
2627                 public readonly Attributes OptAttributes;
2628                 public readonly Location Location;
2629
2630                 //
2631                 // Are we implementing an interface ?
2632                 //
2633                 public bool IsImplementing = false;
2634
2635                 //
2636                 // Protected data.
2637                 //
2638                 protected MemberBase member;
2639                 protected int modifiers;
2640                 protected MethodAttributes flags;
2641                 protected bool is_method;
2642                 protected string accessor_name;
2643                 ArrayList conditionals;
2644
2645                 MethodBuilder builder = null;
2646                 public MethodBuilder MethodBuilder {
2647                         get {
2648                                 return builder;
2649                         }
2650                 }
2651
2652                 public MethodData (MemberBase member, string name, Type return_type,
2653                                    Type [] parameter_types, InternalParameters parameters,
2654                                    CallingConventions cc, Attributes opt_attrs,
2655                                    int modifiers, MethodAttributes flags, bool is_method)
2656                 {
2657                         this.member = member;
2658                         this.accessor_name = name;
2659                         this.ReturnType = return_type;
2660                         this.ParameterTypes = parameter_types;
2661                         this.ParameterInfo = parameters;
2662                         this.CallingConventions = cc;
2663                         this.OptAttributes = opt_attrs;
2664                         this.modifiers = modifiers;
2665                         this.flags = flags;
2666                         this.is_method = is_method;
2667                         this.Location = member.Location;
2668                         this.conditionals = new ArrayList ();
2669                 }
2670
2671                 //
2672                 // Attributes.
2673                 //
2674                 Attribute dllimport_attribute = null;
2675                 string obsolete = null;
2676                 bool obsolete_error = false;
2677
2678                 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2679                 {
2680                         if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2681                                 return true;
2682
2683                         foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2684                                 if (asec.Attributes == null)
2685                                         continue;
2686                                         
2687                                 foreach (Attribute a in asec.Attributes) {
2688                                         if (a.Name == "Conditional") {
2689                                                 if (!ApplyConditionalAttribute (a))
2690                                                         return false;
2691                                         } else if (a.Name == "Obsolete") {
2692                                                 if (!ApplyObsoleteAttribute (a))
2693                                                         return false;
2694                                         } else if (a.Name.IndexOf ("DllImport") != -1) {
2695                                                 if (!is_method) {
2696                                                         a.Type = TypeManager.dllimport_type;
2697                                                         Attribute.Error_AttributeNotValidForElement (a, Location);
2698                                                         return false;
2699                                                 }
2700                                                 if (!ApplyDllImportAttribute (a))
2701                                                         return false;
2702                                         }
2703                                 }
2704                         }
2705
2706                         return true;
2707                 }
2708
2709                 //
2710                 // Applies the `DllImport' attribute to the method.
2711                 //
2712                 protected virtual bool ApplyDllImportAttribute (Attribute a)
2713                 {
2714                         const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2715                         if ((modifiers & extern_static) != extern_static) {
2716                                 Report.Error (601, Location,
2717                                               "The DllImport attribute must be specified on a method " +
2718                                               "marked `static' and `extern'.");
2719                                 return false;
2720                         }
2721
2722                         flags |= MethodAttributes.PinvokeImpl;
2723                         dllimport_attribute = a;
2724                         return true;
2725                 }
2726
2727                 //
2728                 // Applies the `Obsolete' attribute to the method.
2729                 //
2730                 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2731                 {
2732                         if (obsolete != null) {
2733                                 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2734                                 return false;
2735                         }
2736
2737                         obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2738                         return obsolete != null;
2739                 }
2740
2741                 //
2742                 // Applies the `Conditional' attribute to the method.
2743                 //
2744                 protected virtual bool ApplyConditionalAttribute (Attribute a)
2745                 {
2746                         // The Conditional attribute is only valid on methods.
2747                         if (!is_method) {
2748                                 Attribute.Error_AttributeNotValidForElement (a, Location);
2749                                 return false;
2750                         }
2751
2752                         string condition = a.Conditional_GetConditionName ();
2753
2754                         if (condition == null)
2755                                 return false;
2756
2757                         if (ReturnType != TypeManager.void_type) {
2758                                 Report.Error (578, Location,
2759                                               "Conditional not valid on `" + member.Name + "' " +
2760                                               "because its return type is not void");
2761                                 return false;
2762                         }
2763
2764                         if ((modifiers & Modifiers.OVERRIDE) != 0) {
2765                                 Report.Error (243, Location,
2766                                               "Conditional not valid on `" + member.Name + "' " +
2767                                               "because it is an override method");
2768                                 return false;
2769                         }
2770
2771                         if (member.IsExplicitImpl) {
2772                                 Report.Error (577, Location,
2773                                               "Conditional not valid on `" + member.Name + "' " +
2774                                               "because it is an explicit interface implementation");
2775                                 return false;
2776                         }
2777
2778                         if (IsImplementing) {
2779                                 Report.Error (623, Location,
2780                                               "Conditional not valid on `" + member.Name + "' " +
2781                                               "because it is an interface method");
2782                                 return false;
2783                         }
2784
2785                         conditionals.Add (condition);
2786
2787                         return true;
2788                 }
2789
2790                 //
2791                 // Checks whether this method should be ignored due to its Conditional attributes.
2792                 //
2793                 bool ShouldIgnore (Location loc)
2794                 {
2795                         // When we're overriding a virtual method, we implicitly inherit the
2796                         // Conditional attributes from our parent.
2797                         if (member.ParentMethod != null) {
2798                                 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2799                                         member.ParentMethod, loc);
2800
2801                                 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2802                                         return true;
2803                         }
2804
2805                         foreach (string condition in conditionals)
2806                                 if (RootContext.AllDefines [condition] == null)
2807                                         return true;
2808
2809                         return false;
2810                 }
2811
2812                 //
2813                 // Returns the TypeManager.MethodFlags for this method.
2814                 // This emits an error 619 / warning 618 if the method is obsolete.
2815                 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2816                 //
2817                 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2818                 {
2819                         TypeManager.MethodFlags flags = 0;
2820
2821                         if (obsolete != null) {
2822                                 if (obsolete_error) {
2823                                         Report.Error (619, loc, "Method `" + member.Name +
2824                                                       "' is obsolete: `" + obsolete + "'");
2825                                         return TypeManager.MethodFlags.IsObsoleteError;
2826                                 } else
2827                                         Report.Warning (618, loc, "Method `" + member.Name +
2828                                                         "' is obsolete: `" + obsolete + "'");
2829
2830                                 flags |= TypeManager.MethodFlags.IsObsolete;
2831                         }
2832
2833                         if (ShouldIgnore (loc))
2834                             flags |= TypeManager.MethodFlags.ShouldIgnore;
2835
2836                         return flags;
2837                 }
2838
2839                 public virtual bool Define (TypeContainer parent)
2840                 {
2841                         MethodInfo implementing = null;
2842                         string method_name, name, prefix;
2843
2844                         if (OptAttributes != null)
2845                                 if (!ApplyAttributes (OptAttributes, is_method))
2846                                         return false;
2847
2848                         if (member.IsExplicitImpl)
2849                                 prefix = member.InterfaceType.FullName + ".";
2850                         else
2851                                 prefix = "";
2852
2853                         if (accessor_name != null)
2854                                 name = accessor_name + "_" + member.ShortName;
2855                         else
2856                                 name = member.ShortName;
2857                         method_name = prefix + name;
2858
2859                         if (parent.Pending != null){
2860                                 if (member is Indexer)
2861                                         implementing = parent.Pending.IsInterfaceIndexer (
2862                                                 member.InterfaceType, ReturnType, ParameterTypes);
2863                                 else
2864                                         implementing = parent.Pending.IsInterfaceMethod (
2865                                                 member.InterfaceType, name, ReturnType, ParameterTypes);
2866
2867                                 if (member.InterfaceType != null && implementing == null){
2868                                         TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2869                                                 Location, name);
2870                                         return false;
2871                                 }
2872                         }
2873
2874                         //
2875                         // For implicit implementations, make sure we are public, for
2876                         // explicit implementations, make sure we are private.
2877                         //
2878                         if (implementing != null){
2879                                 //
2880                                 // Setting null inside this block will trigger a more
2881                                 // verbose error reporting for missing interface implementations
2882                                 //
2883                                 // The "candidate" function has been flagged already
2884                                 // but it wont get cleared
2885                                 //
2886                                 if (!member.IsExplicitImpl){
2887                                         //
2888                                         // We already catch different accessibility settings
2889                                         // so we just need to check that we are not private
2890                                         //
2891                                         if ((modifiers & Modifiers.PRIVATE) != 0)
2892                                                 implementing = null;
2893                                         
2894                                         //
2895                                         // Static is not allowed
2896                                         //
2897                                         if ((modifiers & Modifiers.STATIC) != 0)
2898                                                 implementing = null;
2899                                 } else {
2900                                         if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2901                                                 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2902                                                 implementing = null;
2903                                         }
2904                                 }
2905                         }
2906                         
2907                         //
2908                         // If implementing is still valid, set flags
2909                         //
2910                         if (implementing != null){
2911                                 //
2912                                 // When implementing interface methods, set NewSlot.
2913                                 //
2914                                 if (implementing.DeclaringType.IsInterface)
2915                                         flags |= MethodAttributes.NewSlot;
2916
2917                                 flags |=
2918                                         MethodAttributes.Virtual |
2919                                         MethodAttributes.HideBySig;
2920
2921                                 // Get the method name from the explicit interface.
2922                                 if (member.InterfaceType != null) {
2923                                         name = implementing.Name;
2924                                         method_name = prefix + name;
2925                                 }
2926
2927                                 IsImplementing = true;
2928                         }
2929
2930                         //
2931                         // Create the MethodBuilder for the method
2932                         //
2933                         if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2934                                 if ((modifiers & Modifiers.STATIC) == 0) {
2935                                         Report.Error (601, Location,
2936                                                       "The DllImport attribute must be specified on " +
2937                                                       "a method marked 'static' and 'extern'.");
2938                                         return false;
2939                                 }
2940                                 
2941                                 EmitContext ec = new EmitContext (
2942                                         parent, Location, null, ReturnType, modifiers);
2943                                 
2944                                 builder = dllimport_attribute.DefinePInvokeMethod (
2945                                         ec, parent.TypeBuilder, method_name, flags,
2946                                         ReturnType, ParameterTypes);
2947                         } else
2948                                 builder = parent.TypeBuilder.DefineMethod (
2949                                         method_name, flags, CallingConventions,
2950                                         ReturnType, ParameterTypes);
2951
2952                         if (builder == null)
2953                                 return false;
2954
2955                         if (IsImplementing) {
2956                                 //
2957                                 // clear the pending implemntation flag
2958                                 //
2959                                 if (member is Indexer) {
2960                                         parent.Pending.ImplementIndexer (
2961                                                 member.InterfaceType, builder, ReturnType,
2962                                                 ParameterTypes, true);
2963                                 } else
2964                                         parent.Pending.ImplementMethod (
2965                                                 member.InterfaceType, name, ReturnType,
2966                                                 ParameterTypes, member.IsExplicitImpl);
2967
2968                                 if (member.IsExplicitImpl)
2969                                         parent.TypeBuilder.DefineMethodOverride (
2970                                                 builder, implementing);
2971                         }
2972
2973                         if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
2974                                 Report.Error (111, Location,
2975                                               "Class `" + parent.Name +
2976                                               "' already contains a definition with the " +
2977                                               "same return value and parameter types as the " +
2978                                               "'get' method of property `" + member.Name + "'");
2979                                 return false;
2980                         }
2981
2982                         TypeManager.AddMethod (builder, this);
2983
2984                         return true;
2985                 }
2986
2987                 //
2988                 // Emits the code
2989                 // 
2990                 public virtual void Emit (TypeContainer parent, Block block, object kind)
2991                 {
2992                         ILGenerator ig;
2993                         EmitContext ec;
2994
2995                         if ((flags & MethodAttributes.PinvokeImpl) == 0)
2996                                 ig = builder.GetILGenerator ();
2997                         else
2998                                 ig = null;
2999
3000                         ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3001
3002                         if (OptAttributes != null)
3003                                 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3004
3005                         if (member is MethodCore)
3006                                 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
3007
3008                         //
3009                         // abstract or extern methods have no bodies
3010                         //
3011                         if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3012                                 if (block == null)
3013                                         return;
3014
3015                                 //
3016                                 // abstract or extern methods have no bodies.
3017                                 //
3018                                 if ((modifiers & Modifiers.ABSTRACT) != 0)
3019                                         Report.Error (
3020                                                 500, Location, "Abstract method `" +
3021                                                 TypeManager.CSharpSignature (builder) +
3022                                                 "' can not have a body");
3023
3024                                 if ((modifiers & Modifiers.EXTERN) != 0)
3025                                         Report.Error (
3026                                                 179, Location, "External method `" +
3027                                                 TypeManager.CSharpSignature (builder) +
3028                                                 "' can not have a body");
3029
3030                                 return;
3031                         }
3032
3033                         //
3034                         // Methods must have a body unless they're extern or abstract
3035                         //
3036                         if (block == null) {
3037                                 Report.Error (
3038                                         501, Location, "Method `" +
3039                                         TypeManager.CSharpSignature (builder) +
3040                                         "' must declare a body since it is not marked " +
3041                                         "abstract or extern");
3042                                 return;
3043                         }
3044
3045                         //
3046                         // Handle destructors specially
3047                         //
3048                         // FIXME: This code generates buggy code
3049                         //
3050                         if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3051                                 EmitDestructor (ec, block);
3052                         else {
3053                                 ISymbolWriter sw = CodeGen.SymbolWriter;
3054
3055                                 if ((sw != null) && !Location.IsNull (Location) &&
3056                                     !Location.IsNull (block.EndLocation)) {
3057                                         Location end = block.EndLocation;
3058                                         MethodToken token = MethodBuilder.GetToken ();
3059                                         sw.OpenMethod (new SymbolToken (token.Token));
3060                                         sw.SetMethodSourceRange (Location.SymbolDocument,
3061                                                                  Location.Row, 0,
3062                                                                  end.SymbolDocument,
3063                                                                  end.Row, 0);
3064
3065                                         ec.EmitTopBlock (block, ParameterInfo, Location);
3066
3067                                         sw.CloseMethod ();
3068                                 } else
3069                                         ec.EmitTopBlock (block, ParameterInfo, Location);
3070                         }
3071                 }
3072
3073                 void EmitDestructor (EmitContext ec, Block block)
3074                 {
3075                         ILGenerator ig = ec.ig;
3076                         
3077                         Label finish = ig.DefineLabel ();
3078                         bool old_in_try = ec.InTry;
3079                         
3080                         ig.BeginExceptionBlock ();
3081                         ec.InTry = true;
3082                         ec.ReturnLabel = finish;
3083                         ec.HasReturnLabel = true;
3084                         ec.EmitTopBlock (block, null, Location);
3085                         ec.InTry = old_in_try;
3086                         
3087                         // ig.MarkLabel (finish);
3088                         bool old_in_finally = ec.InFinally;
3089                         ec.InFinally = true;
3090                         ig.BeginFinallyBlock ();
3091                         
3092                         if (ec.ContainerType.BaseType != null) {
3093                                 Expression member_lookup = Expression.MemberLookup (
3094                                         ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3095                                         MemberTypes.Method, Expression.AllBindingFlags, Location);
3096
3097                                 if (member_lookup != null){
3098                                         MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3099                                 
3100                                         ig.Emit (OpCodes.Ldarg_0);
3101                                         ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3102                                 }
3103                         }
3104                         ec.InFinally = old_in_finally;
3105                         
3106                         ig.EndExceptionBlock ();
3107                         //ig.MarkLabel (ec.ReturnLabel);
3108                         ig.Emit (OpCodes.Ret);
3109                 }
3110         }
3111
3112         abstract public class MemberBase : MemberCore {
3113                 public Expression Type;
3114                 public readonly Attributes OptAttributes;
3115
3116                 protected MethodAttributes flags;
3117
3118                 //
3119                 // The "short" name of this property / indexer / event.  This is the
3120                 // name without the explicit interface.
3121                 //
3122                 public string ShortName;
3123
3124                 //
3125                 // The type of this property / indexer / event
3126                 //
3127                 public Type MemberType;
3128
3129                 //
3130                 // If true, this is an explicit interface implementation
3131                 //
3132                 public bool IsExplicitImpl = false;
3133
3134                 //
3135                 // The name of the interface we are explicitly implementing
3136                 //
3137                 public string ExplicitInterfaceName = null;
3138
3139                 //
3140                 // If true, the interface type we are explicitly implementing
3141                 //
3142                 public Type InterfaceType = null;
3143
3144                 //
3145                 // The method we're overriding if this is an override method.
3146                 //
3147                 protected MethodInfo parent_method = null;
3148                 public MethodInfo ParentMethod {
3149                         get {
3150                                 return parent_method;
3151                         }
3152                 }
3153
3154                 //
3155                 // The constructor is only exposed to our children
3156                 //
3157                 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3158                                       Attributes attrs, Location loc)
3159                         : base (name, loc)
3160                 {
3161                         Type = type;
3162                         ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
3163                         OptAttributes = attrs;
3164                 }
3165
3166                 protected virtual bool CheckBase (TypeContainer parent)
3167                 {
3168                         return true;
3169                 }
3170
3171                 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3172                 {
3173                         bool error = false;
3174
3175                         foreach (Type partype in parameters){
3176                                 if (partype.IsPointer && !UnsafeOK (parent))
3177                                         error = true;
3178
3179                                 if (parent.AsAccessible (partype, ModFlags))
3180                                         continue;
3181
3182                                 if (this is Indexer)
3183                                         Report.Error (55, Location,
3184                                                       "Inconsistent accessibility: parameter type `" +
3185                                                       TypeManager.CSharpName (partype) + "' is less " +
3186                                                       "accessible than indexer `" + Name + "'");
3187                                 else
3188                                         Report.Error (51, Location,
3189                                                       "Inconsistent accessibility: parameter type `" +
3190                                                       TypeManager.CSharpName (partype) + "' is less " +
3191                                                       "accessible than method `" + Name + "'");
3192                                 error = true;
3193                         }
3194
3195                         return !error;
3196                 }
3197
3198                 protected virtual bool DoDefine (TypeContainer parent)
3199                 {
3200                         if (Name == null)
3201                                 Name = "this";
3202
3203                         if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3204                                 return false;
3205
3206                         flags = Modifiers.MethodAttr (ModFlags);
3207
3208                         // Lookup Type, verify validity
3209                         MemberType = parent.ResolveType (Type, false, Location);
3210                         if (MemberType == null)
3211                                 return false;
3212
3213                         // verify accessibility
3214                         if (!parent.AsAccessible (MemberType, ModFlags)) {
3215                                 if (this is Property)
3216                                         Report.Error (53, Location,
3217                                                       "Inconsistent accessibility: property type `" +
3218                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3219                                                       "accessible than property `" + Name + "'");
3220                                 else if (this is Indexer)
3221                                         Report.Error (54, Location,
3222                                                       "Inconsistent accessibility: indexer return type `" +
3223                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3224                                                       "accessible than indexer `" + Name + "'");
3225                                 else if (this is Method)
3226                                         Report.Error (50, Location,
3227                                                       "Inconsistent accessibility: return type `" +
3228                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3229                                                       "accessible than method `" + Name + "'");
3230                                 else
3231                                         Report.Error (52, Location,
3232                                                       "Inconsistent accessibility: field type `" +
3233                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3234                                                       "accessible than field `" + Name + "'");
3235                                 return false;
3236                         }
3237
3238                         if (MemberType.IsPointer && !UnsafeOK (parent))
3239                                 return false;
3240                         
3241                         //
3242                         // Check for explicit interface implementation
3243                         //
3244                         if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3245                                 int pos = Name.LastIndexOf (".");
3246
3247                                 ExplicitInterfaceName = Name.Substring (0, pos);
3248                                 ShortName = Name.Substring (pos + 1);
3249                         } else
3250                                 ShortName = Name;
3251
3252                         if (ExplicitInterfaceName != null) {
3253                                 InterfaceType  = RootContext.LookupType (
3254                                         parent, ExplicitInterfaceName, false, Location);
3255                                 if (InterfaceType == null)
3256                                         return false;
3257
3258                                 // Compute the full name that we need to export.
3259                                 Name = InterfaceType.FullName + "." + ShortName;
3260                                 
3261                                 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3262                                         return false;
3263                                 
3264                                 IsExplicitImpl = true;
3265                         } else
3266                                 IsExplicitImpl = false;
3267
3268                         return true;
3269                 }
3270         }
3271
3272         //
3273         // Fields and Events both generate FieldBuilders, we use this to share 
3274         // their common bits.  This is also used to flag usage of the field
3275         //
3276         abstract public class FieldBase : MemberBase {
3277                 public FieldBuilder  FieldBuilder;
3278                 public Status status;
3279
3280                 [Flags]
3281                 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3282
3283                 //
3284                 // The constructor is only exposed to our children
3285                 //
3286                 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3287                                      object init, Attributes attrs, Location loc)
3288                         : base (type, mod, allowed_mod, name, attrs, loc)
3289                 {
3290                         this.init = init;
3291                 }
3292
3293                 //
3294                 // Whether this field has an initializer.
3295                 //
3296                 public bool HasInitializer {
3297                         get {
3298                                 return init != null;
3299                         }
3300                 }
3301
3302                 // Private.
3303                 readonly Object init;
3304                 Expression init_expr;
3305                 bool init_expr_initialized = false;
3306
3307                 //
3308                 // Resolves and returns the field initializer.
3309                 //
3310                 public Expression GetInitializerExpression (EmitContext ec)
3311                 {
3312                         if (init_expr_initialized)
3313                                 return init_expr;
3314
3315                         Expression e;
3316                         if (init is Expression)
3317                                 e = (Expression) init;
3318                         else
3319                                 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3320
3321                         ec.IsFieldInitializer = true;
3322                         e = e.DoResolve (ec);
3323                         ec.IsFieldInitializer = false;
3324
3325                         init_expr = e;
3326                         init_expr_initialized = true;
3327
3328                         return init_expr;
3329                 }
3330         }
3331
3332         //
3333         // The Field class is used to represents class/struct fields during parsing.
3334         //
3335         public class Field : FieldBase {
3336                 // <summary>
3337                 //   Modifiers allowed in a class declaration
3338                 // </summary>
3339                 const int AllowedModifiers =
3340                         Modifiers.NEW |
3341                         Modifiers.PUBLIC |
3342                         Modifiers.PROTECTED |
3343                         Modifiers.INTERNAL |
3344                         Modifiers.PRIVATE |
3345                         Modifiers.STATIC |
3346                         Modifiers.VOLATILE |
3347                         Modifiers.UNSAFE |
3348                         Modifiers.READONLY;
3349
3350                 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3351                               Attributes attrs, Location loc)
3352                         : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3353                 {
3354                 }
3355
3356                 public override bool Define (TypeContainer parent)
3357                 {
3358                         Type t = parent.ResolveType (Type, false, Location);
3359                         
3360                         if (t == null)
3361                                 return false;
3362
3363                         if (!parent.AsAccessible (t, ModFlags)) {
3364                                 Report.Error (52, Location,
3365                                               "Inconsistent accessibility: field type `" +
3366                                               TypeManager.CSharpName (t) + "' is less " +
3367                                               "accessible than field `" + Name + "'");
3368                                 return false;
3369                         }
3370
3371                         if (t.IsPointer && !UnsafeOK (parent))
3372                                 return false;
3373                                 
3374                         if (RootContext.WarningLevel > 1){
3375                                 Type ptype = parent.TypeBuilder.BaseType;
3376
3377                                 // ptype is only null for System.Object while compiling corlib.
3378                                 if (ptype != null){
3379                                         TypeContainer.FindMembers (
3380                                                 ptype, MemberTypes.Method,
3381                                                 BindingFlags.Public |
3382                                                 BindingFlags.Static | BindingFlags.Instance,
3383                                                 System.Type.FilterName, Name);
3384                                 }
3385                         }
3386
3387                         if ((ModFlags & Modifiers.VOLATILE) != 0){
3388                                 if (!t.IsClass){
3389                                         if (TypeManager.IsEnumType (t))
3390                                                 t = TypeManager.EnumToUnderlying (t);
3391
3392                                         if (!((t == TypeManager.bool_type) ||
3393                                               (t == TypeManager.sbyte_type) ||
3394                                               (t == TypeManager.byte_type) ||
3395                                               (t == TypeManager.short_type) ||    
3396                                               (t == TypeManager.ushort_type) ||
3397                                               (t == TypeManager.int32_type) ||    
3398                                               (t == TypeManager.uint32_type) ||    
3399                                               (t == TypeManager.char_type) ||    
3400                                               (t == TypeManager.float_type))){
3401                                                 Report.Error (
3402                                                         677, Location, parent.MakeName (Name) +
3403                                                         " A volatile field can not be of type `" +
3404                                                         TypeManager.CSharpName (t) + "'");
3405                                                 return false;
3406                                         }
3407                                 }
3408                         }
3409
3410                         FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3411
3412                         if (parent is Struct && 
3413                             ((fa & FieldAttributes.Static) == 0) &&
3414                             t == parent.TypeBuilder &&
3415                             !TypeManager.IsBuiltinType (t)){
3416                                 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name + 
3417                                               "' causes a cycle in the structure layout");
3418                                 return false;
3419                         }
3420                         FieldBuilder = parent.TypeBuilder.DefineField (
3421                                 Name, t, Modifiers.FieldAttr (ModFlags));
3422
3423                         TypeManager.RegisterFieldBase (FieldBuilder, this);
3424                         return true;
3425                 }
3426
3427                 public void Emit (TypeContainer tc)
3428                 {
3429                         EmitContext ec = new EmitContext (tc, Location, null,
3430                                                           FieldBuilder.FieldType, ModFlags);
3431
3432                         Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3433                 }
3434         }
3435
3436         //
3437         // `set' and `get' accessors are represented with an Accessor.
3438         // 
3439         public class Accessor {
3440                 //
3441                 // Null if the accessor is empty, or a Block if not
3442                 //
3443                 public Block Block;
3444                 public Attributes OptAttributes;
3445                 
3446                 public Accessor (Block b, Attributes attrs)
3447                 {
3448                         Block = b;
3449                         OptAttributes = attrs;
3450                 }
3451         }
3452
3453         //
3454         // Properties and Indexers both generate PropertyBuilders, we use this to share 
3455         // their common bits.
3456         //
3457         abstract public class PropertyBase : MethodCore {
3458                 public Accessor Get, Set;
3459                 public PropertyBuilder PropertyBuilder;
3460                 public MethodBuilder GetBuilder, SetBuilder;
3461                 public MethodData GetData, SetData;
3462
3463                 protected EmitContext ec;
3464
3465                 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3466                                      Parameters parameters, Accessor get_block, Accessor set_block,
3467                                      Attributes attrs, Location loc)
3468                         : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3469                 {
3470                         Get = get_block;
3471                         Set = set_block;
3472                 }
3473
3474                 protected override bool DoDefine (TypeContainer parent)
3475                 {
3476                         if (!base.DoDefine (parent))
3477                                 return false;
3478
3479                         ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3480
3481                         return true;
3482                 }
3483
3484                 //
3485                 // Checks our base implementation if any
3486                 //
3487                 protected override bool CheckBase (TypeContainer parent)
3488                 {
3489                         // Check whether arguments were correct.
3490                         if (!DoDefineParameters (parent))
3491                                 return false;
3492
3493                         if (IsExplicitImpl)
3494                                 return true;
3495
3496                         string report_name;
3497                         MethodSignature ms, base_ms;
3498                         if (this is Indexer) {
3499                                 string name, base_name;
3500
3501                                 report_name = "this";
3502                                 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3503                                 ms = new MethodSignature (name, null, ParameterTypes);
3504                                 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3505                                 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3506                         } else {
3507                                 report_name = Name;
3508                                 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3509                         }
3510
3511                         MemberList props_this;
3512
3513                         props_this = TypeContainer.FindMembers (
3514                                 parent.TypeBuilder, MemberTypes.Property,
3515                                 BindingFlags.NonPublic | BindingFlags.Public |
3516                                 BindingFlags.Static | BindingFlags.Instance |
3517                                 BindingFlags.DeclaredOnly,
3518                                 MethodSignature.method_signature_filter, ms);
3519
3520                         if (props_this.Count > 0) {
3521                                 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3522                                               "already defines a member called `" + report_name + "' " +
3523                                               "with the same parameter types");
3524                                 return false;
3525                         }
3526
3527                         //
3528                         // Find properties with the same name on the base class
3529                         //
3530                         MemberList props;
3531                         MemberList props_static = TypeContainer.FindMembers (
3532                                 parent.TypeBuilder.BaseType, MemberTypes.Property,
3533                                 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3534                                 MethodSignature.inheritable_property_signature_filter, base_ms);
3535
3536                         MemberList props_instance = TypeContainer.FindMembers (
3537                                 parent.TypeBuilder.BaseType, MemberTypes.Property,
3538                                 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3539                                 MethodSignature.inheritable_property_signature_filter,
3540                                 base_ms);
3541
3542                         //
3543                         // Find if we have anything
3544                         //
3545                         if (props_static.Count > 0)
3546                                 props = props_static;
3547                         else if (props_instance.Count > 0)
3548                                 props = props_instance;
3549                         else
3550                                 props = null;
3551
3552                         //
3553                         // If we have something on the base.
3554                         if (props != null && props.Count > 0){
3555                                 PropertyInfo pi = (PropertyInfo) props [0];
3556
3557                                 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
3558                                 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
3559
3560                                 MethodInfo reference = inherited_get == null ?
3561                                         inherited_set : inherited_get;
3562                                 
3563                                 if (reference != null) {
3564                                         string name = reference.DeclaringType.Name + "." + report_name;
3565
3566                                         if (!CheckMethodAgainstBase (parent, flags, reference, name))
3567                                                 return false;
3568                                 }
3569
3570                                 if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
3571                                         Report.Error (508, parent.MakeName (Name) + ": cannot " +
3572                                                       "change return type when overriding inherited " +
3573                                                       "member `" + pi.DeclaringType + "." + pi.Name + "'");
3574                                         return false;
3575                                 }
3576                         } else {
3577                                 if ((ModFlags & Modifiers.NEW) != 0)
3578                                         WarningNotHiding (parent);
3579                                 
3580                                 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3581                                         if (this is Indexer)
3582                                                 Report.Error (115, Location,
3583                                                               parent.MakeName (Name) +
3584                                                               " no suitable indexers found to override");
3585                                         else
3586                                                 Report.Error (115, Location,
3587                                                               parent.MakeName (Name) +
3588                                                               " no suitable properties found to override");
3589                                         return false;
3590                                 }
3591                         }
3592                         return true;
3593                 }
3594
3595                 public void Emit (TypeContainer tc)
3596                 {
3597                         //
3598                         // The PropertyBuilder can be null for explicit implementations, in that
3599                         // case, we do not actually emit the ".property", so there is nowhere to
3600                         // put the attribute
3601                         //
3602                         if (PropertyBuilder != null)
3603                                 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3604
3605                         if (GetData != null)
3606                                 GetData.Emit (tc, Get.Block, Get);
3607
3608                         if (SetData != null)
3609                                 SetData.Emit (tc, Set.Block, Set);
3610                 }
3611         }
3612                         
3613         public class Property : PropertyBase {
3614                 const int AllowedModifiers =
3615                         Modifiers.NEW |
3616                         Modifiers.PUBLIC |
3617                         Modifiers.PROTECTED |
3618                         Modifiers.INTERNAL |
3619                         Modifiers.PRIVATE |
3620                         Modifiers.STATIC |
3621                         Modifiers.SEALED |
3622                         Modifiers.OVERRIDE |
3623                         Modifiers.ABSTRACT |
3624                         Modifiers.UNSAFE |
3625                         Modifiers.EXTERN |
3626                         Modifiers.VIRTUAL;
3627
3628                 public Property (Expression type, string name, int mod_flags,
3629                                  Accessor get_block, Accessor set_block,
3630                                  Attributes attrs, Location loc)
3631                         : base (type, name, mod_flags, AllowedModifiers,
3632                                 Parameters.EmptyReadOnlyParameters,
3633                                 get_block, set_block, attrs, loc)
3634                 {
3635                 }
3636
3637                 public override bool Define (TypeContainer parent)
3638                 {
3639                         if (!DoDefine (parent))
3640                                 return false;
3641
3642                         if (!CheckBase (parent))
3643                                 return false;
3644
3645                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3646
3647                         if (Get != null) {
3648                                 Type [] parameters = TypeManager.NoTypes;
3649
3650                                 InternalParameters ip = new InternalParameters (
3651                                         parent, Parameters.EmptyReadOnlyParameters);
3652
3653                                 GetData = new MethodData (this, "get", MemberType,
3654                                                           parameters, ip, CallingConventions.Standard,
3655                                                           Get.OptAttributes, ModFlags, flags, false);
3656
3657                                 if (!GetData.Define (parent))
3658                                         return false;
3659
3660                                 GetBuilder = GetData.MethodBuilder;
3661                         }
3662
3663                         if (Set != null) {
3664                                 Type [] parameters = new Type [1];
3665                                 parameters [0] = MemberType;
3666
3667                                 Parameter [] parms = new Parameter [1];
3668                                 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3669                                 InternalParameters ip = new InternalParameters (
3670                                         parent, new Parameters (parms, null, Location));
3671
3672                                 SetData = new MethodData (this, "set", TypeManager.void_type,
3673                                                           parameters, ip, CallingConventions.Standard,
3674                                                           Set.OptAttributes, ModFlags, flags, false);
3675
3676                                 if (!SetData.Define (parent))
3677                                         return false;
3678
3679                                 SetBuilder = SetData.MethodBuilder;
3680                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
3681                         }
3682
3683                         // FIXME - PropertyAttributes.HasDefault ?
3684                         
3685                         PropertyAttributes prop_attr =
3686                         PropertyAttributes.RTSpecialName |
3687                         PropertyAttributes.SpecialName;
3688
3689                         if (!IsExplicitImpl){
3690                                 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3691                                         Name, prop_attr, MemberType, null);
3692                                 
3693                                 if (Get != null)
3694                                         PropertyBuilder.SetGetMethod (GetBuilder);
3695                                 
3696                                 if (Set != null)
3697                                         PropertyBuilder.SetSetMethod (SetBuilder);
3698
3699                                 //
3700                                 // HACK for the reasons exposed above
3701                                 //
3702                                 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3703                                         Report.Error (
3704                                                 111, Location,
3705                                                 "Class `" + parent.Name +
3706                                                 "' already contains a definition for the property `" +
3707                                                 Name + "'");
3708                                         return false;
3709                                 }
3710                         }
3711                         return true;
3712                 }
3713         }
3714
3715         /// </summary>
3716         ///  Gigantic workaround  for lameness in SRE follows :
3717         ///  This class derives from EventInfo and attempts to basically
3718         ///  wrap around the EventBuilder so that FindMembers can quickly
3719         ///  return this in it search for members
3720         /// </summary>
3721         public class MyEventBuilder : EventInfo {
3722                 
3723                 //
3724                 // We use this to "point" to our Builder which is
3725                 // not really a MemberInfo
3726                 //
3727                 EventBuilder MyBuilder;
3728                 
3729                 //
3730                 // We "catch" and wrap these methods
3731                 //
3732                 MethodInfo raise, remove, add;
3733
3734                 EventAttributes attributes;
3735                 Type declaring_type, reflected_type, event_type;
3736                 string name;
3737
3738                 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3739                 {
3740                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3741
3742                         // And now store the values in our own fields.
3743                         
3744                         declaring_type = type_builder;
3745
3746                         reflected_type = type_builder;
3747                         
3748                         attributes = event_attr;
3749                         this.name = name;
3750                         this.event_type = event_type;
3751                 }
3752                 
3753                 //
3754                 // Methods that you have to override.  Note that you only need 
3755                 // to "implement" the variants that take the argument (those are
3756                 // the "abstract" methods, the others (GetAddMethod()) are 
3757                 // regular.
3758                 //
3759                 public override MethodInfo GetAddMethod (bool nonPublic)
3760                 {
3761                         return add;
3762                 }
3763                 
3764                 public override MethodInfo GetRemoveMethod (bool nonPublic)
3765                 {
3766                         return remove;
3767                 }
3768                 
3769                 public override MethodInfo GetRaiseMethod (bool nonPublic)
3770                 {
3771                         return raise;
3772                 }
3773                 
3774                 //
3775                 // These methods make "MyEventInfo" look like a Builder
3776                 //
3777                 public void SetRaiseMethod (MethodBuilder raiseMethod)
3778                 {
3779                         raise = raiseMethod;
3780                         MyBuilder.SetRaiseMethod (raiseMethod);
3781                 }
3782
3783                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3784                 {
3785                         remove = removeMethod;
3786                         MyBuilder.SetRemoveOnMethod (removeMethod);
3787                 }
3788
3789                 public void SetAddOnMethod (MethodBuilder addMethod)
3790                 {
3791                         add = addMethod;
3792                         MyBuilder.SetAddOnMethod (addMethod);
3793                 }
3794
3795                 public void SetCustomAttribute (CustomAttributeBuilder cb)
3796                 {
3797                         MyBuilder.SetCustomAttribute (cb);
3798                 }
3799                 
3800                 public override object [] GetCustomAttributes (bool inherit)
3801                 {
3802                         // FIXME : There's nothing which can be seemingly done here because
3803                         // we have no way of getting at the custom attribute objects of the
3804                         // EventBuilder !
3805                         return null;
3806                 }
3807
3808                 public override object [] GetCustomAttributes (Type t, bool inherit)
3809                 {
3810                         // FIXME : Same here !
3811                         return null;
3812                 }
3813
3814                 public override bool IsDefined (Type t, bool b)
3815                 {
3816                         return true;
3817                 }
3818
3819                 public override EventAttributes Attributes {
3820                         get {
3821                                 return attributes;
3822                         }
3823                 }
3824
3825                 public override string Name {
3826                         get {
3827                                 return name;
3828                         }
3829                 }
3830
3831                 public override Type DeclaringType {
3832                         get {
3833                                 return declaring_type;
3834                         }
3835                 }
3836
3837                 public override Type ReflectedType {
3838                         get {
3839                                 return reflected_type;
3840                         }
3841                 }
3842
3843                 public Type EventType {
3844                         get {
3845                                 return event_type;
3846                         }
3847                 }
3848         }
3849         
3850         public class Event : FieldBase {
3851                 const int AllowedModifiers =
3852                         Modifiers.NEW |
3853                         Modifiers.PUBLIC |
3854                         Modifiers.PROTECTED |
3855                         Modifiers.INTERNAL |
3856                         Modifiers.PRIVATE |
3857                         Modifiers.STATIC |
3858                         Modifiers.VIRTUAL |
3859                         Modifiers.SEALED |
3860                         Modifiers.OVERRIDE |
3861                         Modifiers.UNSAFE |
3862                         Modifiers.ABSTRACT;
3863
3864                 public readonly Accessor  Add;
3865                 public readonly Accessor  Remove;
3866                 public MyEventBuilder     EventBuilder;
3867
3868                 MethodBuilder AddBuilder, RemoveBuilder;
3869                 MethodData AddData, RemoveData;
3870                 
3871                 public Event (Expression type, string name, Object init, int mod, Accessor add,
3872                               Accessor remove, Attributes attrs, Location loc)
3873                         : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3874                 {
3875                         Add = add;
3876                         Remove = remove;
3877                 }
3878
3879                 public override bool Define (TypeContainer parent)
3880                 {
3881                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3882
3883                         if (!DoDefine (parent))
3884                                 return false;
3885
3886                         if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
3887                                 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3888                                               "' : event must be of a delegate type");
3889                                 return false;
3890                         }
3891
3892                         Type [] parameter_types = new Type [1];
3893                         parameter_types [0] = MemberType;
3894
3895                         Parameter [] parms = new Parameter [1];
3896                         parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3897                         InternalParameters ip = new InternalParameters (
3898                                 parent, new Parameters (parms, null, Location)); 
3899
3900                         if (!CheckBase (parent))
3901                                 return false;
3902
3903                         //
3904                         // Now define the accessors
3905                         //
3906                         AddData = new MethodData (this, "add", TypeManager.void_type,
3907                                                   parameter_types, ip, CallingConventions.Standard,
3908                                                   (Add != null) ? Add.OptAttributes : null,
3909                                                   ModFlags, flags, false);
3910
3911                         if (!AddData.Define (parent))
3912                                 return false;
3913
3914                         AddBuilder = AddData.MethodBuilder;
3915                         AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3916
3917                         RemoveData = new MethodData (this, "remove", TypeManager.void_type,
3918                                                      parameter_types, ip, CallingConventions.Standard,
3919                                                      (Remove != null) ? Remove.OptAttributes : null,
3920                                                      ModFlags, flags, false);
3921
3922                         if (!RemoveData.Define (parent))
3923                                 return false;
3924
3925                         RemoveBuilder = RemoveData.MethodBuilder;
3926                         RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3927
3928                         if (!IsExplicitImpl){
3929                                 EventBuilder = new MyEventBuilder (
3930                                         parent.TypeBuilder, Name, e_attr, MemberType);
3931                                         
3932                                 if (Add == null && Remove == null) {
3933                                         FieldBuilder = parent.TypeBuilder.DefineField (
3934                                                 Name, MemberType, FieldAttributes.FamANDAssem);
3935                                         TypeManager.RegisterPrivateFieldOfEvent (
3936                                                 (EventInfo) EventBuilder, FieldBuilder);
3937                                         TypeManager.RegisterFieldBase (FieldBuilder, this);
3938                                 }
3939                         
3940                                 EventBuilder.SetAddOnMethod (AddBuilder);
3941                                 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3942
3943                                 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3944                                         Report.Error (111, Location,
3945                                                       "Class `" + parent.Name +
3946                                                       "' already contains a definition for the event `" +
3947                                                       Name + "'");
3948                                         return false;
3949                                 }
3950                         }
3951                         
3952                         return true;
3953                 }
3954
3955                 void EmitDefaultMethod (EmitContext ec, bool is_add)
3956                 {
3957                         ILGenerator ig = ec.ig;
3958                         MethodInfo method = null;
3959                         
3960                         if (is_add)
3961                                 method = TypeManager.delegate_combine_delegate_delegate;
3962                         else
3963                                 method = TypeManager.delegate_remove_delegate_delegate;
3964
3965                         if ((ModFlags & Modifiers.STATIC) != 0) {
3966                                 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
3967                                 ig.Emit (OpCodes.Ldarg_0);
3968                                 ig.Emit (OpCodes.Call, method);
3969                                 ig.Emit (OpCodes.Castclass, MemberType);
3970                                 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
3971                         } else {
3972                                 ig.Emit (OpCodes.Ldarg_0);
3973                                 ig.Emit (OpCodes.Ldarg_0);
3974                                 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3975                                 ig.Emit (OpCodes.Ldarg_1);
3976                                 ig.Emit (OpCodes.Call, method);
3977                                 ig.Emit (OpCodes.Castclass, MemberType);
3978                                 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3979                         }
3980                         ig.Emit (OpCodes.Ret);
3981                 }
3982
3983                 public void Emit (TypeContainer tc)
3984                 {
3985                         EmitContext ec;
3986
3987                         ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
3988                         Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3989
3990                         if (Add != null)
3991                                 AddData.Emit (tc, Add.Block, Add);
3992                         else {
3993                                 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
3994                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3995                                 EmitDefaultMethod (ec, true);
3996                         }
3997
3998                         if (Remove != null)
3999                                 RemoveData.Emit (tc, Remove.Block, Remove);
4000                         else {
4001                                 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4002                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4003                                 EmitDefaultMethod (ec, false);
4004                         }
4005                 }
4006                 
4007         }
4008
4009         //
4010         // FIXME: This does not handle:
4011         //
4012         //   int INTERFACENAME [ args ]
4013         //   Does not 
4014         //
4015         // Only:
4016         // 
4017         // int this [ args ]
4018  
4019         public class Indexer : PropertyBase {
4020
4021                 const int AllowedModifiers =
4022                         Modifiers.NEW |
4023                         Modifiers.PUBLIC |
4024                         Modifiers.PROTECTED |
4025                         Modifiers.INTERNAL |
4026                         Modifiers.PRIVATE |
4027                         Modifiers.VIRTUAL |
4028                         Modifiers.SEALED |
4029                         Modifiers.OVERRIDE |
4030                         Modifiers.UNSAFE |
4031                         Modifiers.EXTERN |
4032                         Modifiers.ABSTRACT;
4033
4034                 public string IndexerName;
4035                 public string InterfaceIndexerName;
4036
4037                 //
4038                 // Are we implementing an interface ?
4039                 //
4040                 bool IsImplementing = false;
4041                 
4042                 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4043                                 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4044                         : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4045                                 attrs, loc)
4046                 {
4047                         ExplicitInterfaceName = int_type;
4048                 }
4049
4050                 public override bool Define (TypeContainer parent)
4051                 {
4052                         PropertyAttributes prop_attr =
4053                                 PropertyAttributes.RTSpecialName |
4054                                 PropertyAttributes.SpecialName;
4055                         
4056                         if (!DoDefine (parent))
4057                                 return false;
4058
4059                         IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4060                         if (IndexerName == null)
4061                                 IndexerName = "Item";
4062                         else if (IsExplicitImpl)
4063                                 Report.Error (592, Location,
4064                                               "Attribute 'IndexerName' is not valid on this declaration " +
4065                                               "type. It is valid on `property' declarations only.");
4066
4067                         ShortName = IndexerName;
4068                         if (IsExplicitImpl) {
4069                                 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4070                                 Name = InterfaceType.FullName + "." + IndexerName;
4071                         } else {
4072                                 InterfaceIndexerName = IndexerName;
4073                                 Name = ShortName;
4074                         }
4075
4076                         if (!CheckBase (parent))
4077                                 return false;
4078
4079                         if (Get != null){
4080                                 InternalParameters ip = new InternalParameters (parent, Parameters);
4081
4082                                 GetData = new MethodData (this, "get", MemberType,
4083                                                           ParameterTypes, ip, CallingConventions.Standard,
4084                                                           Get.OptAttributes, ModFlags, flags, false);
4085
4086                                 if (!GetData.Define (parent))
4087                                         return false;
4088
4089                                 GetBuilder = GetData.MethodBuilder;
4090                         }
4091                         
4092                         if (Set != null){
4093                                 int top = ParameterTypes.Length;
4094                                 Type [] set_pars = new Type [top + 1];
4095                                 ParameterTypes.CopyTo (set_pars, 0);
4096                                 set_pars [top] = MemberType;
4097
4098                                 Parameter [] fixed_parms = Parameters.FixedParameters;
4099
4100                                 if (fixed_parms == null){
4101                                         throw new Exception ("We currently do not support only array arguments in an indexer");
4102                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4103                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4104                                         //
4105                                         // Here is the problem: the `value' parameter has
4106                                         // to come *after* the array parameter in the declaration
4107                                         // like this:
4108                                         // X (object [] x, Type value)
4109                                         // .param [0]
4110                                         //
4111                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4112                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4113                                         
4114                                 }
4115                                 
4116                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4117
4118
4119                                 fixed_parms.CopyTo (tmp, 0);
4120                                 tmp [fixed_parms.Length] = new Parameter (
4121                                         Type, "value", Parameter.Modifier.NONE, null);
4122
4123                                 Parameters set_formal_params = new Parameters (tmp, null, Location);
4124                                 
4125                                 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4126
4127                                 SetData = new MethodData (this, "set", TypeManager.void_type,
4128                                                           set_pars, ip, CallingConventions.Standard,
4129                                                           Set.OptAttributes, ModFlags, flags, false);
4130
4131                                 if (!SetData.Define (parent))
4132                                         return false;
4133
4134                                 SetBuilder = SetData.MethodBuilder;
4135                         }
4136
4137                         //
4138                         // Now name the parameters
4139                         //
4140                         Parameter [] p = Parameters.FixedParameters;
4141                         if (p != null) {
4142                                 int i;
4143                                 
4144                                 for (i = 0; i < p.Length; ++i) {
4145                                         if (Get != null)
4146                                                 GetBuilder.DefineParameter (
4147                                                         i + 1, p [i].Attributes, p [i].Name);
4148
4149                                         if (Set != null)
4150                                                 SetBuilder.DefineParameter (
4151                                                         i + 1, p [i].Attributes, p [i].Name);
4152                                 }
4153
4154                                 if (Set != null)
4155                                         SetBuilder.DefineParameter (
4156                                                 i + 1, ParameterAttributes.None, "value");
4157                                         
4158                                 if (i != ParameterTypes.Length) {
4159                                         Parameter array_param = Parameters.ArrayParameter;
4160                                         SetBuilder.DefineParameter (
4161                                                 i + 1, array_param.Attributes, array_param.Name);
4162                                 }
4163                         }
4164
4165                         if (GetData != null)
4166                                 IsImplementing = GetData.IsImplementing;
4167                         else if (SetData != null)
4168                                 IsImplementing = SetData.IsImplementing;
4169
4170                         //
4171                         // Define the PropertyBuilder if one of the following conditions are met:
4172                         // a) we're not implementing an interface indexer.
4173                         // b) the indexer has a different IndexerName and this is no
4174                         //    explicit interface implementation.
4175                         //
4176                         if (!IsExplicitImpl) {
4177                                 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4178                                         IndexerName, prop_attr, MemberType, ParameterTypes);
4179
4180                                 if (GetData != null)
4181                                         PropertyBuilder.SetGetMethod (GetBuilder);
4182
4183                                 if (SetData != null)
4184                                         PropertyBuilder.SetSetMethod (SetBuilder);
4185                                 
4186                                 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4187                                                              ParameterTypes);
4188                         }
4189
4190                         return true;
4191                 }
4192         }
4193
4194         public class Operator : MemberCore {
4195
4196                 const int AllowedModifiers =
4197                         Modifiers.PUBLIC |
4198                         Modifiers.UNSAFE |
4199                         Modifiers.EXTERN |
4200                         Modifiers.STATIC;
4201
4202                 const int RequiredModifiers =
4203                         Modifiers.PUBLIC |
4204                         Modifiers.STATIC;
4205
4206                 public enum OpType : byte {
4207
4208                         // Unary operators
4209                         LogicalNot,
4210                         OnesComplement,
4211                         Increment,
4212                         Decrement,
4213                         True,
4214                         False,
4215
4216                         // Unary and Binary operators
4217                         Addition,
4218                         Subtraction,
4219
4220                         UnaryPlus,
4221                         UnaryNegation,
4222                         
4223                         // Binary operators
4224                         Multiply,
4225                         Division,
4226                         Modulus,
4227                         BitwiseAnd,
4228                         BitwiseOr,
4229                         ExclusiveOr,
4230                         LeftShift,
4231                         RightShift,
4232                         Equality,
4233                         Inequality,
4234                         GreaterThan,
4235                         LessThan,
4236                         GreaterThanOrEqual,
4237                         LessThanOrEqual,
4238
4239                         // Implicit and Explicit
4240                         Implicit,
4241                         Explicit
4242                 };
4243
4244                 public readonly OpType OperatorType;
4245                 public readonly Expression ReturnType;
4246                 public readonly Expression FirstArgType, SecondArgType;
4247                 public readonly string FirstArgName, SecondArgName;
4248                 public readonly Block  Block;
4249                 public Attributes      OptAttributes;
4250                 public MethodBuilder   OperatorMethodBuilder;
4251                 
4252                 public string MethodName;
4253                 public Method OperatorMethod;
4254
4255                 public Operator (OpType type, Expression ret_type, int flags,
4256                                  Expression arg1type, string arg1name,
4257                                  Expression arg2type, string arg2name,
4258                                  Block block, Attributes attrs, Location loc)
4259                         : base ("", loc)
4260                 {
4261                         OperatorType = type;
4262                         ReturnType = ret_type;
4263                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4264                         FirstArgType = arg1type;
4265                         FirstArgName = arg1name;
4266                         SecondArgType = arg2type;
4267                         SecondArgName = arg2name;
4268                         Block = block;
4269                         OptAttributes = attrs;
4270                 }
4271
4272                 string Prototype (TypeContainer parent)
4273                 {
4274                         return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4275                                 SecondArgType + ")";
4276                 }
4277                 
4278                 public override bool Define (TypeContainer parent)
4279                 {
4280                         int length = 1;
4281                         MethodName = "op_" + OperatorType;
4282                         
4283                         if (SecondArgType != null)
4284                                 length = 2;
4285                         
4286                         Parameter [] param_list = new Parameter [length];
4287
4288                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4289                                 Report.Error (
4290                                         558, Location, 
4291                                         "User defined operators `" +
4292                                         Prototype (parent) +
4293                                         "' must be declared static and public");
4294                                 return false;
4295                         }
4296
4297                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
4298                                                        Parameter.Modifier.NONE, null);
4299                         if (SecondArgType != null)
4300                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4301                                                                Parameter.Modifier.NONE, null);
4302                         
4303                         OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4304                                                      new Parameters (param_list, null, Location),
4305                                                      OptAttributes, Mono.CSharp.Location.Null);
4306
4307                         OperatorMethod.IsOperator = true;                       
4308                         OperatorMethod.Define (parent);
4309
4310                         if (OperatorMethod.MethodBuilder == null)
4311                                 return false;
4312                         
4313                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4314
4315                         Type [] param_types = OperatorMethod.ParameterTypes;
4316                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
4317                         Type return_type = OperatorMethod.GetReturnType ();
4318                         Type first_arg_type = param_types [0];
4319
4320                         // Rules for conversion operators
4321                         
4322                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4323                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
4324                                         Report.Error (
4325                                                 555, Location,
4326                                                 "User-defined conversion cannot take an object of the " +
4327                                                 "enclosing type and convert to an object of the enclosing" +
4328                                                 " type");
4329                                         return false;
4330                                 }
4331                                 
4332                                 if (first_arg_type != declaring_type && return_type != declaring_type){
4333                                         Report.Error (
4334                                                 556, Location, 
4335                                                 "User-defined conversion must convert to or from the " +
4336                                                 "enclosing type");
4337                                         return false;
4338                                 }
4339                                 
4340                                 if (first_arg_type == TypeManager.object_type ||
4341                                     return_type == TypeManager.object_type){
4342                                         Report.Error (
4343                                                 -8, Location,
4344                                                 "User-defined conversion cannot convert to or from " +
4345                                                 "object type");
4346                                         return false;
4347                                 }
4348
4349                                 if (first_arg_type.IsInterface || return_type.IsInterface){
4350                                         Report.Error (
4351                                                 552, Location,
4352                                                 "User-defined conversion cannot convert to or from an " +
4353                                                 "interface type");
4354                                         return false;
4355                                 }
4356                                 
4357                                 if (first_arg_type.IsSubclassOf (return_type) ||
4358                                     return_type.IsSubclassOf (first_arg_type)){
4359                                         Report.Error (
4360                                                 -10, Location,
4361                                                 "User-defined conversion cannot convert between types " +
4362                                                 "that derive from each other");
4363                                         return false;
4364                                 }
4365                         } else if (SecondArgType == null) {
4366                                 // Checks for Unary operators
4367                                 
4368                                 if (first_arg_type != declaring_type){
4369                                         Report.Error (
4370                                                 562, Location,
4371                                                 "The parameter of a unary operator must be the " +
4372                                                 "containing type");
4373                                         return false;
4374                                 }
4375                                 
4376                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4377                                         if (return_type != declaring_type){
4378                                                 Report.Error (
4379                                                         559, Location,
4380                                                         "The parameter and return type for ++ and -- " +
4381                                                         "must be the containing type");
4382                                                 return false;
4383                                         }
4384                                         
4385                                 }
4386                                 
4387                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4388                                         if (return_type != TypeManager.bool_type){
4389                                                 Report.Error (
4390                                                         215, Location,
4391                                                         "The return type of operator True or False " +
4392                                                         "must be bool");
4393                                                 return false;
4394                                         }
4395                                 }
4396                                 
4397                         } else {
4398                                 // Checks for Binary operators
4399                                 
4400                                 if (first_arg_type != declaring_type &&
4401                                     param_types [1] != declaring_type){
4402                                         Report.Error (
4403                                                 563, Location,
4404                                                 "One of the parameters of a binary operator must " +
4405                                                 "be the containing type");
4406                                         return false;
4407                                 }
4408                         }
4409
4410                         return true;
4411                 }
4412                 
4413                 public void Emit (TypeContainer parent)
4414                 {
4415                         EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4416                         Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4417
4418                         //
4419                         // abstract or extern methods have no bodies
4420                         //
4421                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4422                                 return;
4423                         
4424                         OperatorMethod.Block = Block;
4425                         OperatorMethod.Emit (parent);
4426                 }
4427
4428                 public static string GetName (OpType ot)
4429                 {
4430                         switch (ot){
4431                         case OpType.LogicalNot:
4432                                 return "!";
4433                         case OpType.OnesComplement:
4434                                 return "~";
4435                         case OpType.Increment:
4436                                 return "++";
4437                         case OpType.Decrement:
4438                                 return "--";
4439                         case OpType.True:
4440                                 return "true";
4441                         case OpType.False:
4442                                 return "false";
4443                         case OpType.Addition:
4444                                 return "+";
4445                         case OpType.Subtraction:
4446                                 return "-";
4447                         case OpType.UnaryPlus:
4448                                 return "+";
4449                         case OpType.UnaryNegation:
4450                                 return "-";
4451                         case OpType.Multiply:
4452                                 return "*";
4453                         case OpType.Division:
4454                                 return "/";
4455                         case OpType.Modulus:
4456                                 return "%";
4457                         case OpType.BitwiseAnd:
4458                                 return "&";
4459                         case OpType.BitwiseOr:
4460                                 return "|";
4461                         case OpType.ExclusiveOr:
4462                                 return "^";
4463                         case OpType.LeftShift:
4464                                 return "<<";
4465                         case OpType.RightShift:
4466                                 return ">>";
4467                         case OpType.Equality:
4468                                 return "==";
4469                         case OpType.Inequality:
4470                                 return "!=";
4471                         case OpType.GreaterThan:
4472                                 return ">";
4473                         case OpType.LessThan:
4474                                 return "<";
4475                         case OpType.GreaterThanOrEqual:
4476                                 return ">=";
4477                         case OpType.LessThanOrEqual:
4478                                 return "<=";
4479                         case OpType.Implicit:
4480                                 return "implicit";
4481                         case OpType.Explicit:
4482                                 return "explicit";
4483                         default: return "";
4484                         }
4485                 }
4486                 
4487                 public override string ToString ()
4488                 {
4489                         Type return_type = OperatorMethod.GetReturnType();
4490                         Type [] param_types = OperatorMethod.ParameterTypes;
4491                         
4492                         if (SecondArgType == null)
4493                                 return String.Format (
4494                                         "{0} operator {1}({2})",
4495                                         TypeManager.CSharpName (return_type),
4496                                         GetName (OperatorType),
4497                                         param_types [0]);
4498                         else
4499                                 return String.Format (
4500                                         "{0} operator {1}({2}, {3})",
4501                                         TypeManager.CSharpName (return_type),
4502                                         GetName (OperatorType),
4503                                         param_types [0], param_types [1]);
4504                 }
4505         }
4506
4507         //
4508         // This is used to compare method signatures
4509         //
4510         struct MethodSignature {
4511                 public string Name;
4512                 public Type RetType;
4513                 public Type [] Parameters;
4514                 
4515                 /// <summary>
4516                 ///    This delegate is used to extract methods which have the
4517                 ///    same signature as the argument
4518                 /// </summary>
4519                 public static MemberFilter method_signature_filter;
4520
4521                 /// <summary>
4522                 ///   This delegate is used to extract inheritable methods which
4523                 ///   have the same signature as the argument.  By inheritable,
4524                 ///   this means that we have permissions to override the method
4525                 ///   from the current assembly and class
4526                 /// </summary>
4527                 public static MemberFilter inheritable_method_signature_filter;
4528
4529                 /// <summary>
4530                 ///   This delegate is used to extract inheritable methods which
4531                 ///   have the same signature as the argument.  By inheritable,
4532                 ///   this means that we have permissions to override the method
4533                 ///   from the current assembly and class
4534                 /// </summary>
4535                 public static MemberFilter inheritable_property_signature_filter;
4536                 
4537                 static MethodSignature ()
4538                 {
4539                         method_signature_filter = new MemberFilter (MemberSignatureCompare);
4540                         inheritable_method_signature_filter = new MemberFilter (
4541                                 InheritableMemberSignatureCompare);
4542                         inheritable_property_signature_filter = new MemberFilter (
4543                                 InheritablePropertySignatureCompare);
4544                 }
4545                 
4546                 public MethodSignature (string name, Type ret_type, Type [] parameters)
4547                 {
4548                         Name = name;
4549                         RetType = ret_type;
4550
4551                         if (parameters == null)
4552                                 Parameters = TypeManager.NoTypes;
4553                         else
4554                                 Parameters = parameters;
4555                 }
4556                 
4557                 public override int GetHashCode ()
4558                 {
4559                         return Name.GetHashCode ();
4560                 }
4561
4562                 public override bool Equals (Object o)
4563                 {
4564                         MethodSignature other = (MethodSignature) o;
4565
4566                         if (other.Name != Name)
4567                                 return false;
4568
4569                         if (other.RetType != RetType)
4570                                 return false;
4571                         
4572                         if (Parameters == null){
4573                                 if (other.Parameters == null)
4574                                         return true;
4575                                 return false;
4576                         }
4577
4578                         if (other.Parameters == null)
4579                                 return false;
4580                         
4581                         int c = Parameters.Length;
4582                         if (other.Parameters.Length != c)
4583                                 return false;
4584
4585                         for (int i = 0; i < c; i++)
4586                                 if (other.Parameters [i] != Parameters [i])
4587                                         return false;
4588
4589                         return true;
4590                 }
4591
4592                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4593                 {
4594                         MethodSignature sig = (MethodSignature) filter_criteria;
4595
4596                         if (m.Name != sig.Name)
4597                                 return false;
4598
4599                         Type ReturnType;
4600                         MethodInfo mi = m as MethodInfo;
4601                         PropertyInfo pi = m as PropertyInfo;
4602
4603                         if (mi != null)
4604                                 ReturnType = mi.ReturnType;
4605                         else if (pi != null)
4606                                 ReturnType = pi.PropertyType;
4607                         else
4608                                 return false;
4609                         
4610                         //
4611                         // we use sig.RetType == null to mean `do not check the
4612                         // method return value.  
4613                         //
4614                         if (sig.RetType != null)
4615                                 if (ReturnType != sig.RetType)
4616                                         return false;
4617
4618                         Type [] args;
4619                         if (mi != null)
4620                                 args = TypeManager.GetArgumentTypes (mi);
4621                         else
4622                                 args = TypeManager.GetArgumentTypes (pi);
4623                         Type [] sigp = sig.Parameters;
4624
4625                         if (args.Length != sigp.Length)
4626                                 return false;
4627
4628                         for (int i = args.Length; i > 0; ){
4629                                 i--;
4630                                 if (args [i] != sigp [i])
4631                                         return false;
4632                         }
4633                         return true;
4634                 }
4635
4636                 //
4637                 // This filter should be used when we are requesting methods that
4638                 // we want to override.
4639                 //
4640                 // This makes a number of assumptions, for example
4641                 // that the methods being extracted are of a parent
4642                 // class (this means we know implicitly that we are
4643                 // being called to find out about members by a derived
4644                 // class).
4645                 // 
4646                 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4647                 {
4648                         if (MemberSignatureCompare (m, filter_criteria)){
4649                                 MethodInfo mi = (MethodInfo) m;
4650                                 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4651
4652                                 // If only accessible to the current class.
4653                                 if (prot == MethodAttributes.Private)
4654                                         return false;
4655
4656                                 // If only accessible to the defining assembly or 
4657                                 if (prot == MethodAttributes.FamANDAssem ||
4658                                     prot == MethodAttributes.Assembly){
4659                                         if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4660                                                 return true;
4661                                         else
4662                                                 return false;
4663                                 }
4664
4665                                 // Anything else (FamOrAssembly and Public) is fine
4666                                 return true;
4667                         }
4668                         return false;
4669                 }
4670
4671                 //
4672                 // This filter should be used when we are requesting properties that
4673                 // we want to override.
4674                 //
4675                 // This makes a number of assumptions, for example
4676                 // that the methods being extracted are of a parent
4677                 // class (this means we know implicitly that we are
4678                 // being called to find out about members by a derived
4679                 // class).
4680                 // 
4681                 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4682                 {
4683                         if (MemberSignatureCompare (m, filter_criteria)){
4684                                 PropertyInfo pi = (PropertyInfo) m;
4685
4686                                 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4687                                 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4688
4689                                 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4690
4691                                 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4692
4693                                 // If only accessible to the current class.
4694                                 if (prot == MethodAttributes.Private)
4695                                         return false;
4696
4697                                 // If only accessible to the defining assembly or 
4698                                 if (prot == MethodAttributes.FamANDAssem ||
4699                                     prot == MethodAttributes.Assembly){
4700                                         if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4701                                                 return true;
4702                                         else
4703                                                 return false;
4704                                 }
4705
4706                                 // Anything else (FamOrAssembly and Public) is fine
4707                                 return true;
4708                         }
4709                         return false;
4710                 }
4711         }
4712 }