2002-10-19 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mbas / 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                         FieldBuilder = parent.TypeBuilder.DefineField (
3411                                 Name, t, Modifiers.FieldAttr (ModFlags));
3412
3413                         TypeManager.RegisterFieldBase (FieldBuilder, this);
3414                         return true;
3415                 }
3416
3417                 public void Emit (TypeContainer tc)
3418                 {
3419                         EmitContext ec = new EmitContext (tc, Location, null,
3420                                                           FieldBuilder.FieldType, ModFlags);
3421
3422                         Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3423                 }
3424         }
3425
3426         //
3427         // `set' and `get' accessors are represented with an Accessor.
3428         // 
3429         public class Accessor {
3430                 //
3431                 // Null if the accessor is empty, or a Block if not
3432                 //
3433                 public Block Block;
3434                 public Attributes OptAttributes;
3435                 
3436                 public Accessor (Block b, Attributes attrs)
3437                 {
3438                         Block = b;
3439                         OptAttributes = attrs;
3440                 }
3441         }
3442
3443         //
3444         // Properties and Indexers both generate PropertyBuilders, we use this to share 
3445         // their common bits.
3446         //
3447         abstract public class PropertyBase : MethodCore {
3448                 public Accessor Get, Set;
3449                 public PropertyBuilder PropertyBuilder;
3450                 public MethodBuilder GetBuilder, SetBuilder;
3451                 public MethodData GetData, SetData;
3452
3453                 protected EmitContext ec;
3454
3455                 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3456                                      Parameters parameters, Accessor get_block, Accessor set_block,
3457                                      Attributes attrs, Location loc)
3458                         : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3459                 {
3460                         Get = get_block;
3461                         Set = set_block;
3462                 }
3463
3464                 protected override bool DoDefine (TypeContainer parent)
3465                 {
3466                         if (!base.DoDefine (parent))
3467                                 return false;
3468
3469                         ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3470
3471                         return true;
3472                 }
3473
3474                 //
3475                 // Checks our base implementation if any
3476                 //
3477                 protected override bool CheckBase (TypeContainer parent)
3478                 {
3479                         // Check whether arguments were correct.
3480                         if (!DoDefineParameters (parent))
3481                                 return false;
3482
3483                         if (IsExplicitImpl)
3484                                 return true;
3485
3486                         string report_name;
3487                         MethodSignature ms, base_ms;
3488                         if (this is Indexer) {
3489                                 string name, base_name;
3490
3491                                 report_name = "this";
3492                                 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3493                                 ms = new MethodSignature (name, null, ParameterTypes);
3494                                 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3495                                 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3496                         } else {
3497                                 report_name = Name;
3498                                 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3499                         }
3500
3501                         MemberList props_this;
3502
3503                         props_this = TypeContainer.FindMembers (
3504                                 parent.TypeBuilder, MemberTypes.Property,
3505                                 BindingFlags.NonPublic | BindingFlags.Public |
3506                                 BindingFlags.Static | BindingFlags.Instance |
3507                                 BindingFlags.DeclaredOnly,
3508                                 MethodSignature.method_signature_filter, ms);
3509
3510                         if (props_this.Count > 0) {
3511                                 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3512                                               "already defines a member called `" + report_name + "' " +
3513                                               "with the same parameter types");
3514                                 return false;
3515                         }
3516
3517                         //
3518                         // Find properties with the same name on the base class
3519                         //
3520                         MemberList props;
3521                         MemberList props_static = TypeContainer.FindMembers (
3522                                 parent.TypeBuilder.BaseType, MemberTypes.Property,
3523                                 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3524                                 MethodSignature.inheritable_property_signature_filter, base_ms);
3525
3526                         MemberList props_instance = TypeContainer.FindMembers (
3527                                 parent.TypeBuilder.BaseType, MemberTypes.Property,
3528                                 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3529                                 MethodSignature.inheritable_property_signature_filter,
3530                                 base_ms);
3531
3532                         //
3533                         // Find if we have anything
3534                         //
3535                         if (props_static.Count > 0)
3536                                 props = props_static;
3537                         else if (props_instance.Count > 0)
3538                                 props = props_instance;
3539                         else
3540                                 props = null;
3541
3542                         //
3543                         // If we have something on the base.
3544                         if (props != null && props.Count > 0){
3545                                 PropertyInfo pi = (PropertyInfo) props [0];
3546
3547                                 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
3548                                 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
3549
3550                                 MethodInfo reference = inherited_get == null ?
3551                                         inherited_set : inherited_get;
3552                                 
3553                                 if (reference != null) {
3554                                         string name = reference.DeclaringType.Name + "." + report_name;
3555
3556                                         if (!CheckMethodAgainstBase (parent, flags, reference, name))
3557                                                 return false;
3558                                 }
3559
3560                                 if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
3561                                         Report.Error (508, parent.MakeName (Name) + ": cannot " +
3562                                                       "change return type when overriding inherited " +
3563                                                       "member `" + pi.DeclaringType + "." + pi.Name + "'");
3564                                         return false;
3565                                 }
3566                         } else {
3567                                 if ((ModFlags & Modifiers.NEW) != 0)
3568                                         WarningNotHiding (parent);
3569                                 
3570                                 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3571                                         if (this is Indexer)
3572                                                 Report.Error (115, Location,
3573                                                               parent.MakeName (Name) +
3574                                                               " no suitable indexers found to override");
3575                                         else
3576                                                 Report.Error (115, Location,
3577                                                               parent.MakeName (Name) +
3578                                                               " no suitable properties found to override");
3579                                         return false;
3580                                 }
3581                         }
3582                         return true;
3583                 }
3584
3585                 public void Emit (TypeContainer tc)
3586                 {
3587                         //
3588                         // The PropertyBuilder can be null for explicit implementations, in that
3589                         // case, we do not actually emit the ".property", so there is nowhere to
3590                         // put the attribute
3591                         //
3592                         if (PropertyBuilder != null)
3593                                 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3594
3595                         if (GetData != null)
3596                                 GetData.Emit (tc, Get.Block, Get);
3597
3598                         if (SetData != null)
3599                                 SetData.Emit (tc, Set.Block, Set);
3600                 }
3601         }
3602                         
3603         public class Property : PropertyBase {
3604                 const int AllowedModifiers =
3605                         Modifiers.NEW |
3606                         Modifiers.PUBLIC |
3607                         Modifiers.PROTECTED |
3608                         Modifiers.INTERNAL |
3609                         Modifiers.PRIVATE |
3610                         Modifiers.STATIC |
3611                         Modifiers.SEALED |
3612                         Modifiers.OVERRIDE |
3613                         Modifiers.ABSTRACT |
3614                         Modifiers.UNSAFE |
3615                         Modifiers.EXTERN |
3616                         Modifiers.VIRTUAL;
3617
3618                 public Property (Expression type, string name, int mod_flags,
3619                                  Accessor get_block, Accessor set_block,
3620                                  Attributes attrs, Location loc)
3621                         : base (type, name, mod_flags, AllowedModifiers,
3622                                 Parameters.EmptyReadOnlyParameters,
3623                                 get_block, set_block, attrs, loc)
3624                 {
3625                 }
3626
3627                 public override bool Define (TypeContainer parent)
3628                 {
3629                         if (!DoDefine (parent))
3630                                 return false;
3631
3632                         if (!CheckBase (parent))
3633                                 return false;
3634
3635                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3636
3637                         if (Get != null) {
3638                                 Type [] parameters = TypeManager.NoTypes;
3639
3640                                 InternalParameters ip = new InternalParameters (
3641                                         parent, Parameters.EmptyReadOnlyParameters);
3642
3643                                 GetData = new MethodData (this, "get", MemberType,
3644                                                           parameters, ip, CallingConventions.Standard,
3645                                                           Get.OptAttributes, ModFlags, flags, false);
3646
3647                                 if (!GetData.Define (parent))
3648                                         return false;
3649
3650                                 GetBuilder = GetData.MethodBuilder;
3651                         }
3652
3653                         if (Set != null) {
3654                                 Type [] parameters = new Type [1];
3655                                 parameters [0] = MemberType;
3656
3657                                 Parameter [] parms = new Parameter [1];
3658                                 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3659                                 InternalParameters ip = new InternalParameters (
3660                                         parent, new Parameters (parms, null, Location));
3661
3662                                 SetData = new MethodData (this, "set", TypeManager.void_type,
3663                                                           parameters, ip, CallingConventions.Standard,
3664                                                           Set.OptAttributes, ModFlags, flags, false);
3665
3666                                 if (!SetData.Define (parent))
3667                                         return false;
3668
3669                                 SetBuilder = SetData.MethodBuilder;
3670                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
3671                         }
3672
3673                         // FIXME - PropertyAttributes.HasDefault ?
3674                         
3675                         PropertyAttributes prop_attr =
3676                         PropertyAttributes.RTSpecialName |
3677                         PropertyAttributes.SpecialName;
3678
3679                         if (!IsExplicitImpl){
3680                                 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3681                                         Name, prop_attr, MemberType, null);
3682                                 
3683                                 if (Get != null)
3684                                         PropertyBuilder.SetGetMethod (GetBuilder);
3685                                 
3686                                 if (Set != null)
3687                                         PropertyBuilder.SetSetMethod (SetBuilder);
3688
3689                                 //
3690                                 // HACK for the reasons exposed above
3691                                 //
3692                                 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3693                                         Report.Error (
3694                                                 111, Location,
3695                                                 "Class `" + parent.Name +
3696                                                 "' already contains a definition for the property `" +
3697                                                 Name + "'");
3698                                         return false;
3699                                 }
3700                         }
3701                         return true;
3702                 }
3703         }
3704
3705         /// </summary>
3706         ///  Gigantic workaround  for lameness in SRE follows :
3707         ///  This class derives from EventInfo and attempts to basically
3708         ///  wrap around the EventBuilder so that FindMembers can quickly
3709         ///  return this in it search for members
3710         /// </summary>
3711         public class MyEventBuilder : EventInfo {
3712                 
3713                 //
3714                 // We use this to "point" to our Builder which is
3715                 // not really a MemberInfo
3716                 //
3717                 EventBuilder MyBuilder;
3718                 
3719                 //
3720                 // We "catch" and wrap these methods
3721                 //
3722                 MethodInfo raise, remove, add;
3723
3724                 EventAttributes attributes;
3725                 Type declaring_type, reflected_type, event_type;
3726                 string name;
3727
3728                 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3729                 {
3730                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3731
3732                         // And now store the values in our own fields.
3733                         
3734                         declaring_type = type_builder;
3735
3736                         reflected_type = type_builder;
3737                         
3738                         attributes = event_attr;
3739                         this.name = name;
3740                         this.event_type = event_type;
3741                 }
3742                 
3743                 //
3744                 // Methods that you have to override.  Note that you only need 
3745                 // to "implement" the variants that take the argument (those are
3746                 // the "abstract" methods, the others (GetAddMethod()) are 
3747                 // regular.
3748                 //
3749                 public override MethodInfo GetAddMethod (bool nonPublic)
3750                 {
3751                         return add;
3752                 }
3753                 
3754                 public override MethodInfo GetRemoveMethod (bool nonPublic)
3755                 {
3756                         return remove;
3757                 }
3758                 
3759                 public override MethodInfo GetRaiseMethod (bool nonPublic)
3760                 {
3761                         return raise;
3762                 }
3763                 
3764                 //
3765                 // These methods make "MyEventInfo" look like a Builder
3766                 //
3767                 public void SetRaiseMethod (MethodBuilder raiseMethod)
3768                 {
3769                         raise = raiseMethod;
3770                         MyBuilder.SetRaiseMethod (raiseMethod);
3771                 }
3772
3773                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3774                 {
3775                         remove = removeMethod;
3776                         MyBuilder.SetRemoveOnMethod (removeMethod);
3777                 }
3778
3779                 public void SetAddOnMethod (MethodBuilder addMethod)
3780                 {
3781                         add = addMethod;
3782                         MyBuilder.SetAddOnMethod (addMethod);
3783                 }
3784
3785                 public void SetCustomAttribute (CustomAttributeBuilder cb)
3786                 {
3787                         MyBuilder.SetCustomAttribute (cb);
3788                 }
3789                 
3790                 public override object [] GetCustomAttributes (bool inherit)
3791                 {
3792                         // FIXME : There's nothing which can be seemingly done here because
3793                         // we have no way of getting at the custom attribute objects of the
3794                         // EventBuilder !
3795                         return null;
3796                 }
3797
3798                 public override object [] GetCustomAttributes (Type t, bool inherit)
3799                 {
3800                         // FIXME : Same here !
3801                         return null;
3802                 }
3803
3804                 public override bool IsDefined (Type t, bool b)
3805                 {
3806                         return true;
3807                 }
3808
3809                 public override EventAttributes Attributes {
3810                         get {
3811                                 return attributes;
3812                         }
3813                 }
3814
3815                 public override string Name {
3816                         get {
3817                                 return name;
3818                         }
3819                 }
3820
3821                 public override Type DeclaringType {
3822                         get {
3823                                 return declaring_type;
3824                         }
3825                 }
3826
3827                 public override Type ReflectedType {
3828                         get {
3829                                 return reflected_type;
3830                         }
3831                 }
3832
3833                 public Type EventType {
3834                         get {
3835                                 return event_type;
3836                         }
3837                 }
3838         }
3839         
3840         public class Event : FieldBase {
3841                 const int AllowedModifiers =
3842                         Modifiers.NEW |
3843                         Modifiers.PUBLIC |
3844                         Modifiers.PROTECTED |
3845                         Modifiers.INTERNAL |
3846                         Modifiers.PRIVATE |
3847                         Modifiers.STATIC |
3848                         Modifiers.VIRTUAL |
3849                         Modifiers.SEALED |
3850                         Modifiers.OVERRIDE |
3851                         Modifiers.UNSAFE |
3852                         Modifiers.ABSTRACT;
3853
3854                 public readonly Accessor  Add;
3855                 public readonly Accessor  Remove;
3856                 public MyEventBuilder     EventBuilder;
3857
3858                 MethodBuilder AddBuilder, RemoveBuilder;
3859                 MethodData AddData, RemoveData;
3860                 
3861                 public Event (Expression type, string name, Object init, int mod, Accessor add,
3862                               Accessor remove, Attributes attrs, Location loc)
3863                         : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3864                 {
3865                         Add = add;
3866                         Remove = remove;
3867                 }
3868
3869                 public override bool Define (TypeContainer parent)
3870                 {
3871                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3872
3873                         if (!DoDefine (parent))
3874                                 return false;
3875
3876                         if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
3877                                 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3878                                               "' : event must be of a delegate type");
3879                                 return false;
3880                         }
3881
3882                         Type [] parameter_types = new Type [1];
3883                         parameter_types [0] = MemberType;
3884
3885                         Parameter [] parms = new Parameter [1];
3886                         parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3887                         InternalParameters ip = new InternalParameters (
3888                                 parent, new Parameters (parms, null, Location)); 
3889
3890                         if (!CheckBase (parent))
3891                                 return false;
3892
3893                         //
3894                         // Now define the accessors
3895                         //
3896                         AddData = new MethodData (this, "add", TypeManager.void_type,
3897                                                   parameter_types, ip, CallingConventions.Standard,
3898                                                   (Add != null) ? Add.OptAttributes : null,
3899                                                   ModFlags, flags, false);
3900
3901                         if (!AddData.Define (parent))
3902                                 return false;
3903
3904                         AddBuilder = AddData.MethodBuilder;
3905                         AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3906
3907                         RemoveData = new MethodData (this, "remove", TypeManager.void_type,
3908                                                      parameter_types, ip, CallingConventions.Standard,
3909                                                      (Remove != null) ? Remove.OptAttributes : null,
3910                                                      ModFlags, flags, false);
3911
3912                         if (!RemoveData.Define (parent))
3913                                 return false;
3914
3915                         RemoveBuilder = RemoveData.MethodBuilder;
3916                         RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3917
3918                         if (!IsExplicitImpl){
3919                                 EventBuilder = new MyEventBuilder (
3920                                         parent.TypeBuilder, Name, e_attr, MemberType);
3921                                         
3922                                 if (Add == null && Remove == null) {
3923                                         FieldBuilder = parent.TypeBuilder.DefineField (
3924                                                 Name, MemberType, FieldAttributes.FamANDAssem);
3925                                         TypeManager.RegisterPrivateFieldOfEvent (
3926                                                 (EventInfo) EventBuilder, FieldBuilder);
3927                                         TypeManager.RegisterFieldBase (FieldBuilder, this);
3928                                 }
3929                         
3930                                 EventBuilder.SetAddOnMethod (AddBuilder);
3931                                 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3932
3933                                 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3934                                         Report.Error (111, Location,
3935                                                       "Class `" + parent.Name +
3936                                                       "' already contains a definition for the event `" +
3937                                                       Name + "'");
3938                                         return false;
3939                                 }
3940                         }
3941                         
3942                         return true;
3943                 }
3944
3945                 void EmitDefaultMethod (EmitContext ec, bool is_add)
3946                 {
3947                         ILGenerator ig = ec.ig;
3948                         MethodInfo method = null;
3949                         
3950                         if (is_add)
3951                                 method = TypeManager.delegate_combine_delegate_delegate;
3952                         else
3953                                 method = TypeManager.delegate_remove_delegate_delegate;
3954
3955                         if ((ModFlags & Modifiers.STATIC) != 0) {
3956                                 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
3957                                 ig.Emit (OpCodes.Ldarg_0);
3958                                 ig.Emit (OpCodes.Call, method);
3959                                 ig.Emit (OpCodes.Castclass, MemberType);
3960                                 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
3961                         } else {
3962                                 ig.Emit (OpCodes.Ldarg_0);
3963                                 ig.Emit (OpCodes.Ldarg_0);
3964                                 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3965                                 ig.Emit (OpCodes.Ldarg_1);
3966                                 ig.Emit (OpCodes.Call, method);
3967                                 ig.Emit (OpCodes.Castclass, MemberType);
3968                                 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3969                         }
3970                         ig.Emit (OpCodes.Ret);
3971                 }
3972
3973                 public void Emit (TypeContainer tc)
3974                 {
3975                         EmitContext ec;
3976
3977                         ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
3978                         Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3979
3980                         if (Add != null)
3981                                 AddData.Emit (tc, Add.Block, Add);
3982                         else {
3983                                 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
3984                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3985                                 EmitDefaultMethod (ec, true);
3986                         }
3987
3988                         if (Remove != null)
3989                                 RemoveData.Emit (tc, Remove.Block, Remove);
3990                         else {
3991                                 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
3992                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3993                                 EmitDefaultMethod (ec, false);
3994                         }
3995                 }
3996                 
3997         }
3998
3999         //
4000         // FIXME: This does not handle:
4001         //
4002         //   int INTERFACENAME [ args ]
4003         //   Does not 
4004         //
4005         // Only:
4006         // 
4007         // int this [ args ]
4008  
4009         public class Indexer : PropertyBase {
4010
4011                 const int AllowedModifiers =
4012                         Modifiers.NEW |
4013                         Modifiers.PUBLIC |
4014                         Modifiers.PROTECTED |
4015                         Modifiers.INTERNAL |
4016                         Modifiers.PRIVATE |
4017                         Modifiers.VIRTUAL |
4018                         Modifiers.SEALED |
4019                         Modifiers.OVERRIDE |
4020                         Modifiers.UNSAFE |
4021                         Modifiers.EXTERN |
4022                         Modifiers.ABSTRACT;
4023
4024                 public string IndexerName;
4025                 public string InterfaceIndexerName;
4026
4027                 //
4028                 // Are we implementing an interface ?
4029                 //
4030                 bool IsImplementing = false;
4031                 
4032                 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4033                                 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4034                         : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4035                                 attrs, loc)
4036                 {
4037                         ExplicitInterfaceName = int_type;
4038                 }
4039
4040                 public override bool Define (TypeContainer parent)
4041                 {
4042                         PropertyAttributes prop_attr =
4043                                 PropertyAttributes.RTSpecialName |
4044                                 PropertyAttributes.SpecialName;
4045                         
4046                         if (!DoDefine (parent))
4047                                 return false;
4048
4049                         IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4050                         if (IndexerName == null)
4051                                 IndexerName = "Item";
4052                         else if (IsExplicitImpl)
4053                                 Report.Error (592, Location,
4054                                               "Attribute 'IndexerName' is not valid on this declaration " +
4055                                               "type. It is valid on `property' declarations only.");
4056
4057                         ShortName = IndexerName;
4058                         if (IsExplicitImpl) {
4059                                 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4060                                 Name = InterfaceType.FullName + "." + IndexerName;
4061                         } else {
4062                                 InterfaceIndexerName = IndexerName;
4063                                 Name = ShortName;
4064                         }
4065
4066                         if (!CheckBase (parent))
4067                                 return false;
4068
4069                         if (Get != null){
4070                                 InternalParameters ip = new InternalParameters (parent, Parameters);
4071
4072                                 GetData = new MethodData (this, "get", MemberType,
4073                                                           ParameterTypes, ip, CallingConventions.Standard,
4074                                                           Get.OptAttributes, ModFlags, flags, false);
4075
4076                                 if (!GetData.Define (parent))
4077                                         return false;
4078
4079                                 GetBuilder = GetData.MethodBuilder;
4080                         }
4081                         
4082                         if (Set != null){
4083                                 int top = ParameterTypes.Length;
4084                                 Type [] set_pars = new Type [top + 1];
4085                                 ParameterTypes.CopyTo (set_pars, 0);
4086                                 set_pars [top] = MemberType;
4087
4088                                 Parameter [] fixed_parms = Parameters.FixedParameters;
4089
4090                                 if (fixed_parms == null){
4091                                         throw new Exception ("We currently do not support only array arguments in an indexer");
4092                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4093                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4094                                         //
4095                                         // Here is the problem: the `value' parameter has
4096                                         // to come *after* the array parameter in the declaration
4097                                         // like this:
4098                                         // X (object [] x, Type value)
4099                                         // .param [0]
4100                                         //
4101                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4102                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4103                                         
4104                                 }
4105                                 
4106                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4107
4108
4109                                 fixed_parms.CopyTo (tmp, 0);
4110                                 tmp [fixed_parms.Length] = new Parameter (
4111                                         Type, "value", Parameter.Modifier.NONE, null);
4112
4113                                 Parameters set_formal_params = new Parameters (tmp, null, Location);
4114                                 
4115                                 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4116
4117                                 SetData = new MethodData (this, "set", TypeManager.void_type,
4118                                                           set_pars, ip, CallingConventions.Standard,
4119                                                           Set.OptAttributes, ModFlags, flags, false);
4120
4121                                 if (!SetData.Define (parent))
4122                                         return false;
4123
4124                                 SetBuilder = SetData.MethodBuilder;
4125                         }
4126
4127                         //
4128                         // Now name the parameters
4129                         //
4130                         Parameter [] p = Parameters.FixedParameters;
4131                         if (p != null) {
4132                                 int i;
4133                                 
4134                                 for (i = 0; i < p.Length; ++i) {
4135                                         if (Get != null)
4136                                                 GetBuilder.DefineParameter (
4137                                                         i + 1, p [i].Attributes, p [i].Name);
4138
4139                                         if (Set != null)
4140                                                 SetBuilder.DefineParameter (
4141                                                         i + 1, p [i].Attributes, p [i].Name);
4142                                 }
4143
4144                                 if (Set != null)
4145                                         SetBuilder.DefineParameter (
4146                                                 i + 1, ParameterAttributes.None, "value");
4147                                         
4148                                 if (i != ParameterTypes.Length) {
4149                                         Parameter array_param = Parameters.ArrayParameter;
4150                                         SetBuilder.DefineParameter (
4151                                                 i + 1, array_param.Attributes, array_param.Name);
4152                                 }
4153                         }
4154
4155                         if (GetData != null)
4156                                 IsImplementing = GetData.IsImplementing;
4157                         else if (SetData != null)
4158                                 IsImplementing = SetData.IsImplementing;
4159
4160                         //
4161                         // Define the PropertyBuilder if one of the following conditions are met:
4162                         // a) we're not implementing an interface indexer.
4163                         // b) the indexer has a different IndexerName and this is no
4164                         //    explicit interface implementation.
4165                         //
4166                         if (!IsExplicitImpl) {
4167                                 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4168                                         IndexerName, prop_attr, MemberType, ParameterTypes);
4169
4170                                 if (GetData != null)
4171                                         PropertyBuilder.SetGetMethod (GetBuilder);
4172
4173                                 if (SetData != null)
4174                                         PropertyBuilder.SetSetMethod (SetBuilder);
4175                                 
4176                                 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4177                                                              ParameterTypes);
4178                         }
4179
4180                         return true;
4181                 }
4182         }
4183
4184         public class Operator : MemberCore {
4185
4186                 const int AllowedModifiers =
4187                         Modifiers.PUBLIC |
4188                         Modifiers.UNSAFE |
4189                         Modifiers.EXTERN |
4190                         Modifiers.STATIC;
4191
4192                 const int RequiredModifiers =
4193                         Modifiers.PUBLIC |
4194                         Modifiers.STATIC;
4195
4196                 public enum OpType : byte {
4197
4198                         // Unary operators
4199                         LogicalNot,
4200                         OnesComplement,
4201                         Increment,
4202                         Decrement,
4203                         True,
4204                         False,
4205
4206                         // Unary and Binary operators
4207                         Addition,
4208                         Subtraction,
4209
4210                         UnaryPlus,
4211                         UnaryNegation,
4212                         
4213                         // Binary operators
4214                         Multiply,
4215                         Division,
4216                         Modulus,
4217                         BitwiseAnd,
4218                         BitwiseOr,
4219                         ExclusiveOr,
4220                         LeftShift,
4221                         RightShift,
4222                         Equality,
4223                         Inequality,
4224                         GreaterThan,
4225                         LessThan,
4226                         GreaterThanOrEqual,
4227                         LessThanOrEqual,
4228
4229                         // Implicit and Explicit
4230                         Implicit,
4231                         Explicit
4232                 };
4233
4234                 public readonly OpType OperatorType;
4235                 public readonly Expression ReturnType;
4236                 public readonly Expression FirstArgType, SecondArgType;
4237                 public readonly string FirstArgName, SecondArgName;
4238                 public readonly Block  Block;
4239                 public Attributes      OptAttributes;
4240                 public MethodBuilder   OperatorMethodBuilder;
4241                 
4242                 public string MethodName;
4243                 public Method OperatorMethod;
4244
4245                 public Operator (OpType type, Expression ret_type, int flags,
4246                                  Expression arg1type, string arg1name,
4247                                  Expression arg2type, string arg2name,
4248                                  Block block, Attributes attrs, Location loc)
4249                         : base ("", loc)
4250                 {
4251                         OperatorType = type;
4252                         ReturnType = ret_type;
4253                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4254                         FirstArgType = arg1type;
4255                         FirstArgName = arg1name;
4256                         SecondArgType = arg2type;
4257                         SecondArgName = arg2name;
4258                         Block = block;
4259                         OptAttributes = attrs;
4260                 }
4261
4262                 string Prototype (TypeContainer parent)
4263                 {
4264                         return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4265                                 SecondArgType + ")";
4266                 }
4267                 
4268                 public override bool Define (TypeContainer parent)
4269                 {
4270                         int length = 1;
4271                         MethodName = "op_" + OperatorType;
4272                         
4273                         if (SecondArgType != null)
4274                                 length = 2;
4275                         
4276                         Parameter [] param_list = new Parameter [length];
4277
4278                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4279                                 Report.Error (
4280                                         558, Location, 
4281                                         "User defined operators `" +
4282                                         Prototype (parent) +
4283                                         "' must be declared static and public");
4284                                 return false;
4285                         }
4286
4287                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
4288                                                        Parameter.Modifier.NONE, null);
4289                         if (SecondArgType != null)
4290                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4291                                                                Parameter.Modifier.NONE, null);
4292                         
4293                         OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4294                                                      new Parameters (param_list, null, Location),
4295                                                      OptAttributes, Mono.CSharp.Location.Null);
4296
4297                         OperatorMethod.IsOperator = true;                       
4298                         OperatorMethod.Define (parent);
4299
4300                         if (OperatorMethod.MethodBuilder == null)
4301                                 return false;
4302                         
4303                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4304
4305                         Type [] param_types = OperatorMethod.ParameterTypes;
4306                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
4307                         Type return_type = OperatorMethod.GetReturnType ();
4308                         Type first_arg_type = param_types [0];
4309
4310                         // Rules for conversion operators
4311                         
4312                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4313                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
4314                                         Report.Error (
4315                                                 555, Location,
4316                                                 "User-defined conversion cannot take an object of the " +
4317                                                 "enclosing type and convert to an object of the enclosing" +
4318                                                 " type");
4319                                         return false;
4320                                 }
4321                                 
4322                                 if (first_arg_type != declaring_type && return_type != declaring_type){
4323                                         Report.Error (
4324                                                 556, Location, 
4325                                                 "User-defined conversion must convert to or from the " +
4326                                                 "enclosing type");
4327                                         return false;
4328                                 }
4329                                 
4330                                 if (first_arg_type == TypeManager.object_type ||
4331                                     return_type == TypeManager.object_type){
4332                                         Report.Error (
4333                                                 -8, Location,
4334                                                 "User-defined conversion cannot convert to or from " +
4335                                                 "object type");
4336                                         return false;
4337                                 }
4338
4339                                 if (first_arg_type.IsInterface || return_type.IsInterface){
4340                                         Report.Error (
4341                                                 552, Location,
4342                                                 "User-defined conversion cannot convert to or from an " +
4343                                                 "interface type");
4344                                         return false;
4345                                 }
4346                                 
4347                                 if (first_arg_type.IsSubclassOf (return_type) ||
4348                                     return_type.IsSubclassOf (first_arg_type)){
4349                                         Report.Error (
4350                                                 -10, Location,
4351                                                 "User-defined conversion cannot convert between types " +
4352                                                 "that derive from each other");
4353                                         return false;
4354                                 }
4355                         } else if (SecondArgType == null) {
4356                                 // Checks for Unary operators
4357                                 
4358                                 if (first_arg_type != declaring_type){
4359                                         Report.Error (
4360                                                 562, Location,
4361                                                 "The parameter of a unary operator must be the " +
4362                                                 "containing type");
4363                                         return false;
4364                                 }
4365                                 
4366                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4367                                         if (return_type != declaring_type){
4368                                                 Report.Error (
4369                                                         559, Location,
4370                                                         "The parameter and return type for ++ and -- " +
4371                                                         "must be the containing type");
4372                                                 return false;
4373                                         }
4374                                         
4375                                 }
4376                                 
4377                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4378                                         if (return_type != TypeManager.bool_type){
4379                                                 Report.Error (
4380                                                         215, Location,
4381                                                         "The return type of operator True or False " +
4382                                                         "must be bool");
4383                                                 return false;
4384                                         }
4385                                 }
4386                                 
4387                         } else {
4388                                 // Checks for Binary operators
4389                                 
4390                                 if (first_arg_type != declaring_type &&
4391                                     param_types [1] != declaring_type){
4392                                         Report.Error (
4393                                                 563, Location,
4394                                                 "One of the parameters of a binary operator must " +
4395                                                 "be the containing type");
4396                                         return false;
4397                                 }
4398                         }
4399
4400                         return true;
4401                 }
4402                 
4403                 public void Emit (TypeContainer parent)
4404                 {
4405                         EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4406                         Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4407
4408                         //
4409                         // abstract or extern methods have no bodies
4410                         //
4411                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4412                                 return;
4413                         
4414                         OperatorMethod.Block = Block;
4415                         OperatorMethod.Emit (parent);
4416                 }
4417
4418                 public static string GetName (OpType ot)
4419                 {
4420                         switch (ot){
4421                         case OpType.LogicalNot:
4422                                 return "!";
4423                         case OpType.OnesComplement:
4424                                 return "~";
4425                         case OpType.Increment:
4426                                 return "++";
4427                         case OpType.Decrement:
4428                                 return "--";
4429                         case OpType.True:
4430                                 return "true";
4431                         case OpType.False:
4432                                 return "false";
4433                         case OpType.Addition:
4434                                 return "+";
4435                         case OpType.Subtraction:
4436                                 return "-";
4437                         case OpType.UnaryPlus:
4438                                 return "+";
4439                         case OpType.UnaryNegation:
4440                                 return "-";
4441                         case OpType.Multiply:
4442                                 return "*";
4443                         case OpType.Division:
4444                                 return "/";
4445                         case OpType.Modulus:
4446                                 return "%";
4447                         case OpType.BitwiseAnd:
4448                                 return "&";
4449                         case OpType.BitwiseOr:
4450                                 return "|";
4451                         case OpType.ExclusiveOr:
4452                                 return "^";
4453                         case OpType.LeftShift:
4454                                 return "<<";
4455                         case OpType.RightShift:
4456                                 return ">>";
4457                         case OpType.Equality:
4458                                 return "==";
4459                         case OpType.Inequality:
4460                                 return "!=";
4461                         case OpType.GreaterThan:
4462                                 return ">";
4463                         case OpType.LessThan:
4464                                 return "<";
4465                         case OpType.GreaterThanOrEqual:
4466                                 return ">=";
4467                         case OpType.LessThanOrEqual:
4468                                 return "<=";
4469                         case OpType.Implicit:
4470                                 return "implicit";
4471                         case OpType.Explicit:
4472                                 return "explicit";
4473                         default: return "";
4474                         }
4475                 }
4476                 
4477                 public override string ToString ()
4478                 {
4479                         Type return_type = OperatorMethod.GetReturnType();
4480                         Type [] param_types = OperatorMethod.ParameterTypes;
4481                         
4482                         if (SecondArgType == null)
4483                                 return String.Format (
4484                                         "{0} operator {1}({2})",
4485                                         TypeManager.CSharpName (return_type),
4486                                         GetName (OperatorType),
4487                                         param_types [0]);
4488                         else
4489                                 return String.Format (
4490                                         "{0} operator {1}({2}, {3})",
4491                                         TypeManager.CSharpName (return_type),
4492                                         GetName (OperatorType),
4493                                         param_types [0], param_types [1]);
4494                 }
4495         }
4496
4497         //
4498         // This is used to compare method signatures
4499         //
4500         struct MethodSignature {
4501                 public string Name;
4502                 public Type RetType;
4503                 public Type [] Parameters;
4504                 
4505                 /// <summary>
4506                 ///    This delegate is used to extract methods which have the
4507                 ///    same signature as the argument
4508                 /// </summary>
4509                 public static MemberFilter method_signature_filter;
4510
4511                 /// <summary>
4512                 ///   This delegate is used to extract inheritable methods which
4513                 ///   have the same signature as the argument.  By inheritable,
4514                 ///   this means that we have permissions to override the method
4515                 ///   from the current assembly and class
4516                 /// </summary>
4517                 public static MemberFilter inheritable_method_signature_filter;
4518
4519                 /// <summary>
4520                 ///   This delegate is used to extract inheritable methods which
4521                 ///   have the same signature as the argument.  By inheritable,
4522                 ///   this means that we have permissions to override the method
4523                 ///   from the current assembly and class
4524                 /// </summary>
4525                 public static MemberFilter inheritable_property_signature_filter;
4526                 
4527                 static MethodSignature ()
4528                 {
4529                         method_signature_filter = new MemberFilter (MemberSignatureCompare);
4530                         inheritable_method_signature_filter = new MemberFilter (
4531                                 InheritableMemberSignatureCompare);
4532                         inheritable_property_signature_filter = new MemberFilter (
4533                                 InheritablePropertySignatureCompare);
4534                 }
4535                 
4536                 public MethodSignature (string name, Type ret_type, Type [] parameters)
4537                 {
4538                         Name = name;
4539                         RetType = ret_type;
4540
4541                         if (parameters == null)
4542                                 Parameters = TypeManager.NoTypes;
4543                         else
4544                                 Parameters = parameters;
4545                 }
4546                 
4547                 public override int GetHashCode ()
4548                 {
4549                         return Name.GetHashCode ();
4550                 }
4551
4552                 public override bool Equals (Object o)
4553                 {
4554                         MethodSignature other = (MethodSignature) o;
4555
4556                         if (other.Name != Name)
4557                                 return false;
4558
4559                         if (other.RetType != RetType)
4560                                 return false;
4561                         
4562                         if (Parameters == null){
4563                                 if (other.Parameters == null)
4564                                         return true;
4565                                 return false;
4566                         }
4567
4568                         if (other.Parameters == null)
4569                                 return false;
4570                         
4571                         int c = Parameters.Length;
4572                         if (other.Parameters.Length != c)
4573                                 return false;
4574
4575                         for (int i = 0; i < c; i++)
4576                                 if (other.Parameters [i] != Parameters [i])
4577                                         return false;
4578
4579                         return true;
4580                 }
4581
4582                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4583                 {
4584                         MethodSignature sig = (MethodSignature) filter_criteria;
4585
4586                         if (m.Name != sig.Name)
4587                                 return false;
4588
4589                         Type ReturnType;
4590                         MethodInfo mi = m as MethodInfo;
4591                         PropertyInfo pi = m as PropertyInfo;
4592
4593                         if (mi != null)
4594                                 ReturnType = mi.ReturnType;
4595                         else if (pi != null)
4596                                 ReturnType = pi.PropertyType;
4597                         else
4598                                 return false;
4599                         
4600                         //
4601                         // we use sig.RetType == null to mean `do not check the
4602                         // method return value.  
4603                         //
4604                         if (sig.RetType != null)
4605                                 if (ReturnType != sig.RetType)
4606                                         return false;
4607
4608                         Type [] args;
4609                         if (mi != null)
4610                                 args = TypeManager.GetArgumentTypes (mi);
4611                         else
4612                                 args = TypeManager.GetArgumentTypes (pi);
4613                         Type [] sigp = sig.Parameters;
4614
4615                         if (args.Length != sigp.Length)
4616                                 return false;
4617
4618                         for (int i = args.Length; i > 0; ){
4619                                 i--;
4620                                 if (args [i] != sigp [i])
4621                                         return false;
4622                         }
4623                         return true;
4624                 }
4625
4626                 //
4627                 // This filter should be used when we are requesting methods that
4628                 // we want to override.
4629                 //
4630                 // This makes a number of assumptions, for example
4631                 // that the methods being extracted are of a parent
4632                 // class (this means we know implicitly that we are
4633                 // being called to find out about members by a derived
4634                 // class).
4635                 // 
4636                 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4637                 {
4638                         if (MemberSignatureCompare (m, filter_criteria)){
4639                                 MethodInfo mi = (MethodInfo) m;
4640                                 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4641
4642                                 // If only accessible to the current class.
4643                                 if (prot == MethodAttributes.Private)
4644                                         return false;
4645
4646                                 // If only accessible to the defining assembly or 
4647                                 if (prot == MethodAttributes.FamANDAssem ||
4648                                     prot == MethodAttributes.Assembly){
4649                                         if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4650                                                 return true;
4651                                         else
4652                                                 return false;
4653                                 }
4654
4655                                 // Anything else (FamOrAssembly and Public) is fine
4656                                 return true;
4657                         }
4658                         return false;
4659                 }
4660
4661                 //
4662                 // This filter should be used when we are requesting properties that
4663                 // we want to override.
4664                 //
4665                 // This makes a number of assumptions, for example
4666                 // that the methods being extracted are of a parent
4667                 // class (this means we know implicitly that we are
4668                 // being called to find out about members by a derived
4669                 // class).
4670                 // 
4671                 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4672                 {
4673                         if (MemberSignatureCompare (m, filter_criteria)){
4674                                 PropertyInfo pi = (PropertyInfo) m;
4675
4676                                 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4677                                 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4678
4679                                 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4680
4681                                 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4682
4683                                 // If only accessible to the current class.
4684                                 if (prot == MethodAttributes.Private)
4685                                         return false;
4686
4687                                 // If only accessible to the defining assembly or 
4688                                 if (prot == MethodAttributes.FamANDAssem ||
4689                                     prot == MethodAttributes.Assembly){
4690                                         if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4691                                                 return true;
4692                                         else
4693                                                 return false;
4694                                 }
4695
4696                                 // Anything else (FamOrAssembly and Public) is fine
4697                                 return true;
4698                         }
4699                         return false;
4700                 }
4701         }
4702 }