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