2002-05-05 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / class.cs
1 //
2 // class.cs: Class and Struct handlers
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //
6 // Licensed under the terms of the GNU GPL
7 //
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
9 //
10 //
11
12 using System.Collections;
13 using System.Reflection;
14 using System.Reflection.Emit;
15 using System;
16 using System.Runtime.CompilerServices;
17 using System.Diagnostics.SymbolStore;
18
19 namespace Mono.CSharp {
20
21         /// <summary>
22         ///   This is the base class for structs and classes.  
23         /// </summary>
24         public class TypeContainer : DeclSpace {
25                 // Holds a list of classes and structures
26                 ArrayList types;
27
28                 // Holds the list of properties
29                 ArrayList properties;
30
31                 // Holds the list of enumerations
32                 ArrayList enums;
33
34                 // Holds the list of delegates
35                 ArrayList delegates;
36                 
37                 // Holds the list of constructors
38                 ArrayList instance_constructors;
39
40                 // Holds the list of fields
41                 ArrayList fields;
42
43                 // Holds a list of fields that have initializers
44                 ArrayList initialized_fields;
45
46                 // Holds a list of static fields that have initializers
47                 ArrayList initialized_static_fields;
48
49                 // Holds the list of constants
50                 ArrayList constants;
51
52                 // Holds the list of
53                 ArrayList interfaces;
54
55                 // Holds order in which interfaces must be closed
56                 ArrayList interface_order;
57                 
58                 // Holds the methods.
59                 ArrayList methods;
60
61                 // Holds the events
62                 ArrayList events;
63
64                 // Holds the indexers
65                 ArrayList indexers;
66
67                 // Holds the operators
68                 ArrayList operators;
69
70                 //
71                 // Pointers to the default constructor and the default static constructor
72                 //
73                 Constructor default_constructor;
74                 Constructor default_static_constructor;
75
76                 //
77                 // Whether we have seen a static constructor for this class or not
78                 //
79                 bool have_static_constructor = false;
80                 
81                 //
82                 // This one is computed after we can distinguish interfaces
83                 // from classes from the arraylist `type_bases' 
84                 //
85                 string     base_class_name;
86
87                 ArrayList type_bases;
88
89                 // Attributes for this type
90                 protected Attributes attributes;
91
92                 // Information in the case we are an attribute type
93
94                 public AttributeTargets Targets = AttributeTargets.All;
95                 public bool AllowMultiple = false;
96                 public bool Inherited;
97                 
98
99                 public TypeContainer (TypeContainer parent, string name, Location l)
100                         : base (parent, name, l)
101                 {
102                         string n;
103                         types = new ArrayList ();
104
105                         if (parent == null)
106                                 n = "";
107                         else
108                                 n = parent.Name;
109
110                         base_class_name = null;
111                         
112                         //Console.WriteLine ("New class " + name + " inside " + n);
113                 }
114
115                 public AdditionResult AddConstant (Const constant)
116                 {
117                         AdditionResult res;
118                         string name = constant.Name;
119
120                         if ((res = IsValid (name)) != AdditionResult.Success)
121                                 return res;
122                         
123                         if (constants == null)
124                                 constants = new ArrayList ();
125
126                         constants.Add (constant);
127                         DefineName (name, constant);
128
129                         return AdditionResult.Success;
130                 }
131
132                 public AdditionResult AddEnum (Mono.CSharp.Enum e)
133                 {
134                         AdditionResult res;
135                         string name = e.Name;
136
137                         if ((res = IsValid (name)) != AdditionResult.Success)
138                                 return res;
139
140                         if (enums == null)
141                                 enums = new ArrayList ();
142
143                         enums.Add (e);
144                         DefineName (name, e);
145
146                         return AdditionResult.Success;
147                 }
148                 
149                 public AdditionResult AddClass (Class c)
150                 {
151                         AdditionResult res;
152                         string name = c.Name;
153
154
155                         if ((res = IsValid (name)) != AdditionResult.Success)
156                                 return res;
157
158                         DefineName (name, c);
159                         types.Add (c);
160
161                         return AdditionResult.Success;
162                 }
163
164                 public AdditionResult AddStruct (Struct s)
165                 {
166                         AdditionResult res;
167                         string name = s.Name;
168                         
169                         if ((res = IsValid (name)) != AdditionResult.Success)
170                                 return res;
171
172                         DefineName (name, s);
173                         types.Add (s);
174
175                         return AdditionResult.Success;
176                 }
177
178                 public AdditionResult AddDelegate (Delegate d)
179                 {
180                         AdditionResult res;
181                         string name = d.Name;
182
183                         if ((res = IsValid (name)) != AdditionResult.Success)
184                                 return res;
185
186                         if (delegates == null)
187                                 delegates = new ArrayList ();
188                         
189                         DefineName (name, d);
190                         delegates.Add (d);
191
192                         return AdditionResult.Success;
193                 }
194
195                 public AdditionResult AddMethod (Method method)
196                 {
197                         string name = method.Name;
198                         Object value = defined_names [name];
199                         
200                         if (value != null && (!(value is Method)))
201                                 return AdditionResult.NameExists;
202
203                         if (methods == null)
204                                 methods = new ArrayList ();
205
206                         methods.Add (method);
207                         if (value != null)
208                                 DefineName (name, method);
209
210                         return AdditionResult.Success;
211                 }
212
213                 public AdditionResult AddConstructor (Constructor c)
214                 {
215                         if (c.Name != Basename) 
216                                 return AdditionResult.NotAConstructor;
217
218                         bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
219                         
220                         if (is_static){
221                                 have_static_constructor = true;
222                                 if (default_static_constructor != null){
223                                         Console.WriteLine ("I have a static constructor already");
224                                         Console.WriteLine ("   " + default_static_constructor);
225                                         return AdditionResult.MethodExists;
226                                 }
227
228                                 default_static_constructor = c;
229                         } else {
230                                 if (c.IsDefault ()){
231                                         if (default_constructor != null)
232                                                 return AdditionResult.MethodExists;
233                                         default_constructor = c;
234                                 }
235                                 
236                                 if (instance_constructors == null)
237                                         instance_constructors = new ArrayList ();
238                                 
239                                 instance_constructors.Add (c);
240                         }
241                         
242                         return AdditionResult.Success;
243                 }
244                 
245                 public AdditionResult AddInterface (Interface iface)
246                 {
247                         AdditionResult res;
248                         string name = iface.Name;
249
250                         if ((res = IsValid (name)) != AdditionResult.Success)
251                                 return res;
252                         
253                         if (interfaces == null)
254                                 interfaces = new ArrayList ();
255                         interfaces.Add (iface);
256                         DefineName (name, iface);
257                         
258                         return AdditionResult.Success;
259                 }
260
261                 public AdditionResult AddField (Field field)
262                 {
263                         AdditionResult res;
264                         string name = field.Name;
265                         
266                         if ((res = IsValid (name)) != AdditionResult.Success)
267                                 return res;
268
269                         if (fields == null)
270                                 fields = new ArrayList ();
271
272                         fields.Add (field);
273                         
274                         if (field.Initializer != null){
275                                 if ((field.ModFlags & Modifiers.STATIC) != 0){
276                                         if (initialized_static_fields == null)
277                                                 initialized_static_fields = new ArrayList ();
278
279                                         initialized_static_fields.Add (field);
280
281                                         //
282                                         // We have not seen a static constructor,
283                                         // but we will provide static initialization of fields
284                                         //
285                                         have_static_constructor = true;
286                                 } else {
287                                         if (initialized_fields == null)
288                                                 initialized_fields = new ArrayList ();
289                                 
290                                         initialized_fields.Add (field);
291                                 }
292                         }
293                         
294                         DefineName (name, field);
295                         return AdditionResult.Success;
296                 }
297
298                 public AdditionResult AddProperty (Property prop)
299                 {
300                         AdditionResult res;
301                         string name = prop.Name;
302
303                         if ((res = IsValid (name)) != AdditionResult.Success)
304                                 return res;
305
306                         if (properties == null)
307                                 properties = new ArrayList ();
308
309                         properties.Add (prop);
310                         DefineName (name, prop);
311
312                         return AdditionResult.Success;
313                 }
314
315                 public AdditionResult AddEvent (Event e)
316                 {
317                         AdditionResult res;
318                         string name = e.Name;
319
320                         if ((res = IsValid (name)) != AdditionResult.Success)
321                                 return res;
322
323                         if (events == null)
324                                 events = new ArrayList ();
325                         
326                         events.Add (e);
327                         DefineName (name, e);
328
329                         return AdditionResult.Success;
330                 }
331
332                 public AdditionResult AddIndexer (Indexer i)
333                 {
334                         if (indexers == null)
335                                 indexers = new ArrayList ();
336
337                         indexers.Add (i);
338
339                         return AdditionResult.Success;
340                 }
341
342                 public AdditionResult AddOperator (Operator op)
343                 {
344                         if (operators == null)
345                                 operators = new ArrayList ();
346
347                         operators.Add (op);
348
349                         return AdditionResult.Success;
350                 }
351
352                 public void RegisterOrder (Interface iface)
353                 {
354                         if (interface_order == null)
355                                 interface_order = new ArrayList ();
356
357                         interface_order.Add (iface);
358                 }
359                 
360                 public ArrayList Types {
361                         get {
362                                 return types;
363                         }
364                 }
365
366                 public ArrayList Methods {
367                         get {
368                                 return methods;
369                         }
370                 }
371
372                 public ArrayList Constants {
373                         get {
374                                 return constants;
375                         }
376                 }
377
378                 public ArrayList Interfaces {
379                         get {
380                                 return interfaces;
381                         }
382                 }
383                 
384                 public string Base {
385                         get {
386                                 return base_class_name;
387                         }
388                 }
389                 
390                 public ArrayList Bases {
391                         get {
392                                 return type_bases;
393                         }
394
395                         set {
396                                 type_bases = value;
397                         }
398                 }
399
400                 public ArrayList Fields {
401                         get {
402                                 return fields;
403                         }
404                 }
405
406                 public ArrayList InstanceConstructors {
407                         get {
408                                 return instance_constructors;
409                         }
410                 }
411
412                 public ArrayList Properties {
413                         get {
414                                 return properties;
415                         }
416                 }
417
418                 public ArrayList Events {
419                         get {
420                                 return events;
421                         }
422                 }
423                 
424                 public ArrayList Enums {
425                         get {
426                                 return enums;
427                         }
428                 }
429
430                 public ArrayList Indexers {
431                         get {
432                                 return indexers;
433                         }
434                 }
435
436                 public ArrayList Operators {
437                         get {
438                                 return operators;
439                         }
440                 }
441
442                 public ArrayList Delegates {
443                         get {
444                                 return delegates;
445                         }
446                 }
447                 
448                 public Attributes OptAttributes {
449                         get {
450                                 return attributes;
451                         }
452                 }
453                 
454                 public bool HaveStaticConstructor {
455                         get {
456                                 return have_static_constructor;
457                         }
458                 }
459                 
460                 public virtual TypeAttributes TypeAttr {
461                         get {
462                                 return Modifiers.TypeAttr (ModFlags, this);
463                         }
464                 }
465
466                 //
467                 // Emits the instance field initializers
468                 //
469                 public bool EmitFieldInitializers (EmitContext ec)
470                 {
471                         ArrayList fields;
472                         ILGenerator ig = ec.ig;
473                         Expression instance_expr;
474                         
475                         if (ec.IsStatic){
476                                 fields = initialized_static_fields;
477                                 instance_expr = null;
478                         } else {
479                                 fields = initialized_fields;
480                                 instance_expr = new This (Location.Null).Resolve (ec);
481                         }
482
483                         if (fields == null)
484                                 return true;
485                         
486                         foreach (Field f in fields){
487                                 Object init = f.Initializer;
488
489                                 Expression e;
490                                 if (init is Expression)
491                                         e = (Expression) init;
492                                 else {
493                                         string base_type = f.Type.Substring (0, f.Type.IndexOf ("["));
494                                         string rank = f.Type.Substring (f.Type.IndexOf ("["));
495                                         e = new ArrayCreation (base_type, rank, (ArrayList)init, f.Location);
496                                 }
497
498                                 Location l = f.Location;
499                                 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
500                                 fe.InstanceExpression = instance_expr;
501                                 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                                 for (int i = argument_list.Count; i > 0; ){
2527                                         --i;
2528
2529                                         Argument a = (Argument) argument_list [i];
2530                                         if (!a.Resolve (ec, location))
2531                                                 return false;
2532                                 }
2533                         }
2534
2535                         if (this is ConstructorBaseInitializer)
2536                                 t = ec.ContainerType.BaseType;
2537                         else
2538                                 t = ec.ContainerType;
2539                         
2540                         parent_constructor_group = Expression.MemberLookup (
2541                                 ec, t, ".ctor", 
2542                                 MemberTypes.Constructor,
2543                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2544                                 location);
2545                         
2546                         if (parent_constructor_group == null){
2547                                 Report.Error (1501, location,
2548                                        "Can not find a constructor for this argument list");
2549                                 return false;
2550                         }
2551                         
2552                         parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
2553                                 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2554                         
2555                         if (parent_constructor == null){
2556                                 Report.Error (1501, location,
2557                                        "Can not find a constructor for this argument list");
2558                                 return false;
2559                         }
2560                         
2561                         return true;
2562                 }
2563
2564                 public void Emit (EmitContext ec)
2565                 {
2566                         ec.ig.Emit (OpCodes.Ldarg_0);
2567                         if (argument_list != null)
2568                                 Invocation.EmitArguments (ec, null, argument_list);
2569                         ec.ig.Emit (OpCodes.Call, parent_constructor);
2570                 }
2571         }
2572
2573         public class ConstructorBaseInitializer : ConstructorInitializer {
2574                 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2575                 {
2576                 }
2577         }
2578
2579         public class ConstructorThisInitializer : ConstructorInitializer {
2580                 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2581                 {
2582                 }
2583         }
2584         
2585         public class Constructor : MethodCore {
2586                 public ConstructorBuilder ConstructorBuilder;
2587                 public ConstructorInitializer Initializer;
2588                 public Attributes OptAttributes;
2589
2590                 // <summary>
2591                 //   Modifiers allowed for a constructor.
2592                 // </summary>
2593                 const int AllowedModifiers =
2594                         Modifiers.PUBLIC |
2595                         Modifiers.PROTECTED |
2596                         Modifiers.INTERNAL |
2597                         Modifiers.STATIC |
2598                         Modifiers.UNSAFE |
2599                         Modifiers.PRIVATE;
2600
2601                 //
2602                 // The spec claims that static is not permitted, but
2603                 // my very own code has static constructors.
2604                 //
2605                 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2606                         : base (name, args, l)
2607                 {
2608                         Initializer = init;
2609                 }
2610
2611                 //
2612                 // Returns true if this is a default constructor
2613                 //
2614                 public bool IsDefault ()
2615                 {
2616                         if ((ModFlags & Modifiers.STATIC) != 0)
2617                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2618                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2619                         
2620                         else
2621                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2622                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2623                                         (Initializer is ConstructorBaseInitializer) &&
2624                                         (Initializer.Arguments == null);
2625                 }
2626
2627                 //
2628                 // Creates the ConstructorBuilder
2629                 //
2630                 public override bool Define (TypeContainer parent)
2631                 {
2632                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
2633                                                MethodAttributes.SpecialName);
2634
2635                         Type [] parameters = ParameterTypes (parent);
2636
2637                         if ((ModFlags & Modifiers.STATIC) != 0)
2638                                 ca |= MethodAttributes.Static;
2639                         else {
2640                                 if (parent is Struct && parameters.Length == 0){
2641                                         Report.Error (
2642                                                 568, Location, 
2643                                                 "Structs can not contain explicit parameterless " +
2644                                                 "constructors");
2645                                         return false;
2646                                 }
2647                                 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2648                         }
2649
2650                         foreach (Type partype in parameters)
2651                                 if (!TypeContainer.AsAccessible (partype, ModFlags))
2652                                         return false;
2653
2654                         ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2655                                 ca, GetCallingConvention (parent is Class), parameters);
2656
2657                         //
2658                         // HACK because System.Reflection.Emit is lame
2659                         //
2660                         ParameterInfo = new InternalParameters (parent, Parameters);
2661
2662                         if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
2663                                 Report.Error (
2664                                         111, Location,
2665                                         "Class `" +parent.Name+ "' already contains a definition with the " +
2666                                         "same return value and parameter types for constructor `" + Name
2667                                         + "'");
2668                                 return false;
2669                         }
2670
2671                         return true;
2672                 }
2673
2674                 //
2675                 // Emits the code
2676                 //
2677                 public void Emit (TypeContainer parent)
2678                 {
2679                         ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2680                         EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2681
2682                         if (parent is Class && ((ModFlags & Modifiers.STATIC) == 0)){
2683                                 if (Initializer == null)
2684                                         Initializer = new ConstructorBaseInitializer (null, parent.Location);
2685                                 
2686                                 if (!Initializer.Resolve (ec))
2687                                         return;
2688                         }
2689
2690                         LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder);
2691                         
2692                         //
2693                         // Classes can have base initializers and instance field initializers.
2694                         //
2695                         if (parent is Class){
2696                                 if ((ModFlags & Modifiers.STATIC) == 0){
2697                                         parent.EmitFieldInitializers (ec);
2698                                         Initializer.Emit (ec);
2699                                 }
2700                         }
2701                         
2702                         if ((ModFlags & Modifiers.STATIC) != 0)
2703                                 parent.EmitFieldInitializers (ec);
2704
2705                         Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2706
2707                         ec.EmitTopBlock (Block, Location);
2708                 }
2709         }
2710
2711         //
2712         // Fields and Events both generate FieldBuilders, we use this to share 
2713         // their common bits.  This is also used to flag usage of the field
2714         //
2715         abstract public class FieldBase : MemberCore {
2716                 public readonly string Type;
2717                 public readonly Object Initializer;
2718                 public readonly Attributes OptAttributes;
2719                 public FieldBuilder  FieldBuilder;
2720                 public Status status;
2721
2722                 [Flags]
2723                 public enum Status : byte { ASSIGNED = 1, USED = 2 }
2724
2725                 //
2726                 // The constructor is only exposed to our children
2727                 //
2728                 protected FieldBase (string type, int mod, int allowed_mod, string name,
2729                                      object init, Attributes attrs, Location loc)
2730                         : base (name, loc)
2731                 {
2732                         Type = type;
2733                         ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
2734                         Initializer = init;
2735                         OptAttributes = attrs;
2736                 }
2737         }
2738
2739         //
2740         // The Field class is used to represents class/struct fields during parsing.
2741         //
2742         public class Field : FieldBase {
2743                 // <summary>
2744                 //   Modifiers allowed in a class declaration
2745                 // </summary>
2746                 const int AllowedModifiers =
2747                         Modifiers.NEW |
2748                         Modifiers.PUBLIC |
2749                         Modifiers.PROTECTED |
2750                         Modifiers.INTERNAL |
2751                         Modifiers.PRIVATE |
2752                         Modifiers.STATIC |
2753                         Modifiers.VOLATILE |
2754                         Modifiers.UNSAFE |
2755                         Modifiers.READONLY;
2756
2757                 public Field (string type, int mod, string name, Object expr_or_array_init,
2758                               Attributes attrs, Location loc)
2759                         : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
2760                 {
2761                 }
2762
2763                 public override bool Define (TypeContainer parent)
2764                 {
2765                         Type t = RootContext.LookupType (parent, Type, false, Location);
2766                         
2767                         if (t == null)
2768                                 return false;
2769
2770                         if (!TypeContainer.AsAccessible (t, ModFlags))
2771                                 return false;
2772
2773                         if (t.IsPointer && !UnsafeOK (parent))
2774                                 return false;
2775                                 
2776                         if (RootContext.WarningLevel > 1){
2777                                 Type ptype = parent.TypeBuilder.BaseType;
2778
2779                                 // ptype is only null for System.Object while compiling corlib.
2780                                 if (ptype != null){
2781                                         MemberInfo [] mi;
2782                                         
2783                                         mi = TypeContainer.FindMembers (
2784                                                 ptype, MemberTypes.Method,
2785                                                 BindingFlags.Public |
2786                                                 BindingFlags.Static | BindingFlags.Instance,
2787                                                 System.Type.FilterName, Name);
2788                                 }
2789                         }
2790
2791                         if ((ModFlags & Modifiers.VOLATILE) != 0){
2792                                 if (!t.IsClass){
2793                                         if (TypeManager.IsEnumType (t))
2794                                                 t = TypeManager.EnumToUnderlying (t);
2795
2796                                         if (!((t == TypeManager.bool_type) ||
2797                                               (t == TypeManager.sbyte_type) ||
2798                                               (t == TypeManager.byte_type) ||
2799                                               (t == TypeManager.short_type) ||    
2800                                               (t == TypeManager.ushort_type) ||
2801                                               (t == TypeManager.int32_type) ||    
2802                                               (t == TypeManager.uint32_type) ||    
2803                                               (t == TypeManager.char_type) ||    
2804                                               (t == TypeManager.float_type))){
2805                                                 Report.Error (
2806                                                         677, Location, parent.MakeName (Name) +
2807                                                         " A volatile field can not be of type `" +
2808                                                         TypeManager.CSharpName (t) + "'");
2809                                                 return false;
2810                                         }
2811                                 }
2812                         }
2813                         
2814                         FieldBuilder = parent.TypeBuilder.DefineField (
2815                                 Name, t, Modifiers.FieldAttr (ModFlags));
2816
2817                         TypeManager.RegisterFieldBase (FieldBuilder, this);
2818                         return true;
2819                 }
2820
2821                 public void Emit (TypeContainer tc)
2822                 {
2823                         EmitContext ec = new EmitContext (tc, Location, null,
2824                                                           FieldBuilder.FieldType, ModFlags);
2825
2826                         Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
2827                 }
2828         }
2829
2830         public class Property : MemberCore {
2831                 public readonly string Type;
2832                 public Block           Get, Set;
2833                 public PropertyBuilder PropertyBuilder;
2834                 public Attributes OptAttributes;
2835                 public MethodBuilder GetBuilder, SetBuilder;
2836
2837                 //
2838                 // The type, once we compute it.
2839                 
2840                 Type PropertyType;
2841
2842                 const int AllowedModifiers =
2843                         Modifiers.NEW |
2844                         Modifiers.PUBLIC |
2845                         Modifiers.PROTECTED |
2846                         Modifiers.INTERNAL |
2847                         Modifiers.PRIVATE |
2848                         Modifiers.STATIC |
2849                         Modifiers.SEALED |
2850                         Modifiers.OVERRIDE |
2851                         Modifiers.ABSTRACT |
2852                         Modifiers.UNSAFE |
2853                         Modifiers.EXTERN |
2854                         Modifiers.VIRTUAL;
2855
2856                 public Property (string type, string name, int mod_flags, Block get_block, Block set_block,
2857                                  Attributes attrs, Location loc)
2858                         : base (name, loc)
2859                 {
2860                         Type = type;
2861                         ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
2862                         Get = get_block;
2863                         Set = set_block;
2864                         OptAttributes = attrs;
2865                 }
2866
2867                 //
2868                 // Checks our base implementation if any
2869                 //
2870                 bool CheckBase (MethodAttributes flags, TypeContainer parent)
2871                 {
2872                         //
2873                         // Find properties with the same name on the base class
2874                         //
2875
2876                         MemberInfo [] props;
2877                         MemberInfo [] props_static = TypeManager.MemberLookup (
2878                                 parent.TypeBuilder, 
2879                                 parent.TypeBuilder.BaseType,
2880                                 MemberTypes.Property, BindingFlags.Public | BindingFlags.Static,
2881                                 Name);
2882
2883                         MemberInfo [] props_instance = TypeManager.MemberLookup (
2884                                 parent.TypeBuilder, 
2885                                 parent.TypeBuilder.BaseType,
2886                                 MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance,
2887                                 Name);
2888
2889                         //
2890                         // Find if we have anything
2891                         //
2892                         if (props_static != null && props_static.Length > 0)
2893                                 props = props_static;
2894                         else if (props_instance != null && props_instance.Length > 0)
2895                                 props = props_instance;
2896                         else
2897                                 props = null;
2898
2899                         //
2900                         // If we have something on the base.
2901                         if (props != null && props.Length > 0){
2902                                 if (props.Length > 1)
2903                                         throw new Exception ("Should not happen");
2904                                 
2905                                 PropertyInfo pi = (PropertyInfo) props [0];
2906
2907                                 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
2908                                 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
2909
2910                                 MethodInfo reference = inherited_get == null ?
2911                                         inherited_set : inherited_get;
2912                                 
2913                                 if (reference != null)
2914                                         if (!CheckMethodAgainstBase (parent, flags, reference))
2915                                                 return false;
2916                                 
2917                         } else {
2918                                 if ((ModFlags & Modifiers.NEW) != 0)
2919                                         WarningNotHiding (parent);
2920                                 
2921                                 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2922                                         Report.Error (115, Location,
2923                                                       parent.MakeName (Name) +
2924                                                       " no suitable properties found to override");
2925                                         return false;
2926                                 }
2927                         }
2928                         return true;
2929                 }
2930
2931                 bool DefineMethod (TypeContainer parent, Type iface_type, string short_name,
2932                                    MethodAttributes flags, bool is_get)
2933                 {
2934                         Type [] parameters = TypeManager.NoTypes;
2935                         MethodInfo implementing;
2936                         Type fn_type;
2937                         string name;
2938
2939                         if (is_get){
2940                                 fn_type = PropertyType;
2941                                 name = "get_" + short_name;
2942                         } else {
2943                                 name = "set_" + short_name;
2944                                 parameters = new Type [1];
2945                                 parameters [0] = PropertyType;
2946                                 fn_type = TypeManager.void_type;
2947                         }
2948
2949                         implementing = parent.IsInterfaceMethod (
2950                                 iface_type, name, fn_type, parameters, false);
2951
2952                         //
2953                         // For implicit implementations, make sure we are public, for
2954                         // explicit implementations, make sure we are private.
2955                         //
2956                         if (implementing != null){
2957                                 //
2958                                 // Setting null inside this block will trigger a more
2959                                 // verbose error reporting for missing interface implementations
2960                                 //
2961                                 // The "candidate" function has been flagged already
2962                                 // but it wont get cleared
2963                                 //
2964                                 if (iface_type == null){
2965                                         //
2966                                         // We already catch different accessibility settings
2967                                         // so we just need to check that we are not private
2968                                         //
2969                                         if ((ModFlags & Modifiers.PRIVATE) != 0)
2970                                                 implementing = null;
2971                                         
2972                                         //
2973                                         // Static is not allowed
2974                                         //
2975                                         if ((ModFlags & Modifiers.STATIC) != 0)
2976                                                 implementing = null;
2977                                 } else {
2978                                         if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2979                                                 Report.Error (
2980                                                         106, Location, "`public' or `abstract' modifiers "+
2981                                                         "are not allowed in explicit interface declarations"
2982                                                         );
2983                                                 implementing = null;
2984                                         }
2985                                 }
2986                         }
2987                         
2988                         //
2989                         // If implementing is still valid, set flags
2990                         //
2991                         if (implementing != null){
2992                                 //
2993                                 // When implementing interface methods, set NewSlot.
2994                                 //
2995                                 if (implementing.DeclaringType.IsInterface)
2996                                         flags |= MethodAttributes.NewSlot;
2997                                 
2998                                 flags |=
2999                                         MethodAttributes.Virtual |
3000                                         MethodAttributes.HideBySig;
3001
3002                                 //
3003                                 // clear the pending flag
3004                                 //
3005                                 parent.IsInterfaceMethod (
3006                                         iface_type, name, fn_type, parameters, true);
3007                         }
3008
3009                         //
3010                         // If this is not an explicit interface implementation,
3011                         // clear implementing, as it is only used for explicit
3012                         // interface implementation
3013                         //
3014                         if (Name.IndexOf (".") == -1)
3015                                 implementing = null;
3016                         
3017                         if (is_get){
3018                                 GetBuilder = parent.TypeBuilder.DefineMethod (
3019                                         name, flags, PropertyType, null);
3020                                 PropertyBuilder.SetGetMethod (GetBuilder);
3021                         
3022                                 if (implementing != null)
3023                                         parent.TypeBuilder.DefineMethodOverride (
3024                                                 GetBuilder, implementing);
3025                                 
3026                                 //
3027                                 // HACK because System.Reflection.Emit is lame
3028                                 //
3029                                 InternalParameters ip = new InternalParameters (
3030                                         parent, Parameters.GetEmptyReadOnlyParameters ());
3031                                 
3032                                 if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
3033                                         Report.Error (111, Location,
3034                                                       "Class `" + parent.Name +
3035                                                       "' already contains a definition with the " +
3036                                                       "same return value and parameter types as the " +
3037                                                       "'get' method of property `" + Name + "'");
3038                                         return false;
3039                                 }
3040                         } else {
3041                                 SetBuilder = parent.TypeBuilder.DefineMethod (
3042                                         name, flags, null, parameters);
3043                                 
3044                                 if (implementing != null)
3045                                         parent.TypeBuilder.DefineMethodOverride (
3046                                                 SetBuilder, implementing);
3047                                 
3048                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
3049                                 PropertyBuilder.SetSetMethod (SetBuilder);
3050
3051                                 //
3052                                 // HACK because System.Reflection.Emit is lame
3053                                 //
3054                                 Parameter [] parms = new Parameter [1];
3055                                 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3056                                 InternalParameters ip = new InternalParameters (
3057                                         parent, new Parameters (parms, null, Location));
3058
3059                                 if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
3060                                         Report.Error (
3061                                                 111, Location,
3062                                                 "Class `" + parent.Name +
3063                                                 "' already contains a definition with the " +
3064                                                 "same return value and parameter types as the " +
3065                                                 "'set' method of property `" + Name + "'");
3066                                         return false;
3067                                 }
3068                         }
3069
3070                         return true;
3071                 }
3072
3073                 public override bool Define (TypeContainer parent)
3074                 {
3075                         Type iface_type = null;
3076                         string short_name;
3077                         
3078                         if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3079                                 return false;
3080
3081                         MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
3082                         
3083                         flags |= MethodAttributes.HideBySig |
3084                                 MethodAttributes.SpecialName;
3085
3086                         // Lookup Type, verify validity
3087                         PropertyType = RootContext.LookupType (parent, Type, false, Location);
3088                         if (PropertyType == null)
3089                                 return false;
3090
3091                         // verify accessibility
3092                         if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
3093                                 return false;
3094
3095                         if (PropertyType.IsPointer && !UnsafeOK (parent))
3096                                 return false;
3097                         
3098                         if (!CheckBase (flags, parent))
3099                                 return false;
3100
3101                         //
3102                         // Check for explicit interface implementation
3103                         //
3104                         if (Name.IndexOf (".") != -1){
3105                                 int pos = Name.LastIndexOf (".");
3106                                 string iface = Name.Substring (0, pos);
3107
3108                                 iface_type = RootContext.LookupType (parent, iface, false, Location);
3109                                 if (iface_type == null)
3110                                         return false;
3111
3112                                 short_name = Name.Substring (pos + 1);
3113
3114                                 // Compute the full name that we need to export.
3115                                 Name = iface_type.FullName + "." + short_name;
3116                         } else
3117                                 short_name = Name;
3118
3119                         // FIXME - PropertyAttributes.HasDefault ?
3120
3121                         PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
3122                                                        PropertyAttributes.SpecialName;
3123                 
3124                         PropertyBuilder = parent.TypeBuilder.DefineProperty (
3125                                 Name, prop_attr, PropertyType, null);
3126
3127                         if (Get != null)
3128                                 if (!DefineMethod (parent, iface_type, short_name, flags, true))
3129                                         return false;
3130                         
3131                         if (Set != null)
3132                                 if (!DefineMethod (parent, iface_type, short_name, flags, false))
3133                                         return false;
3134                         
3135                         //
3136                         // HACK for the reasons exposed above
3137                         //
3138                         if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3139                                 Report.Error (
3140                                         111, Location,
3141                                         "Class `" + parent.Name +
3142                                         "' already contains a definition for the property `" +
3143                                         Name + "'");
3144                                 return false;
3145                         }
3146
3147                         return true;
3148                 }
3149                 
3150                 public void Emit (TypeContainer tc)
3151                 {
3152                         ILGenerator ig;
3153                         EmitContext ec;
3154
3155                         ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
3156                         Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3157                         
3158
3159                         //
3160                         // abstract or extern properties have no bodies
3161                         //
3162                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3163                                 return;
3164
3165                         if (Get != null){
3166                                 ig = GetBuilder.GetILGenerator ();
3167                                 ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
3168                                 
3169                                 ec.EmitTopBlock (Get, Location);
3170                         }
3171
3172                         if (Set != null){
3173                                 ig = SetBuilder.GetILGenerator ();
3174                                 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3175                                 
3176                                 ec.EmitTopBlock (Set, Location);
3177                         }
3178                 }
3179         }
3180
3181
3182         /// </summary>
3183         ///  Gigantic workaround  for lameness in SRE follows :
3184         ///  This class derives from EventInfo and attempts to basically
3185         ///  wrap around the EventBuilder so that FindMembers can quickly
3186         ///  return this in it search for members
3187         /// </summary>
3188         public class MyEventBuilder : EventInfo {
3189                 
3190                 //
3191                 // We use this to "point" to our Builder which is
3192                 // not really a MemberInfo
3193                 //
3194                 EventBuilder MyBuilder;
3195                 
3196                 //
3197                 // We "catch" and wrap these methods
3198                 //
3199                 MethodInfo raise, remove, add;
3200
3201                 EventAttributes attributes;
3202                 Type declaring_type, reflected_type, event_type;
3203                 string name;
3204
3205                 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3206                 {
3207                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3208
3209                         // And now store the values in our own fields.
3210                         
3211                         declaring_type = type_builder;
3212
3213                         // FIXME : This is supposed to be MyBuilder but since that doesn't
3214                         // derive from Type, I have no clue what to do with this.
3215                         reflected_type = null;
3216                         
3217                         attributes = event_attr;
3218                         this.name = name;
3219                         this.event_type = event_type;
3220                 }
3221                 
3222                 //
3223                 // Methods that you have to override.  Note that you only need 
3224                 // to "implement" the variants that take the argument (those are
3225                 // the "abstract" methods, the others (GetAddMethod()) are 
3226                 // regular.
3227                 //
3228                 public override MethodInfo GetAddMethod (bool nonPublic)
3229                 {
3230                         return add;
3231                 }
3232                 
3233                 public override MethodInfo GetRemoveMethod (bool nonPublic)
3234                 {
3235                         return remove;
3236                 }
3237                 
3238                 public override MethodInfo GetRaiseMethod (bool nonPublic)
3239                 {
3240                         return raise;
3241                 }
3242                 
3243                 //
3244                 // These methods make "MyEventInfo" look like a Builder
3245                 //
3246                 public void SetRaiseMethod (MethodBuilder raiseMethod)
3247                 {
3248                         raise = raiseMethod;
3249                         MyBuilder.SetRaiseMethod (raiseMethod);
3250                 }
3251
3252                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3253                 {
3254                         remove = removeMethod;
3255                         MyBuilder.SetRemoveOnMethod (removeMethod);
3256                 }
3257
3258                 public void SetAddOnMethod (MethodBuilder addMethod)
3259                 {
3260                         add = addMethod;
3261                         MyBuilder.SetAddOnMethod (addMethod);
3262                 }
3263
3264                 public void SetCustomAttribute (CustomAttributeBuilder cb)
3265                 {
3266                         MyBuilder.SetCustomAttribute (cb);
3267                 }
3268                 
3269                 public override object [] GetCustomAttributes (bool inherit)
3270                 {
3271                         // FIXME : There's nothing which can be seemingly done here because
3272                         // we have no way of getting at the custom attribute objects of the
3273                         // EventBuilder !
3274                         return null;
3275                 }
3276
3277                 public override object [] GetCustomAttributes (Type t, bool inherit)
3278                 {
3279                         // FIXME : Same here !
3280                         return null;
3281                 }
3282
3283                 public override bool IsDefined (Type t, bool b)
3284                 {
3285                         return true;
3286                 }
3287
3288                 public override EventAttributes Attributes {
3289                         get {
3290                                 return attributes;
3291                         }
3292                 }
3293
3294                 public override string Name {
3295                         get {
3296                                 return name;
3297                         }
3298                 }
3299
3300                 public override Type DeclaringType {
3301                         get {
3302                                 return declaring_type;
3303                         }
3304                 }
3305
3306                 public override Type ReflectedType {
3307                         get {
3308                                 return reflected_type;
3309                         }
3310                 }
3311
3312                 public Type EventType {
3313                         get {
3314                                 return event_type;
3315                         }
3316                 }
3317         }
3318         
3319         public class Event : FieldBase {
3320                 const int AllowedModifiers =
3321                         Modifiers.NEW |
3322                         Modifiers.PUBLIC |
3323                         Modifiers.PROTECTED |
3324                         Modifiers.INTERNAL |
3325                         Modifiers.PRIVATE |
3326                         Modifiers.STATIC |
3327                         Modifiers.VIRTUAL |
3328                         Modifiers.SEALED |
3329                         Modifiers.OVERRIDE |
3330                         Modifiers.UNSAFE |
3331                         Modifiers.ABSTRACT;
3332
3333                 public readonly Block     Add;
3334                 public readonly Block     Remove;
3335                 public MyEventBuilder     EventBuilder;
3336
3337                 Type EventType;
3338                 MethodBuilder AddBuilder, RemoveBuilder;
3339                 
3340                 public Event (string type, string name, Object init, int mod, Block add_block,
3341                               Block rem_block, Attributes attrs, Location loc)
3342                         : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3343                 {
3344                         Add = add_block;
3345                         Remove = rem_block;
3346                 }
3347
3348                 public override bool Define (TypeContainer parent)
3349                 {
3350                         if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3351                                 return false;
3352
3353                         MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
3354                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3355
3356                         EventType = RootContext.LookupType (parent, Type, false, Location);
3357                         if (EventType == null)
3358                                 return false;
3359
3360                         if (!TypeContainer.AsAccessible (EventType, ModFlags))
3361                                 return false;
3362
3363                         if (EventType.IsPointer && !UnsafeOK (parent))
3364                                 return false;
3365
3366                         if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
3367                                 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3368                                               "' : event must be of a delegate type");
3369                                 return false;
3370                         }
3371                         
3372                         Type [] parameters = new Type [1];
3373                         parameters [0] = EventType;
3374
3375                         EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
3376
3377                         if (Add == null && Remove == null){
3378                                 FieldBuilder = parent.TypeBuilder.DefineField (
3379                                         Name, EventType, FieldAttributes.Private);
3380                                 TypeManager.RegisterFieldBase (FieldBuilder, this);
3381                         }
3382                         
3383                         //
3384                         // Now define the accessors
3385                         //
3386                         
3387                         AddBuilder = parent.TypeBuilder.DefineMethod (
3388                                                          "add_" + Name, m_attr, null, parameters);
3389                         AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3390                         EventBuilder.SetAddOnMethod (AddBuilder);
3391
3392                         //
3393                         // HACK because System.Reflection.Emit is lame
3394                         //
3395                         Parameter [] parms = new Parameter [1];
3396                         parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3397                         InternalParameters ip = new InternalParameters (
3398                                                             parent, new Parameters (parms, null, Location)); 
3399                         
3400                         if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
3401                                 Report.Error (111, Location,
3402                                               "Class `" + parent.Name + "' already contains a definition with the " +
3403                                               "same return value and parameter types for the " +
3404                                               "'add' method of event `" + Name + "'");
3405                                 return false;
3406                         }
3407                 
3408                         RemoveBuilder = parent.TypeBuilder.DefineMethod (
3409                                                             "remove_" + Name, m_attr, null, parameters);
3410                         RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3411                         EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3412
3413                         //
3414                         // HACK because System.Reflection.Emit is lame
3415                         //
3416
3417                         if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
3418                                 Report.Error (111, Location,    
3419                                               "Class `" + parent.Name + "' already contains a definition with the " +
3420                                               "same return value and parameter types for the " +
3421                                               "'remove' method of event `" + Name + "'");
3422                                 return false;
3423                         }
3424                         
3425                         if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3426                                 Report.Error (111, Location,
3427                                         "Class `" + parent.Name +
3428                                         "' already contains a definition for the event `" +
3429                                         Name + "'");
3430                                 return false;
3431                         }
3432                         
3433                         return true;
3434                 }
3435
3436                 void EmitDefaultMethod (EmitContext ec, bool is_add)
3437                 {
3438                         ILGenerator ig = ec.ig;
3439                         MethodInfo method = null;
3440                         
3441                         if (is_add)
3442                                 method = TypeManager.delegate_combine_delegate_delegate;
3443                         else
3444                                 method = TypeManager.delegate_remove_delegate_delegate;
3445                         
3446                         ig.Emit (OpCodes.Ldarg_0);
3447                         ig.Emit (OpCodes.Ldarg_0);
3448                         ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3449                         ig.Emit (OpCodes.Ldarg_1);
3450                         ig.Emit (OpCodes.Call, method);
3451                         ig.Emit (OpCodes.Castclass, EventType);
3452                         ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3453                         ig.Emit (OpCodes.Ret);
3454                 }
3455
3456                 public void Emit (TypeContainer tc)
3457                 {
3458                         EmitContext ec;
3459                         ILGenerator ig;
3460
3461                         ig = AddBuilder.GetILGenerator ();
3462                         ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3463
3464                         if (Add != null)
3465                                 ec.EmitTopBlock (Add, Location);
3466                         else
3467                                 EmitDefaultMethod (ec, true);
3468
3469                         ig = RemoveBuilder.GetILGenerator ();
3470                         ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3471                         
3472                         if (Remove != null)
3473                                 ec.EmitTopBlock (Remove, Location);
3474                         else
3475                                 EmitDefaultMethod (ec, false);
3476
3477                         ec = new EmitContext (tc, Location, null, EventType, ModFlags);
3478                         Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3479                         
3480                 }
3481                 
3482         }
3483
3484         //
3485         // FIXME: This does not handle:
3486         //
3487         //   int INTERFACENAME [ args ]
3488         //
3489         // Only:
3490         // 
3491         // int this [ args ]
3492  
3493         public class Indexer : MemberCore {
3494
3495                 const int AllowedModifiers =
3496                         Modifiers.NEW |
3497                         Modifiers.PUBLIC |
3498                         Modifiers.PROTECTED |
3499                         Modifiers.INTERNAL |
3500                         Modifiers.PRIVATE |
3501                         Modifiers.VIRTUAL |
3502                         Modifiers.SEALED |
3503                         Modifiers.OVERRIDE |
3504                         Modifiers.UNSAFE |
3505                         Modifiers.EXTERN |
3506                         Modifiers.ABSTRACT;
3507
3508                 public readonly string     Type;
3509                 public readonly string     InterfaceType;
3510                 public readonly Parameters FormalParameters;
3511                 public readonly Block      Get;
3512                 public readonly Block      Set;
3513                 public Attributes          OptAttributes;
3514                 public MethodBuilder       GetBuilder;
3515                 public MethodBuilder       SetBuilder;
3516                 public PropertyBuilder PropertyBuilder;
3517                 public Type IndexerType;
3518
3519                 public Indexer (string type, string int_type, int flags, Parameters parms,
3520                                 Block get_block, Block set_block, Attributes attrs, Location loc)
3521                         : base ("", loc)
3522                 {
3523
3524                         Type = type;
3525                         InterfaceType = int_type;
3526                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
3527                         FormalParameters = parms;
3528                         Get = get_block;
3529                         Set = set_block;
3530                         OptAttributes = attrs;
3531                 }
3532
3533                 void DefineMethod (TypeContainer parent, Type iface_type, 
3534                                    Type ret_type, string name,
3535                                    Type [] parameters, MethodAttributes attr, bool is_get)
3536                 {
3537                         MethodInfo implementing;
3538
3539                         implementing = parent.IsInterfaceMethod (
3540                                 iface_type, name, ret_type, parameters, false);
3541
3542                         //
3543                         // Setting null inside this block will trigger a more
3544                         // verbose error reporting for missing interface implementations
3545                         //
3546                         // The "candidate" function has been flagged already
3547                         // but it wont get cleared
3548                         //
3549                         if (implementing != null){
3550                                 if (iface_type == null){
3551                                         //
3552                                         // We already catch different accessibility settings
3553                                         // so we just need to check that we are not private
3554                                         //
3555                                         if ((ModFlags & Modifiers.PRIVATE) != 0)
3556                                                 implementing = null;
3557                                         
3558                                         //
3559                                         // Static is not allowed
3560                                         //
3561                                         if ((ModFlags & Modifiers.STATIC) != 0)
3562                                                 implementing = null;
3563                                 } else {
3564                                         if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
3565                                                 Report.Error (
3566                                                         106, Location,
3567                                                         "`public' or `abstract' modifiers are not "+
3568                                                         "allowed in explicit interface declarations"
3569                                                         );
3570                                                 implementing = null;
3571                                         }
3572                                 }
3573                         }
3574                         if (implementing != null){
3575                                 //
3576                                 // When implementing interface methods, set NewSlot.
3577                                 //
3578                                 if (implementing.DeclaringType.IsInterface)
3579                                         attr |= MethodAttributes.NewSlot;
3580                                 
3581                                 attr |=
3582                                         MethodAttributes.Virtual |
3583                                         MethodAttributes.HideBySig;
3584
3585                                 //
3586                                 // clear the pending flag
3587                                 //
3588                                 parent.IsInterfaceMethod (
3589                                         iface_type, name, ret_type, parameters, true);
3590                         }
3591
3592                         //
3593                         // If this is not an explicit interface implementation,
3594                         // clear implementing, as it is only used for explicit
3595                         // interface implementation
3596                         //
3597                         if (Name.IndexOf (".") == -1)
3598                                 implementing = null;
3599
3600                         if (is_get){
3601
3602                                 string meth_name = "get_Item";
3603                                 if (iface_type != null)
3604                                         meth_name = iface_type + ".get_Item";
3605                                 
3606                                 GetBuilder = parent.TypeBuilder.DefineMethod (
3607                                         meth_name, attr, IndexerType, parameters);
3608
3609                                 if (implementing != null) 
3610                                         parent.TypeBuilder.DefineMethodOverride (
3611                                                 GetBuilder, implementing);
3612                                 
3613                                 
3614                                 PropertyBuilder.SetGetMethod (GetBuilder);
3615                         } else {
3616
3617                                 string meth_name = "set_Item";
3618
3619                                 if (iface_type != null)
3620                                         meth_name = iface_type + ".set_Item";
3621                                 
3622                                 SetBuilder = parent.TypeBuilder.DefineMethod (
3623                                         meth_name, attr, null, parameters);
3624                                 if (implementing != null)
3625                                         parent.TypeBuilder.DefineMethodOverride (
3626                                                 SetBuilder, implementing);
3627                                         
3628                                 PropertyBuilder.SetSetMethod (SetBuilder);
3629                         }
3630                 }
3631                         
3632                 public override bool Define (TypeContainer parent)
3633                 {
3634                         PropertyAttributes prop_attr =
3635                                 PropertyAttributes.RTSpecialName |
3636                                 PropertyAttributes.SpecialName;
3637                         bool error = false;
3638                         
3639                         IndexerType = RootContext.LookupType (parent, Type, false, Location);
3640                         Type [] parameters = FormalParameters.GetParameterInfo (parent);
3641
3642                         // Check if the return type and arguments were correct
3643                         if (IndexerType == null || parameters == null)
3644                                 return false;
3645
3646                         if (!parent.MethodModifiersValid (ModFlags, InterfaceType == null ?
3647                                                           "this" : InterfaceType, Location))
3648                                 return false;
3649
3650                         //
3651                         // verify accessibility and unsafe pointers
3652                         //
3653                         if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
3654                                 return false;
3655
3656                         if (IndexerType.IsPointer && !UnsafeOK (parent))
3657                                 return false;
3658
3659                         foreach (Type partype in parameters){
3660                                 if (!TypeContainer.AsAccessible (partype, ModFlags))
3661                                         error = true;
3662                                 if (partype.IsPointer && !UnsafeOK (parent))
3663                                         error = true;
3664                         }
3665
3666                         if (error)
3667                                 return false;
3668                         
3669                         Type iface_type = null;
3670
3671                         if (InterfaceType != null){
3672                                 iface_type = RootContext.LookupType (parent, InterfaceType, false, Location);
3673                                 if (iface_type == null)
3674                                         return false;
3675                         } 
3676                                 
3677                         
3678                         PropertyBuilder = parent.TypeBuilder.DefineProperty (
3679                                 TypeManager.IndexerPropertyName (parent.TypeBuilder),
3680                                 prop_attr, IndexerType, parameters);
3681
3682                         MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
3683                         
3684                         if (Get != null){
3685                                 DefineMethod (parent, iface_type, IndexerType, "get_Item",
3686                                               parameters, attr, true);
3687                                 InternalParameters pi = new InternalParameters (parent, FormalParameters);
3688                                 if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
3689                                         Report.Error (111, Location,
3690                                                       "Class `" + parent.Name +
3691                                                       "' already contains a definition with the " +
3692                                                       "same return value and parameter types for the " +
3693                                                       "'get' indexer");
3694                                         return false;
3695                                 }
3696                         }
3697                         
3698                         if (Set != null){
3699                                 int top = parameters.Length;
3700                                 Type [] set_pars = new Type [top + 1];
3701                                 parameters.CopyTo (set_pars, 0);
3702                                 set_pars [top] = IndexerType;
3703
3704                                 Parameter [] fixed_parms = FormalParameters.FixedParameters;
3705
3706                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3707
3708                                 fixed_parms.CopyTo (tmp, 0);
3709                                 tmp [fixed_parms.Length] = new Parameter (
3710                                         Type, "value", Parameter.Modifier.NONE, null);
3711
3712                                 Parameters set_formal_params = new Parameters (tmp, null, Location);
3713                                 
3714                                 DefineMethod (
3715                                         parent, iface_type, TypeManager.void_type,
3716                                         "set_Item", set_pars, attr, false);
3717
3718                                 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3719                                 
3720                                 if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
3721                                         Report.Error (
3722                                                 111, Location,
3723                                                 "Class `" + parent.Name + "' already contains a " +
3724                                                 "definition with the " +
3725                                                 "same return value and parameter types for the " +
3726                                                 "'set' indexer");
3727                                         return false;
3728                                 }
3729                         }
3730
3731                         //
3732                         // Now name the parameters
3733                         //
3734                         Parameter [] p = FormalParameters.FixedParameters;
3735                         if (p != null) {
3736                                 int i;
3737                                 
3738                                 for (i = 0; i < p.Length; ++i) {
3739                                         if (Get != null)
3740                                                 GetBuilder.DefineParameter (
3741                                                         i + 1, p [i].Attributes, p [i].Name);
3742
3743                                         if (Set != null)
3744                                                 SetBuilder.DefineParameter (
3745                                                         i + 1, p [i].Attributes, p [i].Name);
3746                                 }
3747
3748                                 if (Set != null)
3749                                         SetBuilder.DefineParameter (
3750                                                 i + 1, ParameterAttributes.None, "value");
3751                                         
3752                                 if (i != parameters.Length) {
3753                                         Parameter array_param = FormalParameters.ArrayParameter;
3754                                         SetBuilder.DefineParameter (i + 1, array_param.Attributes,
3755                                                                     array_param.Name);
3756                                 }
3757                         }
3758
3759                         TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
3760
3761                         return true;
3762                 }
3763
3764                 public void Emit (TypeContainer tc)
3765                 {
3766                         ILGenerator ig;
3767                         EmitContext ec;
3768
3769                         ec = new EmitContext (tc, Location, null, IndexerType, ModFlags);
3770                         Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3771
3772                         if (Get != null){
3773                                 ig = GetBuilder.GetILGenerator ();
3774                                 ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
3775                                 
3776                                 ec.EmitTopBlock (Get, Location);
3777                         }
3778
3779                         if (Set != null){
3780                                 ig = SetBuilder.GetILGenerator ();
3781                                 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3782                                 
3783                                 ec.EmitTopBlock (Set, Location);
3784                         }
3785                 }
3786         }
3787
3788         public class Operator : MemberCore {
3789
3790                 const int AllowedModifiers =
3791                         Modifiers.PUBLIC |
3792                         Modifiers.UNSAFE |
3793                         Modifiers.EXTERN |
3794                         Modifiers.STATIC;
3795
3796                 const int RequiredModifiers =
3797                         Modifiers.PUBLIC |
3798                         Modifiers.STATIC;
3799
3800                 public enum OpType : byte {
3801
3802                         // Unary operators
3803                         LogicalNot,
3804                         OnesComplement,
3805                         Increment,
3806                         Decrement,
3807                         True,
3808                         False,
3809
3810                         // Unary and Binary operators
3811                         Addition,
3812                         Subtraction,
3813
3814                         UnaryPlus,
3815                         UnaryNegation,
3816                         
3817                         // Binary operators
3818                         Multiply,
3819                         Division,
3820                         Modulus,
3821                         BitwiseAnd,
3822                         BitwiseOr,
3823                         ExclusiveOr,
3824                         LeftShift,
3825                         RightShift,
3826                         Equality,
3827                         Inequality,
3828                         GreaterThan,
3829                         LessThan,
3830                         GreaterThanOrEqual,
3831                         LessThanOrEqual,
3832
3833                         // Implicit and Explicit
3834                         Implicit,
3835                         Explicit
3836                 };
3837
3838                 public readonly OpType OperatorType;
3839                 public readonly string ReturnType;
3840                 public readonly string FirstArgType;
3841                 public readonly string FirstArgName;
3842                 public readonly string SecondArgType;
3843                 public readonly string SecondArgName;
3844                 public readonly Block  Block;
3845                 public Attributes      OptAttributes;
3846                 public MethodBuilder   OperatorMethodBuilder;
3847                 
3848                 public string MethodName;
3849                 public Method OperatorMethod;
3850
3851                 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
3852                                  string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
3853                         : base ("", loc)
3854                 {
3855                         OperatorType = type;
3856                         ReturnType = ret_type;
3857                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
3858                         FirstArgType = arg1type;
3859                         FirstArgName = arg1name;
3860                         SecondArgType = arg2type;
3861                         SecondArgName = arg2name;
3862                         Block = block;
3863                         OptAttributes = attrs;
3864                 }
3865
3866                 string Prototype (TypeContainer parent)
3867                 {
3868                         return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3869                                 SecondArgType + ")";
3870                 }
3871                 
3872                 public override bool Define (TypeContainer parent)
3873                 {
3874                         int length = 1;
3875                         MethodName = "op_" + OperatorType;
3876                         
3877                         if (SecondArgType != null)
3878                                 length = 2;
3879                         
3880                         Parameter [] param_list = new Parameter [length];
3881
3882                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
3883                                 Report.Error (
3884                                         558, Location, 
3885                                         "User defined operators `" +
3886                                         Prototype (parent) +
3887                                         "' must be declared static and public");
3888                                 return false;
3889                         }
3890
3891                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
3892                                                        Parameter.Modifier.NONE, null);
3893                         if (SecondArgType != null)
3894                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
3895                                                                Parameter.Modifier.NONE, null);
3896                         
3897                         OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
3898                                                      new Parameters (param_list, null, Location),
3899                                                      OptAttributes, Mono.CSharp.Location.Null);
3900                         
3901                         OperatorMethod.Define (parent);
3902
3903                         if (OperatorMethod.MethodBuilder == null)
3904                                 return false;
3905                         
3906                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
3907
3908                         Type [] param_types = OperatorMethod.ParameterTypes (parent);
3909                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
3910                         Type return_type = OperatorMethod.GetReturnType (parent);
3911                         Type first_arg_type = param_types [0];
3912
3913                         // Rules for conversion operators
3914                         
3915                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
3916                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
3917                                         Report.Error (
3918                                                 555, Location,
3919                                                 "User-defined conversion cannot take an object of the " +
3920                                                 "enclosing type and convert to an object of the enclosing" +
3921                                                 " type");
3922                                         return false;
3923                                 }
3924                                 
3925                                 if (first_arg_type != declaring_type && return_type != declaring_type){
3926                                         Report.Error (
3927                                                 556, Location, 
3928                                                 "User-defined conversion must convert to or from the " +
3929                                                 "enclosing type");
3930                                         return false;
3931                                 }
3932                                 
3933                                 if (first_arg_type == TypeManager.object_type ||
3934                                     return_type == TypeManager.object_type){
3935                                         Report.Error (
3936                                                 -8, Location,
3937                                                 "User-defined conversion cannot convert to or from " +
3938                                                 "object type");
3939                                         return false;
3940                                 }
3941
3942                                 if (first_arg_type.IsInterface || return_type.IsInterface){
3943                                         Report.Error (
3944                                                 552, Location,
3945                                                 "User-defined conversion cannot convert to or from an " +
3946                                                 "interface type");
3947                                         return false;
3948                                 }
3949                                 
3950                                 if (first_arg_type.IsSubclassOf (return_type) ||
3951                                     return_type.IsSubclassOf (first_arg_type)){
3952                                         Report.Error (
3953                                                 -10, Location,
3954                                                 "User-defined conversion cannot convert between types " +
3955                                                 "that derive from each other");
3956                                         return false;
3957                                 }
3958                         } else if (SecondArgType == null) {
3959                                 // Checks for Unary operators
3960                                 
3961                                 if (first_arg_type != declaring_type){
3962                                         Report.Error (
3963                                                 562, Location,
3964                                                 "The parameter of a unary operator must be the " +
3965                                                 "containing type");
3966                                         return false;
3967                                 }
3968                                 
3969                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
3970                                         if (return_type != declaring_type){
3971                                                 Report.Error (
3972                                                         559, Location,
3973                                                         "The parameter and return type for ++ and -- " +
3974                                                         "must be the containing type");
3975                                                 return false;
3976                                         }
3977                                         
3978                                 }
3979                                 
3980                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
3981                                         if (return_type != TypeManager.bool_type){
3982                                                 Report.Error (
3983                                                         215, Location,
3984                                                         "The return type of operator True or False " +
3985                                                         "must be bool");
3986                                                 return false;
3987                                         }
3988                                 }
3989                                 
3990                         } else {
3991                                 // Checks for Binary operators
3992                                 
3993                                 if (first_arg_type != declaring_type &&
3994                                     param_types [1] != declaring_type){
3995                                         Report.Error (
3996                                                 563, Location,
3997                                                 "One of the parameters of a binary operator must " +
3998                                                 "be the containing type");
3999                                         return false;
4000                                 }
4001                         }
4002
4003                         return true;
4004                 }
4005                 
4006                 public void Emit (TypeContainer parent)
4007                 {
4008                         EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4009                         Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4010
4011                         //
4012                         // abstract or extern methods have no bodies
4013                         //
4014                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4015                                 return;
4016                         
4017                         OperatorMethod.Block = Block;
4018                         OperatorMethod.Emit (parent);
4019                 }
4020         }
4021
4022         //
4023         // This is used to compare method signatures
4024         //
4025         struct MethodSignature {
4026                 public string Name;
4027                 public Type RetType;
4028                 public Type [] Parameters;
4029                 
4030                 /// <summary>
4031                 ///    This delegate is used to extract methods which have the
4032                 ///    same signature as the argument
4033                 /// </summary>
4034                 public static MemberFilter method_signature_filter;
4035
4036                 /// <summary>
4037                 ///   This delegate is used to extract inheritable methods which
4038                 ///   have the same signature as the argument.  By inheritable,
4039                 ///   this means that we have permissions to override the method
4040                 ///   from the current assembly and class
4041                 /// </summary>
4042                 public static MemberFilter inheritable_method_signature_filter;
4043                 
4044                 static MethodSignature ()
4045                 {
4046                         method_signature_filter = new MemberFilter (MemberSignatureCompare);
4047                         inheritable_method_signature_filter = new MemberFilter (
4048                                 InheritableMemberSignatureCompare);
4049                 }
4050                 
4051                 public MethodSignature (string name, Type ret_type, Type [] parameters)
4052                 {
4053                         Name = name;
4054                         RetType = ret_type;
4055
4056                         if (parameters == null)
4057                                 Parameters = TypeManager.NoTypes;
4058                         else
4059                                 Parameters = parameters;
4060                 }
4061                 
4062                 public override int GetHashCode ()
4063                 {
4064                         return Name.GetHashCode ();
4065                 }
4066
4067                 public override bool Equals (Object o)
4068                 {
4069                         MethodSignature other = (MethodSignature) o;
4070
4071                         if (other.Name != Name)
4072                                 return false;
4073
4074                         if (other.RetType != RetType)
4075                                 return false;
4076                         
4077                         if (Parameters == null){
4078                                 if (other.Parameters == null)
4079                                         return true;
4080                                 return false;
4081                         }
4082
4083                         if (other.Parameters == null)
4084                                 return false;
4085                         
4086                         int c = Parameters.Length;
4087                         if (other.Parameters.Length != c)
4088                                 return false;
4089
4090                         for (int i = 0; i < c; i++)
4091                                 if (other.Parameters [i] != Parameters [i])
4092                                         return false;
4093
4094                         return true;
4095                 }
4096
4097                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4098                 {
4099                         MethodInfo mi;
4100
4101                         if (! (m is MethodInfo))
4102                                 return false;
4103
4104                         MethodSignature sig = (MethodSignature) filter_criteria;
4105
4106                         if (m.Name != sig.Name)
4107                                 return false;
4108                         
4109                         mi = (MethodInfo) m;
4110
4111                         if (mi.ReturnType != sig.RetType)
4112                                 return false;
4113
4114                         Type [] args = TypeManager.GetArgumentTypes (mi);
4115                         Type [] sigp = sig.Parameters;
4116
4117                         if (args.Length != sigp.Length)
4118                                 return false;
4119
4120                         for (int i = args.Length; i > 0; ){
4121                                 i--;
4122                                 if (args [i] != sigp [i])
4123                                         return false;
4124                         }
4125                         return true;
4126                 }
4127
4128                 //
4129                 // This filter should be used when we are requesting methods that
4130                 // we want to override.  
4131                 // 
4132                 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4133                 {
4134                         if (MemberSignatureCompare (m, filter_criteria)){
4135                                 MethodInfo mi = (MethodInfo) m;
4136                                 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4137
4138                                 // If only accessible to the current class.
4139                                 if (prot == MethodAttributes.Private)
4140                                         return false;
4141
4142                                 // If only accessible to the defining assembly or 
4143                                 if (prot == MethodAttributes.FamANDAssem ||
4144                                     prot == MethodAttributes.Assembly){
4145                                         if (m is MethodBuilder)
4146                                                 return true;
4147                                         else
4148                                                 return false;
4149                                 }
4150
4151                                 // Anything else (FamOrAssembly and Public) is fine
4152                                 return true;
4153                         }
4154                         return false;
4155                 }
4156         }               
4157 }