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