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