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