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