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