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