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