A few minor fixes
[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                         Implements = null;
2202                 }
2203
2204                 public Method (Expression return_type, int mod, string name, Parameters parameters,
2205                         Attributes attrs, Expression impl_what, Location l)
2206                         : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2207                 { 
2208                         Implements = impl_what;
2209                 }
2210
2211                 //
2212                 // Returns the `System.Type' for the ReturnType of this
2213                 // function.  Provides a nice cache.  (used between semantic analysis
2214                 // and actual code generation
2215                 //
2216                 public Type GetReturnType ()
2217                 {
2218                         return MemberType;
2219                 }
2220
2221                 // Whether this is an operator method.
2222                 public bool IsOperator;
2223
2224                 void DuplicateEntryPoint (MethodInfo b, Location location)
2225                 {
2226                         Report.Error (
2227                                 17, location,
2228                                 "Program `" + CodeGen.FileName +
2229                                 "'  has more than one entry point defined: `" +
2230                                 TypeManager.CSharpSignature(b) + "'");
2231                 }
2232
2233                 void Report28 (MethodInfo b)
2234                 {
2235                         if (RootContext.WarningLevel < 4) 
2236                                 return;
2237                                 
2238                         Report.Warning (
2239                                 28, Location,
2240                                 "`" + TypeManager.CSharpSignature(b) +
2241                                 "' has the wrong signature to be an entry point");
2242                 }
2243
2244                 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2245                 {
2246                         if (b.ReturnType != TypeManager.void_type &&
2247                             b.ReturnType != TypeManager.int32_type)
2248                                 return false;
2249
2250                         if (pinfo.Count == 0)
2251                                 return true;
2252
2253                         if (pinfo.Count > 1)
2254                                 return false;
2255
2256                         Type t = pinfo.ParameterType(0);
2257                         if (t.IsArray &&
2258                             (t.GetArrayRank() == 1) &&
2259                             (t.GetElementType() == TypeManager.string_type) &&
2260                             (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2261                                 return true;
2262                         else
2263                                 return false;
2264                 }
2265
2266                 //
2267                 // Checks our base implementation if any
2268                 //
2269                 protected override bool CheckBase (TypeContainer parent)
2270                 {
2271                         // Check whether arguments were correct.
2272                         if (!DoDefineParameters (parent))
2273                                 return false;
2274
2275                         MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2276                         if (!IsOperator) {
2277                                 MemberList mi_this;
2278
2279                                 mi_this = TypeContainer.FindMembers (
2280                                         parent.TypeBuilder, MemberTypes.Method,
2281                                         BindingFlags.NonPublic | BindingFlags.Public |
2282                                         BindingFlags.Static | BindingFlags.Instance |
2283                                         BindingFlags.DeclaredOnly,
2284                                         MethodSignature.method_signature_filter, ms);
2285
2286                                 if (mi_this.Count > 0) {
2287                                         Report.Error (111, Location, "Class `" + parent.Name + "' " +
2288                                                       "already defines a member called `" + Name + "' " +
2289                                                       "with the same parameter types");
2290                                         return false;
2291                                 }
2292                         }
2293
2294                         //
2295                         // Verify if the parent has a type with the same name, and then
2296                         // check whether we have to create a new slot for it or not.
2297                         //
2298                         Type ptype = parent.TypeBuilder.BaseType;
2299
2300                         // ptype is only null for System.Object while compiling corlib.
2301                         if (ptype != null){
2302                                 MemberList mi, mi_static, mi_instance;
2303
2304                                 mi_static = TypeContainer.FindMembers (
2305                                         ptype, MemberTypes.Method,
2306                                         BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2307                                         MethodSignature.inheritable_method_signature_filter, ms);
2308
2309                                 mi_instance = TypeContainer.FindMembers (
2310                                         ptype, MemberTypes.Method,
2311                                         BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2312                                         MethodSignature.inheritable_method_signature_filter,
2313                                         ms);
2314
2315                                 if (mi_instance.Count > 0){
2316                                         mi = mi_instance;
2317                                 } else if (mi_static.Count > 0)
2318                                         mi = mi_static;
2319                                 else
2320                                         mi = null;
2321
2322                                 if (mi != null && mi.Count > 0){
2323                                         parent_method = (MethodInfo) mi [0];
2324                                         string name = parent_method.DeclaringType.Name + "." +
2325                                                 parent_method.Name;
2326
2327                                         if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2328                                                 return false;
2329
2330                                         if ((ModFlags & Modifiers.NEW) == 0) {
2331                                                 Type parent_ret = TypeManager.TypeToCoreType (
2332                                                         parent_method.ReturnType);
2333
2334                                                 if (parent_ret != MemberType) {
2335                                                         Report.Error (
2336                                                                 508, parent.MakeName (Name) + ": cannot " +
2337                                                                 "change return type when overriding " +
2338                                                                 "inherited member " + name);
2339                                                         return false;
2340                                                 }
2341                                         }
2342                                 } else {
2343                                         if ((ModFlags & Modifiers.NEW) != 0)
2344                                                 WarningNotHiding (parent);
2345
2346                                         if ((ModFlags & Modifiers.OVERRIDE) != 0){
2347                                                 Report.Error (115, Location,
2348                                                               parent.MakeName (Name) +
2349                                                               " no suitable methods found to override");
2350                                         }
2351                                 }
2352                         } else if ((ModFlags & Modifiers.NEW) != 0)
2353                                 WarningNotHiding (parent);
2354
2355                         return true;
2356                 }
2357
2358                 //
2359                 // Creates the type
2360                 //
2361                 public override bool Define (TypeContainer parent)
2362                 {
2363                         if (!DoDefine (parent))
2364                                 return false;
2365
2366                         if (!CheckBase (parent))
2367                                 return false;
2368
2369                         CallingConventions cc = GetCallingConvention (parent is Class);
2370
2371                         MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2372                                                      ParameterInfo, cc, OptAttributes,
2373                                                      ModFlags, flags, true);
2374
2375                         if (!MethodData.Define (parent))
2376                                 return false;
2377
2378                         MethodBuilder = MethodData.MethodBuilder;
2379                         
2380                         //
2381                         // This is used to track the Entry Point,
2382                         //
2383                         if (Name == "Main" &&
2384                             ((ModFlags & Modifiers.STATIC) != 0) && 
2385                             (RootContext.MainClass == null ||
2386                              RootContext.MainClass == parent.TypeBuilder.FullName)){
2387                                 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2388                                         if (RootContext.EntryPoint == null) {
2389                                                 RootContext.EntryPoint = MethodBuilder;
2390                                                 RootContext.EntryPointLocation = Location;
2391                                         } else {
2392                                                 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2393                                                 DuplicateEntryPoint (MethodBuilder, Location);
2394                                         }
2395                                 } else                                  
2396                                         Report28(MethodBuilder);
2397                         }
2398
2399                         return true;
2400                 }
2401
2402                 //
2403                 // Emits the code
2404                 // 
2405                 public void Emit (TypeContainer parent)
2406                 {
2407                         MethodData.Emit (parent, Block, this);
2408                 }
2409         }
2410
2411         public abstract class ConstructorInitializer {
2412                 ArrayList argument_list;
2413                 ConstructorInfo parent_constructor;
2414                 Parameters parameters;
2415                 Location loc;
2416                 
2417                 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2418                                                Location loc)
2419                 {
2420                         this.argument_list = argument_list;
2421                         this.parameters = parameters;
2422                         this.loc = loc;
2423                 }
2424
2425                 public ArrayList Arguments {
2426                         get {
2427                                 return argument_list;
2428                         }
2429                 }
2430
2431                 public bool Resolve (EmitContext ec)
2432                 {
2433                         Expression parent_constructor_group;
2434                         Type t;
2435
2436                         ec.CurrentBlock = new Block (null, true, parameters);
2437
2438                         if (argument_list != null){
2439                                 foreach (Argument a in argument_list){
2440                                         if (!a.Resolve (ec, loc))
2441                                                 return false;
2442                                 }
2443                         }
2444
2445                         ec.CurrentBlock = null;
2446
2447                         if (this is ConstructorBaseInitializer) {
2448                                 if (ec.ContainerType.BaseType == null)
2449                                         return true;
2450
2451                                 t = ec.ContainerType.BaseType;
2452                                 if (ec.ContainerType.IsValueType) {
2453                                         Report.Error (522, loc,
2454                                                 "structs cannot call base class constructors");
2455                                         return false;
2456                                 }
2457                         } else
2458                                 t = ec.ContainerType;
2459
2460                         parent_constructor_group = Expression.MemberLookup (
2461                                 ec, t, t, ".ctor", 
2462                                 MemberTypes.Constructor,
2463                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2464                                 loc);
2465                         
2466                         if (parent_constructor_group == null){
2467                                 Report.Error (1501, loc,
2468                                        "Can not find a constructor for this argument list");
2469                                 return false;
2470                         }
2471                         
2472                         parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
2473                                 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2474                         
2475                         if (parent_constructor == null){
2476                                 Report.Error (1501, loc,
2477                                        "Can not find a constructor for this argument list");
2478                                 return false;
2479                         }
2480                         
2481                         return true;
2482                 }
2483
2484                 public void Emit (EmitContext ec)
2485                 {
2486                         if (parent_constructor != null){
2487                                 if (ec.IsStatic)
2488                                         Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2489                                 else
2490                                         Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2491                         }
2492                 }
2493         }
2494
2495         public class ConstructorBaseInitializer : ConstructorInitializer {
2496                 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2497                         base (argument_list, pars, l)
2498                 {
2499                 }
2500         }
2501
2502         public class ConstructorThisInitializer : ConstructorInitializer {
2503                 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2504                         base (argument_list, pars, l)
2505                 {
2506                 }
2507         }
2508         
2509         public class Constructor : MethodCore {
2510                 public ConstructorBuilder ConstructorBuilder;
2511                 public ConstructorInitializer Initializer;
2512                 new public Attributes OptAttributes;
2513
2514                 // <summary>
2515                 //   Modifiers allowed for a constructor.
2516                 // </summary>
2517                 public const int AllowedModifiers =
2518                         Modifiers.PUBLIC |
2519                         Modifiers.PROTECTED |
2520                         Modifiers.INTERNAL |
2521                         Modifiers.STATIC |
2522                         Modifiers.UNSAFE |
2523                         Modifiers.EXTERN |              
2524                         Modifiers.PRIVATE;
2525
2526                 //
2527                 // The spec claims that static is not permitted, but
2528                 // my very own code has static constructors.
2529                 //
2530                 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2531                         : base (null, 0, AllowedModifiers, name, null, args, l)
2532                 {
2533                         Initializer = init;
2534                 }
2535
2536                 //
2537                 // Returns true if this is a default constructor
2538                 //
2539                 public bool IsDefault ()
2540                 {
2541                         if ((ModFlags & Modifiers.STATIC) != 0)
2542                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2543                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2544                         
2545                         else
2546                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2547                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2548                                         (Initializer is ConstructorBaseInitializer) &&
2549                                         (Initializer.Arguments == null);
2550                 }
2551
2552                 //
2553                 // Creates the ConstructorBuilder
2554                 //
2555                 public override bool Define (TypeContainer parent)
2556                 {
2557                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
2558                                                MethodAttributes.SpecialName);
2559
2560                         // Check if arguments were correct.
2561                         if (!DoDefineParameters (parent))
2562                                 return false;
2563
2564                         if ((ModFlags & Modifiers.STATIC) != 0)
2565                                 ca |= MethodAttributes.Static;
2566                         else {
2567                                 if (parent is Struct && ParameterTypes.Length == 0){
2568                                         Report.Error (
2569                                                 568, Location, 
2570                                                 "Structs can not contain explicit parameterless " +
2571                                                 "constructors");
2572                                         return false;
2573                                 }
2574                                 ca |= MethodAttributes.HideBySig;
2575
2576                                 if ((ModFlags & Modifiers.PUBLIC) != 0)
2577                                         ca |= MethodAttributes.Public;
2578                                 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2579                                         if ((ModFlags & Modifiers.INTERNAL) != 0)
2580                                                 ca |= MethodAttributes.FamORAssem;
2581                                         else 
2582                                                 ca |= MethodAttributes.Family;
2583                                 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2584                                         ca |= MethodAttributes.Assembly;
2585                                 else if (IsDefault ())
2586                                         ca |= MethodAttributes.Public;
2587                                 else
2588                                         ca |= MethodAttributes.Private;
2589                         }
2590
2591                         ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2592                                 ca, GetCallingConvention (parent is Class), ParameterTypes);
2593
2594                         //
2595                         // HACK because System.Reflection.Emit is lame
2596                         //
2597                         if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2598                                 Report.Error (
2599                                         111, Location,
2600                                         "Class `" +parent.Name+ "' already contains a definition with the " +
2601                                         "same return value and parameter types for constructor `" + Name
2602                                         + "'");
2603                                 return false;
2604                         }
2605
2606                         return true;
2607                 }
2608
2609                 //
2610                 // Emits the code
2611                 //
2612                 public void Emit (TypeContainer parent)
2613                 {
2614                         ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2615                         EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2616
2617                         if ((ModFlags & Modifiers.STATIC) == 0){
2618                                 if (parent is Class && Initializer == null)
2619                                         Initializer = new ConstructorBaseInitializer (
2620                                                 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2621
2622
2623                                 //
2624                                 // Spec mandates that Initializers will not have
2625                                 // `this' access
2626                                 //
2627                                 ec.IsStatic = true;
2628                                 if (Initializer != null && !Initializer.Resolve (ec))
2629                                         return;
2630                                 ec.IsStatic = false;
2631                         }
2632
2633                         LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2634                         
2635                         //
2636                         // Classes can have base initializers and instance field initializers.
2637                         //
2638                         if (parent is Class){
2639                                 if ((ModFlags & Modifiers.STATIC) == 0)
2640                                         parent.EmitFieldInitializers (ec);
2641                         }
2642                         if (Initializer != null)
2643                                 Initializer.Emit (ec);
2644                         
2645                         if ((ModFlags & Modifiers.STATIC) != 0)
2646                                 parent.EmitFieldInitializers (ec);
2647
2648                         Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2649
2650                         // If this is a non-static `struct' constructor and doesn't have any
2651                         // initializer, it must initialize all of the struct's fields.
2652                         if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2653                             (Initializer == null))
2654                                 Block.AddThisVariable (parent, Location);
2655
2656                         ec.EmitTopBlock (Block, ParameterInfo, Location);
2657                 }
2658         }
2659
2660         public class MethodData {
2661                 //
2662                 // The return type of this method
2663                 //
2664                 public readonly Type ReturnType;
2665                 public readonly Type[] ParameterTypes;
2666                 public readonly InternalParameters ParameterInfo;
2667                 public readonly CallingConventions CallingConventions;
2668                 public readonly Attributes OptAttributes;
2669                 public readonly Location Location;
2670
2671                 //
2672                 // Are we implementing an interface ?
2673                 //
2674                 public bool IsImplementing = false;
2675
2676                 //
2677                 // Protected data.
2678                 //
2679                 protected MemberBase member;
2680                 protected int modifiers;
2681                 protected MethodAttributes flags;
2682                 protected bool is_method;
2683                 protected string accessor_name;
2684                 ArrayList conditionals;
2685
2686                 MethodBuilder builder = null;
2687                 public MethodBuilder MethodBuilder {
2688                         get {
2689                                 return builder;
2690                         }
2691                 }
2692
2693                 public MethodData (MemberBase member, string name, Type return_type,
2694                                    Type [] parameter_types, InternalParameters parameters,
2695                                    CallingConventions cc, Attributes opt_attrs,
2696                                    int modifiers, MethodAttributes flags, bool is_method)
2697                 {
2698                         this.member = member;
2699                         this.accessor_name = name;
2700                         this.ReturnType = return_type;
2701                         this.ParameterTypes = parameter_types;
2702                         this.ParameterInfo = parameters;
2703                         this.CallingConventions = cc;
2704                         this.OptAttributes = opt_attrs;
2705                         this.modifiers = modifiers;
2706                         this.flags = flags;
2707                         this.is_method = is_method;
2708                         this.Location = member.Location;
2709                         this.conditionals = new ArrayList ();
2710                 }
2711
2712                 //
2713                 // Attributes.
2714                 //
2715                 Attribute dllimport_attribute = null;
2716                 string obsolete = null;
2717                 bool obsolete_error = false;
2718
2719                 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2720                 {
2721                         if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2722                                 return true;
2723
2724                         foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2725                                 if (asec.Attributes == null)
2726                                         continue;
2727                                         
2728                                 foreach (Attribute a in asec.Attributes) {
2729                                         if (a.Name == "Conditional") {
2730                                                 if (!ApplyConditionalAttribute (a))
2731                                                         return false;
2732                                         } else if (a.Name == "Obsolete") {
2733                                                 if (!ApplyObsoleteAttribute (a))
2734                                                         return false;
2735                                         } else if (a.Name.IndexOf ("DllImport") != -1) {
2736                                                 if (!is_method) {
2737                                                         a.Type = TypeManager.dllimport_type;
2738                                                         Attribute.Error_AttributeNotValidForElement (a, Location);
2739                                                         return false;
2740                                                 }
2741                                                 if (!ApplyDllImportAttribute (a))
2742                                                         return false;
2743                                         }
2744                                 }
2745                         }
2746
2747                         return true;
2748                 }
2749
2750                 //
2751                 // Applies the `DllImport' attribute to the method.
2752                 //
2753                 protected virtual bool ApplyDllImportAttribute (Attribute a)
2754                 {
2755                         const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2756                         if ((modifiers & extern_static) != extern_static) {
2757                                 Report.Error (601, Location,
2758                                               "The DllImport attribute must be specified on a method " +
2759                                               "marked `static' and `extern'.");
2760                                 return false;
2761                         }
2762
2763                         flags |= MethodAttributes.PinvokeImpl;
2764                         dllimport_attribute = a;
2765                         return true;
2766                 }
2767
2768                 //
2769                 // Applies the `Obsolete' attribute to the method.
2770                 //
2771                 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2772                 {
2773                         if (obsolete != null) {
2774                                 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2775                                 return false;
2776                         }
2777
2778                         obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2779                         return obsolete != null;
2780                 }
2781
2782                 //
2783                 // Applies the `Conditional' attribute to the method.
2784                 //
2785                 protected virtual bool ApplyConditionalAttribute (Attribute a)
2786                 {
2787                         // The Conditional attribute is only valid on methods.
2788                         if (!is_method) {
2789                                 Attribute.Error_AttributeNotValidForElement (a, Location);
2790                                 return false;
2791                         }
2792
2793                         string condition = a.Conditional_GetConditionName ();
2794
2795                         if (condition == null)
2796                                 return false;
2797
2798                         if (ReturnType != TypeManager.void_type) {
2799                                 Report.Error (578, Location,
2800                                               "Conditional not valid on `" + member.Name + "' " +
2801                                               "because its return type is not void");
2802                                 return false;
2803                         }
2804
2805                         if ((modifiers & Modifiers.OVERRIDE) != 0) {
2806                                 Report.Error (243, Location,
2807                                               "Conditional not valid on `" + member.Name + "' " +
2808                                               "because it is an override method");
2809                                 return false;
2810                         }
2811
2812                         if (member.IsExplicitImpl) {
2813                                 Report.Error (577, Location,
2814                                               "Conditional not valid on `" + member.Name + "' " +
2815                                               "because it is an explicit interface implementation");
2816                                 return false;
2817                         }
2818
2819                         if (IsImplementing) {
2820                                 Report.Error (623, Location,
2821                                               "Conditional not valid on `" + member.Name + "' " +
2822                                               "because it is an interface method");
2823                                 return false;
2824                         }
2825
2826                         conditionals.Add (condition);
2827
2828                         return true;
2829                 }
2830
2831                 //
2832                 // Checks whether this method should be ignored due to its Conditional attributes.
2833                 //
2834                 bool ShouldIgnore (Location loc)
2835                 {
2836                         // When we're overriding a virtual method, we implicitly inherit the
2837                         // Conditional attributes from our parent.
2838                         if (member.ParentMethod != null) {
2839                                 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2840                                         member.ParentMethod, loc);
2841
2842                                 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2843                                         return true;
2844                         }
2845
2846                         foreach (string condition in conditionals)
2847                                 if (RootContext.AllDefines [condition] == null)
2848                                         return true;
2849
2850                         return false;
2851                 }
2852
2853                 //
2854                 // Returns the TypeManager.MethodFlags for this method.
2855                 // This emits an error 619 / warning 618 if the method is obsolete.
2856                 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2857                 //
2858                 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2859                 {
2860                         TypeManager.MethodFlags flags = 0;
2861
2862                         if (obsolete != null) {
2863                                 if (obsolete_error) {
2864                                         Report.Error (619, loc, "Method `" + member.Name +
2865                                                       "' is obsolete: `" + obsolete + "'");
2866                                         return TypeManager.MethodFlags.IsObsoleteError;
2867                                 } else
2868                                         Report.Warning (618, loc, "Method `" + member.Name +
2869                                                         "' is obsolete: `" + obsolete + "'");
2870
2871                                 flags |= TypeManager.MethodFlags.IsObsolete;
2872                         }
2873
2874                         if (ShouldIgnore (loc))
2875                             flags |= TypeManager.MethodFlags.ShouldIgnore;
2876
2877                         return flags;
2878                 }
2879
2880                 public virtual bool Define (TypeContainer parent)
2881                 {
2882                         MethodInfo implementing = null;
2883                         string method_name, name, prefix;
2884
2885                         if (OptAttributes != null)
2886                                 if (!ApplyAttributes (OptAttributes, is_method))
2887                                         return false;
2888
2889                         if (member.IsExplicitImpl)
2890                                 prefix = member.InterfaceType.FullName + ".";
2891                         else
2892                                 prefix = "";
2893
2894                         if (accessor_name != null)
2895                                 name = accessor_name + "_" + member.ShortName;
2896                         else
2897                                 name = member.ShortName;
2898                         method_name = prefix + name;
2899
2900                         if (parent.Pending != null){
2901                                 if (member is Indexer)
2902                                         implementing = parent.Pending.IsInterfaceIndexer (
2903                                                 member.InterfaceType, ReturnType, ParameterTypes);
2904                                 else
2905                                         implementing = parent.Pending.IsInterfaceMethod (
2906                                                 member.InterfaceType, name, ReturnType, ParameterTypes);
2907
2908                                 if (member.InterfaceType != null && implementing == null){
2909                                         TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2910                                                 Location, name);
2911                                         return false;
2912                                 }
2913                         }
2914
2915                         //
2916                         // For implicit implementations, make sure we are public, for
2917                         // explicit implementations, make sure we are private.
2918                         //
2919                         if (implementing != null){
2920                                 //
2921                                 // Setting null inside this block will trigger a more
2922                                 // verbose error reporting for missing interface implementations
2923                                 //
2924                                 // The "candidate" function has been flagged already
2925                                 // but it wont get cleared
2926                                 //
2927                                 if (!member.IsExplicitImpl){
2928                                         //
2929                                         // We already catch different accessibility settings
2930                                         // so we just need to check that we are not private
2931                                         //
2932                                         if ((modifiers & Modifiers.PRIVATE) != 0)
2933                                                 implementing = null;
2934                                         
2935                                         //
2936                                         // Static is not allowed
2937                                         //
2938                                         if ((modifiers & Modifiers.STATIC) != 0)
2939                                                 implementing = null;
2940                                 } else {
2941                                         if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2942                                                 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2943                                                 implementing = null;
2944                                         }
2945                                 }
2946                         }
2947                         
2948                         //
2949                         // If implementing is still valid, set flags
2950                         //
2951                         if (implementing != null){
2952                                 //
2953                                 // When implementing interface methods, set NewSlot.
2954                                 //
2955                                 if (implementing.DeclaringType.IsInterface)
2956                                         flags |= MethodAttributes.NewSlot;
2957
2958                                 flags |=
2959                                         MethodAttributes.Virtual |
2960                                         MethodAttributes.HideBySig;
2961
2962                                 // Get the method name from the explicit interface.
2963                                 if (member.InterfaceType != null) {
2964                                         name = implementing.Name;
2965                                         method_name = prefix + name;
2966                                 }
2967
2968                                 IsImplementing = true;
2969                         }
2970
2971                         //
2972                         // Create the MethodBuilder for the method
2973                         //
2974                         if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2975                                 if ((modifiers & Modifiers.STATIC) == 0) {
2976                                         Report.Error (601, Location,
2977                                                       "The DllImport attribute must be specified on " +
2978                                                       "a method marked 'static' and 'extern'.");
2979                                         return false;
2980                                 }
2981                                 
2982                                 EmitContext ec = new EmitContext (
2983                                         parent, Location, null, ReturnType, modifiers);
2984                                 
2985                                 builder = dllimport_attribute.DefinePInvokeMethod (
2986                                         ec, parent.TypeBuilder, method_name, flags,
2987                                         ReturnType, ParameterTypes);
2988                         } else
2989                                 builder = parent.TypeBuilder.DefineMethod (
2990                                         method_name, flags, CallingConventions,
2991                                         ReturnType, ParameterTypes);
2992
2993                         if (builder == null)
2994                                 return false;
2995
2996                         if (IsImplementing) {
2997                                 //
2998                                 // clear the pending implemntation flag
2999                                 //
3000                                 if (member is Indexer) {
3001                                         parent.Pending.ImplementIndexer (
3002                                                 member.InterfaceType, builder, ReturnType,
3003                                                 ParameterTypes, true);
3004                                 } else
3005                                         parent.Pending.ImplementMethod (
3006                                                 member.InterfaceType, name, ReturnType,
3007                                                 ParameterTypes, member.IsExplicitImpl);
3008
3009                                 if (member.IsExplicitImpl)
3010                                         parent.TypeBuilder.DefineMethodOverride (
3011                                                 builder, implementing);
3012                         }
3013
3014                         if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3015                                 Report.Error (111, Location,
3016                                               "Class `" + parent.Name +
3017                                               "' already contains a definition with the " +
3018                                               "same return value and parameter types as the " +
3019                                               "'get' method of property `" + member.Name + "'");
3020                                 return false;
3021                         }
3022
3023                         TypeManager.AddMethod (builder, this);
3024
3025                         return true;
3026                 }
3027
3028                 //
3029                 // Emits the code
3030                 // 
3031                 public virtual void Emit (TypeContainer parent, Block block, object kind)
3032                 {
3033                         ILGenerator ig;
3034                         EmitContext ec;
3035
3036                         if ((flags & MethodAttributes.PinvokeImpl) == 0)
3037                                 ig = builder.GetILGenerator ();
3038                         else
3039                                 ig = null;
3040
3041                         ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3042
3043                         if (OptAttributes != null)
3044                                 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3045
3046                         if (member is MethodCore)
3047                                 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
3048
3049                         //
3050                         // abstract or extern methods have no bodies
3051                         //
3052                         if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3053                                 if (block == null)
3054                                         return;
3055
3056                                 //
3057                                 // abstract or extern methods have no bodies.
3058                                 //
3059                                 if ((modifiers & Modifiers.ABSTRACT) != 0)
3060                                         Report.Error (
3061                                                 500, Location, "Abstract method `" +
3062                                                 TypeManager.CSharpSignature (builder) +
3063                                                 "' can not have a body");
3064
3065                                 if ((modifiers & Modifiers.EXTERN) != 0)
3066                                         Report.Error (
3067                                                 179, Location, "External method `" +
3068                                                 TypeManager.CSharpSignature (builder) +
3069                                                 "' can not have a body");
3070
3071                                 return;
3072                         }
3073
3074                         //
3075                         // Methods must have a body unless they're extern or abstract
3076                         //
3077                         if (block == null) {
3078                                 Report.Error (
3079                                         501, Location, "Method `" +
3080                                         TypeManager.CSharpSignature (builder) +
3081                                         "' must declare a body since it is not marked " +
3082                                         "abstract or extern");
3083                                 return;
3084                         }
3085
3086                         //
3087                         // Handle destructors specially
3088                         //
3089                         // FIXME: This code generates buggy code
3090                         //
3091                         if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3092                                 EmitDestructor (ec, block);
3093                         else {
3094                                 ISymbolWriter sw = CodeGen.SymbolWriter;
3095
3096                                 if ((sw != null) && !Location.IsNull (Location) &&
3097                                     !Location.IsNull (block.EndLocation)) {
3098                                         Location end = block.EndLocation;
3099                                         MethodToken token = MethodBuilder.GetToken ();
3100                                         sw.OpenMethod (new SymbolToken (token.Token));
3101                                         // Avoid error if we don't support debugging for the platform
3102                                         try {
3103                                                 sw.SetMethodSourceRange (Location.SymbolDocument,
3104                                                                          Location.Row, 0,
3105                                                                          end.SymbolDocument,
3106                                                                          end.Row, 0);
3107                                         } catch (Exception) {
3108                                         }
3109
3110                                         ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3111
3112                                         sw.CloseMethod ();
3113                                 } else
3114                                         ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3115                         }
3116                 }
3117
3118                 void EmitDestructor (EmitContext ec, Block block)
3119                 {
3120                         ILGenerator ig = ec.ig;
3121                         
3122                         Label finish = ig.DefineLabel ();
3123                         bool old_in_try = ec.InTry;
3124                         
3125                         ig.BeginExceptionBlock ();
3126                         ec.InTry = true;
3127                         ec.ReturnLabel = finish;
3128                         ec.HasReturnLabel = true;
3129                         ec.EmitTopBlock (block, null, Location);
3130                         ec.InTry = old_in_try;
3131                         
3132                         // ig.MarkLabel (finish);
3133                         bool old_in_finally = ec.InFinally;
3134                         ec.InFinally = true;
3135                         ig.BeginFinallyBlock ();
3136                         
3137                         if (ec.ContainerType.BaseType != null) {
3138                                 Expression member_lookup = Expression.MemberLookup (
3139                                         ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3140                                         MemberTypes.Method, Expression.AllBindingFlags, Location);
3141
3142                                 if (member_lookup != null){
3143                                         MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3144                                 
3145                                         ig.Emit (OpCodes.Ldarg_0);
3146                                         ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3147                                 }
3148                         }
3149                         ec.InFinally = old_in_finally;
3150                         
3151                         ig.EndExceptionBlock ();
3152                         //ig.MarkLabel (ec.ReturnLabel);
3153                         ig.Emit (OpCodes.Ret);
3154                 }
3155         }
3156
3157         abstract public class MemberBase : MemberCore {
3158                 public Expression Type;
3159                 public readonly Attributes OptAttributes;
3160                 public Expression Implements;
3161
3162                 protected MethodAttributes flags;
3163
3164                 //
3165                 // The "short" name of this property / indexer / event.  This is the
3166                 // name without the explicit interface.
3167                 //
3168                 public string ShortName;
3169
3170                 //
3171                 // The type of this property / indexer / event
3172                 //
3173                 public Type MemberType;
3174
3175                 //
3176                 // If true, this is an explicit interface implementation
3177                 //
3178                 public bool IsExplicitImpl = false;
3179
3180                 //
3181                 // The name of the interface we are explicitly implementing
3182                 //
3183                 public string ExplicitInterfaceName = null;
3184
3185                 //
3186                 // If true, the interface type we are explicitly implementing
3187                 //
3188                 public Type InterfaceType = null;
3189
3190                 //
3191                 // The method we're overriding if this is an override method.
3192                 //
3193                 protected MethodInfo parent_method = null;
3194                 public MethodInfo ParentMethod {
3195                         get {
3196                                 return parent_method;
3197                         }
3198                 }
3199
3200                 //
3201                 // The constructor is only exposed to our children
3202                 //
3203                 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3204                                       Attributes attrs, Location loc)
3205                         : base (name, loc)
3206                 {
3207                         Type = type;
3208                         ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
3209                         OptAttributes = attrs;
3210                 }
3211
3212                 protected virtual bool CheckBase (TypeContainer parent)
3213                 {
3214                         return true;
3215                 }
3216
3217                 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3218                 {
3219                         bool error = false;
3220
3221                         foreach (Type partype in parameters){
3222                                 if (partype.IsPointer && !UnsafeOK (parent))
3223                                         error = true;
3224
3225                                 if (parent.AsAccessible (partype, ModFlags))
3226                                         continue;
3227
3228                                 if (this is Indexer)
3229                                         Report.Error (55, Location,
3230                                                       "Inconsistent accessibility: parameter type `" +
3231                                                       TypeManager.CSharpName (partype) + "' is less " +
3232                                                       "accessible than indexer `" + Name + "'");
3233                                 else
3234                                         Report.Error (51, Location,
3235                                                       "Inconsistent accessibility: parameter type `" +
3236                                                       TypeManager.CSharpName (partype) + "' is less " +
3237                                                       "accessible than method `" + Name + "'");
3238                                 error = true;
3239                         }
3240
3241                         return !error;
3242                 }
3243
3244                 protected virtual bool DoDefine (TypeContainer parent)
3245                 {
3246                         if (Name == null)
3247                                 Name = "this";
3248
3249                         if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3250                                 return false;
3251
3252                         flags = Modifiers.MethodAttr (ModFlags);
3253
3254                         // Lookup Type, verify validity
3255                         MemberType = parent.ResolveType (Type, false, Location);
3256                         if (MemberType == null)
3257                                 return false;
3258
3259                         // verify accessibility
3260                         if (!parent.AsAccessible (MemberType, ModFlags)) {
3261                                 if (this is Property)
3262                                         Report.Error (53, Location,
3263                                                       "Inconsistent accessibility: property type `" +
3264                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3265                                                       "accessible than property `" + Name + "'");
3266                                 else if (this is Indexer)
3267                                         Report.Error (54, Location,
3268                                                       "Inconsistent accessibility: indexer return type `" +
3269                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3270                                                       "accessible than indexer `" + Name + "'");
3271                                 else if (this is Method)
3272                                         Report.Error (50, Location,
3273                                                       "Inconsistent accessibility: return type `" +
3274                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3275                                                       "accessible than method `" + Name + "'");
3276                                 else
3277                                         Report.Error (52, Location,
3278                                                       "Inconsistent accessibility: field type `" +
3279                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3280                                                       "accessible than field `" + Name + "'");
3281                                 return false;
3282                         }
3283
3284                         if (MemberType.IsPointer && !UnsafeOK (parent))
3285                                 return false;
3286                         
3287                         //
3288                         // Check for explicit interface implementation
3289                         //
3290                         if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3291                                 int pos = Name.LastIndexOf (".");
3292
3293                                 ExplicitInterfaceName = Name.Substring (0, pos);
3294                                 ShortName = Name.Substring (pos + 1);
3295                         } else
3296                                 ShortName = Name;
3297
3298                         if (ExplicitInterfaceName != null) {
3299                                 InterfaceType  = RootContext.LookupType (
3300                                         parent, ExplicitInterfaceName, false, Location);
3301                                 if (InterfaceType == null)
3302                                         return false;
3303
3304                                 // Compute the full name that we need to export.
3305                                 Name = InterfaceType.FullName + "." + ShortName;
3306                                 
3307                                 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
3308                                         return false;
3309                                 
3310                                 IsExplicitImpl = true;
3311                         } else
3312                                 IsExplicitImpl = false;
3313
3314                         return true;
3315                 }
3316         }
3317
3318         //
3319         // Fields and Events both generate FieldBuilders, we use this to share 
3320         // their common bits.  This is also used to flag usage of the field
3321         //
3322         abstract public class FieldBase : MemberBase {
3323                 public FieldBuilder  FieldBuilder;
3324                 public Status status;
3325
3326                 [Flags]
3327                 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3328
3329                 //
3330                 // The constructor is only exposed to our children
3331                 //
3332                 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3333                                      object init, Attributes attrs, Location loc)
3334                         : base (type, mod, allowed_mod, name, attrs, loc)
3335                 {
3336                         this.init = init;
3337                 }
3338
3339                 //
3340                 // Whether this field has an initializer.
3341                 //
3342                 public bool HasInitializer {
3343                         get {
3344                                 return init != null;
3345                         }
3346                 }
3347
3348                 // Private.
3349                 readonly Object init;
3350                 Expression init_expr;
3351                 bool init_expr_initialized = false;
3352
3353                 //
3354                 // Resolves and returns the field initializer.
3355                 //
3356                 public Expression GetInitializerExpression (EmitContext ec)
3357                 {
3358                         if (init_expr_initialized)
3359                                 return init_expr;
3360
3361                         Expression e;
3362                         if (init is Expression)
3363                                 e = (Expression) init;
3364                         else
3365                                 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3366
3367                         ec.IsFieldInitializer = true;
3368                         e = e.DoResolve (ec);
3369                         ec.IsFieldInitializer = false;
3370
3371                         init_expr = e;
3372                         init_expr_initialized = true;
3373
3374                         return init_expr;
3375                 }
3376         }
3377
3378         //
3379         // The Field class is used to represents class/struct fields during parsing.
3380         //
3381         public class Field : FieldBase {
3382                 // <summary>
3383                 //   Modifiers allowed in a class declaration
3384                 // </summary>
3385                 const int AllowedModifiers =
3386                         Modifiers.NEW |
3387                         Modifiers.PUBLIC |
3388                         Modifiers.PROTECTED |
3389                         Modifiers.INTERNAL |
3390                         Modifiers.PRIVATE |
3391                         Modifiers.STATIC |
3392                         Modifiers.VOLATILE |
3393                         Modifiers.UNSAFE |
3394                         Modifiers.READONLY;
3395
3396                 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3397                               Attributes attrs, Location loc)
3398                         : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3399                 {
3400                 }
3401
3402                 public override bool Define (TypeContainer parent)
3403                 {
3404                         Type t = parent.ResolveType (Type, false, Location);
3405                         
3406                         if (t == null)
3407                                 return false;
3408
3409                         if (!parent.AsAccessible (t, ModFlags)) {
3410                                 Report.Error (52, Location,
3411                                               "Inconsistent accessibility: field type `" +
3412                                               TypeManager.CSharpName (t) + "' is less " +
3413                                               "accessible than field `" + Name + "'");
3414                                 return false;
3415                         }
3416
3417                         if (t.IsPointer && !UnsafeOK (parent))
3418                                 return false;
3419                                 
3420                         if (RootContext.WarningLevel > 1){
3421                                 Type ptype = parent.TypeBuilder.BaseType;
3422
3423                                 // ptype is only null for System.Object while compiling corlib.
3424                                 if (ptype != null){
3425                                         TypeContainer.FindMembers (
3426                                                 ptype, MemberTypes.Method,
3427                                                 BindingFlags.Public |
3428                                                 BindingFlags.Static | BindingFlags.Instance,
3429                                                 System.Type.FilterName, Name);
3430                                 }
3431                         }
3432
3433                         if ((ModFlags & Modifiers.VOLATILE) != 0){
3434                                 if (!t.IsClass){
3435                                         if (TypeManager.IsEnumType (t))
3436                                                 t = TypeManager.EnumToUnderlying (t);
3437
3438                                         if (!((t == TypeManager.bool_type) ||
3439                                               (t == TypeManager.sbyte_type) ||
3440                                               (t == TypeManager.byte_type) ||
3441                                               (t == TypeManager.short_type) ||    
3442                                               (t == TypeManager.ushort_type) ||
3443                                               (t == TypeManager.int32_type) ||    
3444                                               (t == TypeManager.uint32_type) ||    
3445                                               (t == TypeManager.char_type) ||    
3446                                               (t == TypeManager.float_type))){
3447                                                 Report.Error (
3448                                                         677, Location, parent.MakeName (Name) +
3449                                                         " A volatile field can not be of type `" +
3450                                                         TypeManager.CSharpName (t) + "'");
3451                                                 return false;
3452                                         }
3453                                 }
3454                         }
3455
3456                         FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3457
3458                         if (parent is Struct && 
3459                             ((fa & FieldAttributes.Static) == 0) &&
3460                             t == parent.TypeBuilder &&
3461                             !TypeManager.IsBuiltinType (t)){
3462                                 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name + 
3463                                               "' causes a cycle in the structure layout");
3464                                 return false;
3465                         }
3466                         FieldBuilder = parent.TypeBuilder.DefineField (
3467                                 Name, t, Modifiers.FieldAttr (ModFlags));
3468
3469                         TypeManager.RegisterFieldBase (FieldBuilder, this);
3470                         return true;
3471                 }
3472
3473                 public void Emit (TypeContainer tc)
3474                 {
3475                         EmitContext ec = new EmitContext (tc, Location, null,
3476                                                           FieldBuilder.FieldType, ModFlags);
3477
3478                         Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3479                 }
3480         }
3481
3482         //
3483         // `set' and `get' accessors are represented with an Accessor.
3484         // 
3485         public class Accessor {
3486                 //
3487                 // Null if the accessor is empty, or a Block if not
3488                 //
3489                 public Block Block;
3490                 public Attributes OptAttributes;
3491                 
3492                 public Accessor (Block b, Attributes attrs)
3493                 {
3494                         Block = b;
3495                         OptAttributes = attrs;
3496                 }
3497         }
3498
3499         //
3500         // Properties and Indexers both generate PropertyBuilders, we use this to share 
3501         // their common bits.
3502         //
3503         abstract public class PropertyBase : MethodCore {
3504                 public Accessor Get, Set;
3505                 public PropertyBuilder PropertyBuilder;
3506                 public MethodBuilder GetBuilder, SetBuilder;
3507                 public MethodData GetData, SetData;
3508
3509                 protected EmitContext ec;
3510
3511                 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3512                                      Parameters parameters, Accessor get_block, Accessor set_block,
3513                                      Attributes attrs, Location loc)
3514                         : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3515                 {
3516                         Get = get_block;
3517                         Set = set_block;
3518                 }
3519
3520                 protected override bool DoDefine (TypeContainer parent)
3521                 {
3522                         if (!base.DoDefine (parent))
3523                                 return false;
3524
3525                         ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3526
3527                         return true;
3528                 }
3529
3530                 //
3531                 // Checks our base implementation if any
3532                 //
3533                 protected override bool CheckBase (TypeContainer parent)
3534                 {
3535                         // Check whether arguments were correct.
3536                         if (!DoDefineParameters (parent))
3537                                 return false;
3538
3539                         if (IsExplicitImpl)
3540                                 return true;
3541
3542                         string report_name;
3543                         MethodSignature ms, base_ms;
3544                         if (this is Indexer) {
3545                                 string name, base_name;
3546
3547                                 report_name = "this";
3548                                 name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
3549                                 ms = new MethodSignature (name, null, ParameterTypes);
3550                                 base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
3551                                 base_ms = new MethodSignature (base_name, null, ParameterTypes);
3552                         } else {
3553                                 report_name = Name;
3554                                 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
3555                         }
3556
3557                         MemberList props_this;
3558
3559                         props_this = TypeContainer.FindMembers (
3560                                 parent.TypeBuilder, MemberTypes.Property,
3561                                 BindingFlags.NonPublic | BindingFlags.Public |
3562                                 BindingFlags.Static | BindingFlags.Instance |
3563                                 BindingFlags.DeclaredOnly,
3564                                 MethodSignature.method_signature_filter, ms);
3565
3566                         if (props_this.Count > 0) {
3567                                 Report.Error (111, Location, "Class `" + parent.Name + "' " +
3568                                               "already defines a member called `" + report_name + "' " +
3569                                               "with the same parameter types");
3570                                 return false;
3571                         }
3572
3573                         //
3574                         // Find properties with the same name on the base class
3575                         //
3576                         MemberList props;
3577                         MemberList props_static = TypeContainer.FindMembers (
3578                                 parent.TypeBuilder.BaseType, MemberTypes.Property,
3579                                 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3580                                 MethodSignature.inheritable_property_signature_filter, base_ms);
3581
3582                         MemberList props_instance = TypeContainer.FindMembers (
3583                                 parent.TypeBuilder.BaseType, MemberTypes.Property,
3584                                 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3585                                 MethodSignature.inheritable_property_signature_filter,
3586                                 base_ms);
3587
3588                         //
3589                         // Find if we have anything
3590                         //
3591                         if (props_static.Count > 0)
3592                                 props = props_static;
3593                         else if (props_instance.Count > 0)
3594                                 props = props_instance;
3595                         else
3596                                 props = null;
3597
3598                         //
3599                         // If we have something on the base.
3600                         if (props != null && props.Count > 0){
3601                                 PropertyInfo pi = (PropertyInfo) props [0];
3602
3603                                 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
3604                                 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
3605
3606                                 MethodInfo reference = inherited_get == null ?
3607                                         inherited_set : inherited_get;
3608                                 
3609                                 if (reference != null) {
3610                                         string name = reference.DeclaringType.Name + "." + report_name;
3611
3612                                         if (!CheckMethodAgainstBase (parent, flags, reference, name))
3613                                                 return false;
3614                                 }
3615
3616                                 if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
3617                                         Report.Error (508, parent.MakeName (Name) + ": cannot " +
3618                                                       "change return type when overriding inherited " +
3619                                                       "member `" + pi.DeclaringType + "." + pi.Name + "'");
3620                                         return false;
3621                                 }
3622                         } else {
3623                                 if ((ModFlags & Modifiers.NEW) != 0)
3624                                         WarningNotHiding (parent);
3625                                 
3626                                 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3627                                         if (this is Indexer)
3628                                                 Report.Error (115, Location,
3629                                                               parent.MakeName (Name) +
3630                                                               " no suitable indexers found to override");
3631                                         else
3632                                                 Report.Error (115, Location,
3633                                                               parent.MakeName (Name) +
3634                                                               " no suitable properties found to override");
3635                                         return false;
3636                                 }
3637                         }
3638                         return true;
3639                 }
3640
3641                 public void Emit (TypeContainer tc)
3642                 {
3643                         //
3644                         // The PropertyBuilder can be null for explicit implementations, in that
3645                         // case, we do not actually emit the ".property", so there is nowhere to
3646                         // put the attribute
3647                         //
3648                         if (PropertyBuilder != null)
3649                                 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3650 /*
3651                         if (GetData != null)
3652                                 GetData.Emit (tc, Get.Block, Get);
3653
3654                         if (SetData != null)
3655                                 SetData.Emit (tc, Set.Block, Set);
3656 */                              
3657                 }
3658         }
3659                         
3660         public class Property : PropertyBase {
3661                 const int AllowedModifiers =
3662                         Modifiers.NEW |
3663                         Modifiers.PUBLIC |
3664                         Modifiers.PROTECTED |
3665                         Modifiers.INTERNAL |
3666                         Modifiers.PRIVATE |
3667                         Modifiers.STATIC |
3668                         Modifiers.SEALED |
3669                         Modifiers.OVERRIDE |
3670                         Modifiers.ABSTRACT |
3671                         Modifiers.UNSAFE |
3672                         Modifiers.EXTERN |
3673                         Modifiers.VIRTUAL;
3674
3675                 string set_parameter_name;
3676                 Parameters get_params;
3677                 Parameters set_params;
3678                 
3679                 public Property (Expression type, string name, int mod_flags,
3680                                 Accessor get_block, Accessor set_block,
3681                                 Attributes attrs, Location loc, string set_name, 
3682                                 Parameters p_get, Parameters p_set)
3683                         : base (type, name, mod_flags, AllowedModifiers,
3684                                 p_set,
3685                                 get_block, set_block, attrs, loc)
3686                 {
3687                         set_parameter_name = set_name;
3688                         get_params = p_get;
3689                         set_params = p_set;
3690                         Implements = null;
3691                 }
3692                 
3693                 public Property (Expression type, string name, int mod_flags,
3694                                 Accessor get_block, Accessor set_block,
3695                                 Attributes attrs, Location loc, string set_name, 
3696                                 Parameters p_get, Parameters p_set, Expression impl_what)
3697                         : base (type, name, mod_flags, AllowedModifiers,
3698                                 p_set,
3699                                 get_block, set_block, attrs, loc)
3700                 {
3701                         set_parameter_name = set_name;
3702                         get_params = p_get;
3703                         set_params = p_set;
3704                         Implements = impl_what;
3705                 }               
3706
3707                 public Property (Expression type, string name, int mod_flags,
3708                                  Accessor get_block, Accessor set_block,
3709                                  Attributes attrs, Location loc)
3710                         : base (type, name, mod_flags, AllowedModifiers,
3711                                 Parameters.EmptyReadOnlyParameters,
3712                                 get_block, set_block, attrs, loc)
3713                 {
3714                         set_parameter_name = "Value";
3715                         get_params = Parameters.EmptyReadOnlyParameters;
3716                         set_params = Parameters.EmptyReadOnlyParameters;
3717                 }
3718
3719                 public override bool Define (TypeContainer parent)
3720                 {
3721                         Type [] g_parameters=null, s_parameters=null;
3722                         Parameter [] g_parms, s_parms;
3723                         InternalParameters g_ip=null, s_ip=null;
3724
3725                         if (!DoDefine (parent))
3726                                 return false;
3727
3728                         if (!CheckBase (parent))
3729                                 return false;
3730
3731                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3732
3733                         if (Get != null) {
3734                                 if (get_params == Parameters.EmptyReadOnlyParameters) 
3735                                 {
3736                                         g_parameters = TypeManager.NoTypes;
3737                                         g_ip = new InternalParameters (
3738                                                         parent, Parameters.EmptyReadOnlyParameters);
3739                                 }
3740                                 else
3741                                 {
3742                                         g_parameters = new Type [get_params.FixedParameters.Length];
3743                                         for (int i = 0; i < get_params.FixedParameters.Length; i ++) 
3744                                         {
3745                                                 g_parameters[i] = get_params.FixedParameters[i].ParameterType;
3746                                         }
3747                                         g_parms = new Parameter [get_params.FixedParameters.Length];
3748                                         for (int i = 0; i < get_params.FixedParameters.Length; i ++) 
3749                                         {
3750                                                 Parameter tp = get_params.FixedParameters[i];
3751                                                 g_parms[i] = new Parameter (tp.TypeName, tp.Name,
3752                                                         Parameter.Modifier.NONE, null);
3753                                         }
3754                                         g_ip = new InternalParameters (
3755                                                 parent, new Parameters (g_parms, null, Location));
3756                                 }
3757
3758                                 GetData = new MethodData (this, "get", MemberType,
3759                                                           g_parameters, g_ip, CallingConventions.Standard,
3760                                                           Get.OptAttributes, ModFlags, flags, false);
3761
3762                                 if (!GetData.Define (parent))
3763                                         return false;
3764
3765                                 GetBuilder = GetData.MethodBuilder;
3766                         }
3767
3768                         if (Set != null) {
3769                                 if (set_params == Parameters.EmptyReadOnlyParameters) 
3770                                 {
3771                                         s_parameters = new Type [1];
3772                                         s_parameters [0] = MemberType;
3773
3774                                         s_parms = new Parameter [1];
3775                                         s_parms [0] = new Parameter (Type, /* was "value" */ set_parameter_name, 
3776                                                 Parameter.Modifier.NONE, null);
3777                                 }
3778                                 else
3779                                 {
3780                                         s_parameters = new Type [set_params.FixedParameters.Length];
3781                                         for (int i = 0; i < set_params.FixedParameters.Length; i ++) 
3782                                         {
3783                                                 s_parameters[i] = set_params.FixedParameters[i].ParameterType;
3784                                         }
3785
3786                                         s_parms = new Parameter [set_params.FixedParameters.Length];
3787                                         for (int i = 0; i < set_params.FixedParameters.Length; i ++) 
3788                                         {
3789                                                 Parameter tp = set_params.FixedParameters[i];
3790                                                 s_parms[i] = new Parameter (tp.TypeName, tp.Name,
3791                                                                                                         Parameter.Modifier.NONE, null);
3792                                         }
3793                                 }
3794
3795                                 s_ip = new InternalParameters (
3796                                         parent, new Parameters (s_parms, null, Location));
3797
3798                                 
3799                                 SetData = new MethodData (this, "set", TypeManager.void_type,
3800                                                           s_parameters, s_ip, CallingConventions.Standard,
3801                                                           Set.OptAttributes, ModFlags, flags, false);
3802
3803                                 if (!SetData.Define (parent))
3804                                         return false;
3805
3806                                 SetBuilder = SetData.MethodBuilder;
3807                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, 
3808                                                                 /* was "value" */ set_parameter_name); 
3809                         }
3810
3811                         // FIXME - PropertyAttributes.HasDefault ?
3812                         
3813                         PropertyAttributes prop_attr =
3814                         PropertyAttributes.RTSpecialName |
3815                         PropertyAttributes.SpecialName;
3816
3817                         if (!IsExplicitImpl){
3818                                 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3819                                         Name, prop_attr, MemberType, null);
3820                                 
3821                                 if (Get != null)
3822                                         PropertyBuilder.SetGetMethod (GetBuilder);
3823                                 
3824                                 if (Set != null)
3825                                         PropertyBuilder.SetSetMethod (SetBuilder);
3826
3827                                 //
3828                                 // HACK for the reasons exposed above
3829                                 //
3830                                 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3831                                         Report.Error (
3832                                                 111, Location,
3833                                                 "Class `" + parent.Name +
3834                                                 "' already contains a definition for the property `" +
3835                                                 Name + "'");
3836                                         return false;
3837                                 }
3838                         }
3839                         return true;
3840                 }
3841
3842                 public void Emit (TypeContainer tc)
3843                 {
3844                         base.Emit (tc);
3845                         
3846                         if (GetData != null) 
3847                         {
3848                                 Parameters = get_params;
3849                                 GetData.Emit (tc, Get.Block, Get);
3850                         }
3851
3852                         if (SetData != null) 
3853                         {
3854                                 Parameters = set_params;
3855                                 SetData.Emit (tc, Set.Block, Set);
3856                         }
3857                                 
3858                 }
3859         }
3860
3861         /// </summary>
3862         ///  Gigantic workaround  for lameness in SRE follows :
3863         ///  This class derives from EventInfo and attempts to basically
3864         ///  wrap around the EventBuilder so that FindMembers can quickly
3865         ///  return this in it search for members
3866         /// </summary>
3867         public class MyEventBuilder : EventInfo {
3868                 
3869                 //
3870                 // We use this to "point" to our Builder which is
3871                 // not really a MemberInfo
3872                 //
3873                 EventBuilder MyBuilder;
3874                 
3875                 //
3876                 // We "catch" and wrap these methods
3877                 //
3878                 MethodInfo raise, remove, add;
3879
3880                 EventAttributes attributes;
3881                 Type declaring_type, reflected_type, event_type;
3882                 string name;
3883
3884                 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3885                 {
3886                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3887
3888                         // And now store the values in our own fields.
3889                         
3890                         declaring_type = type_builder;
3891
3892                         reflected_type = type_builder;
3893                         
3894                         attributes = event_attr;
3895                         this.name = name;
3896                         this.event_type = event_type;
3897                 }
3898                 
3899                 //
3900                 // Methods that you have to override.  Note that you only need 
3901                 // to "implement" the variants that take the argument (those are
3902                 // the "abstract" methods, the others (GetAddMethod()) are 
3903                 // regular.
3904                 //
3905                 public override MethodInfo GetAddMethod (bool nonPublic)
3906                 {
3907                         return add;
3908                 }
3909                 
3910                 public override MethodInfo GetRemoveMethod (bool nonPublic)
3911                 {
3912                         return remove;
3913                 }
3914                 
3915                 public override MethodInfo GetRaiseMethod (bool nonPublic)
3916                 {
3917                         return raise;
3918                 }
3919                 
3920                 //
3921                 // These methods make "MyEventInfo" look like a Builder
3922                 //
3923                 public void SetRaiseMethod (MethodBuilder raiseMethod)
3924                 {
3925                         raise = raiseMethod;
3926                         MyBuilder.SetRaiseMethod (raiseMethod);
3927                 }
3928
3929                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3930                 {
3931                         remove = removeMethod;
3932                         MyBuilder.SetRemoveOnMethod (removeMethod);
3933                 }
3934
3935                 public void SetAddOnMethod (MethodBuilder addMethod)
3936                 {
3937                         add = addMethod;
3938                         MyBuilder.SetAddOnMethod (addMethod);
3939                 }
3940
3941                 public void SetCustomAttribute (CustomAttributeBuilder cb)
3942                 {
3943                         MyBuilder.SetCustomAttribute (cb);
3944                 }
3945                 
3946                 public override object [] GetCustomAttributes (bool inherit)
3947                 {
3948                         // FIXME : There's nothing which can be seemingly done here because
3949                         // we have no way of getting at the custom attribute objects of the
3950                         // EventBuilder !
3951                         return null;
3952                 }
3953
3954                 public override object [] GetCustomAttributes (Type t, bool inherit)
3955                 {
3956                         // FIXME : Same here !
3957                         return null;
3958                 }
3959
3960                 public override bool IsDefined (Type t, bool b)
3961                 {
3962                         return true;
3963                 }
3964
3965                 public override EventAttributes Attributes {
3966                         get {
3967                                 return attributes;
3968                         }
3969                 }
3970
3971                 public override string Name {
3972                         get {
3973                                 return name;
3974                         }
3975                 }
3976
3977                 public override Type DeclaringType {
3978                         get {
3979                                 return declaring_type;
3980                         }
3981                 }
3982
3983                 public override Type ReflectedType {
3984                         get {
3985                                 return reflected_type;
3986                         }
3987                 }
3988
3989                 public Type EventType {
3990                         get {
3991                                 return event_type;
3992                         }
3993                 }
3994         }
3995         
3996         public class Event : FieldBase {
3997                 const int AllowedModifiers =
3998                         Modifiers.NEW |
3999                         Modifiers.PUBLIC |
4000                         Modifiers.PROTECTED |
4001                         Modifiers.INTERNAL |
4002                         Modifiers.PRIVATE |
4003                         Modifiers.STATIC |
4004                         Modifiers.VIRTUAL |
4005                         Modifiers.SEALED |
4006                         Modifiers.OVERRIDE |
4007                         Modifiers.UNSAFE |
4008                         Modifiers.ABSTRACT;
4009
4010                 public readonly Accessor  Add;
4011                 public readonly Accessor  Remove;
4012                 public MyEventBuilder     EventBuilder;
4013
4014                 MethodBuilder AddBuilder, RemoveBuilder;
4015                 MethodData AddData, RemoveData;
4016                 
4017                 public Event (Expression type, string name, Object init, int mod, Accessor add,
4018                               Accessor remove, Attributes attrs, Location loc)
4019                         : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4020                 {
4021                         Add = add;
4022                         Remove = remove;
4023                 }
4024
4025                 public override bool Define (TypeContainer parent)
4026                 {
4027                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4028
4029                         if (!DoDefine (parent))
4030                                 return false;
4031
4032                         if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4033                                 Report.Error (66, Location, "'" + parent.Name + "." + Name +
4034                                               "' : event must be of a delegate type");
4035                                 return false;
4036                         }
4037
4038                         Type [] parameter_types = new Type [1];
4039                         parameter_types [0] = MemberType;
4040
4041                         Parameter [] parms = new Parameter [1];
4042                         parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4043                         InternalParameters ip = new InternalParameters (
4044                                 parent, new Parameters (parms, null, Location)); 
4045
4046                         if (!CheckBase (parent))
4047                                 return false;
4048
4049                         //
4050                         // Now define the accessors
4051                         //
4052                         AddData = new MethodData (this, "add", TypeManager.void_type,
4053                                                   parameter_types, ip, CallingConventions.Standard,
4054                                                   (Add != null) ? Add.OptAttributes : null,
4055                                                   ModFlags, flags, false);
4056
4057                         if (!AddData.Define (parent))
4058                                 return false;
4059
4060                         AddBuilder = AddData.MethodBuilder;
4061                         AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4062
4063                         RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4064                                                      parameter_types, ip, CallingConventions.Standard,
4065                                                      (Remove != null) ? Remove.OptAttributes : null,
4066                                                      ModFlags, flags, false);
4067
4068                         if (!RemoveData.Define (parent))
4069                                 return false;
4070
4071                         RemoveBuilder = RemoveData.MethodBuilder;
4072                         RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4073
4074                         if (!IsExplicitImpl){
4075                                 EventBuilder = new MyEventBuilder (
4076                                         parent.TypeBuilder, Name, e_attr, MemberType);
4077                                         
4078                                 if (Add == null && Remove == null) {
4079                                         FieldBuilder = parent.TypeBuilder.DefineField (
4080                                                 Name, MemberType,
4081                                                 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4082                                         TypeManager.RegisterPrivateFieldOfEvent (
4083                                                 (EventInfo) EventBuilder, FieldBuilder);
4084                                         TypeManager.RegisterFieldBase (FieldBuilder, this);
4085                                 }
4086                         
4087                                 EventBuilder.SetAddOnMethod (AddBuilder);
4088                                 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4089
4090                                 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4091                                         Report.Error (111, Location,
4092                                                       "Class `" + parent.Name +
4093                                                       "' already contains a definition for the event `" +
4094                                                       Name + "'");
4095                                         return false;
4096                                 }
4097                         }
4098                         
4099                         return true;
4100                 }
4101
4102                 void EmitDefaultMethod (EmitContext ec, bool is_add)
4103                 {
4104                         ILGenerator ig = ec.ig;
4105                         MethodInfo method = null;
4106                         
4107                         if (is_add)
4108                                 method = TypeManager.delegate_combine_delegate_delegate;
4109                         else
4110                                 method = TypeManager.delegate_remove_delegate_delegate;
4111
4112                         if ((ModFlags & Modifiers.STATIC) != 0) {
4113                                 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4114                                 ig.Emit (OpCodes.Ldarg_0);
4115                                 ig.Emit (OpCodes.Call, method);
4116                                 ig.Emit (OpCodes.Castclass, MemberType);
4117                                 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4118                         } else {
4119                                 ig.Emit (OpCodes.Ldarg_0);
4120                                 ig.Emit (OpCodes.Ldarg_0);
4121                                 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4122                                 ig.Emit (OpCodes.Ldarg_1);
4123                                 ig.Emit (OpCodes.Call, method);
4124                                 ig.Emit (OpCodes.Castclass, MemberType);
4125                                 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4126                         }
4127                         ig.Emit (OpCodes.Ret);
4128                 }
4129
4130                 public void Emit (TypeContainer tc)
4131                 {
4132                         EmitContext ec;
4133
4134                         ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4135                         Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
4136
4137                         if (Add != null)
4138                                 AddData.Emit (tc, Add.Block, Add);
4139                         else {
4140                                 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4141                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4142                                 EmitDefaultMethod (ec, true);
4143                         }
4144
4145                         if (Remove != null)
4146                                 RemoveData.Emit (tc, Remove.Block, Remove);
4147                         else {
4148                                 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4149                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4150                                 EmitDefaultMethod (ec, false);
4151                         }
4152                 }
4153                 
4154         }
4155
4156         //
4157         // FIXME: This does not handle:
4158         //
4159         //   int INTERFACENAME [ args ]
4160         //   Does not 
4161         //
4162         // Only:
4163         // 
4164         // int this [ args ]
4165  
4166         public class Indexer : PropertyBase {
4167
4168                 const int AllowedModifiers =
4169                         Modifiers.NEW |
4170                         Modifiers.PUBLIC |
4171                         Modifiers.PROTECTED |
4172                         Modifiers.INTERNAL |
4173                         Modifiers.PRIVATE |
4174                         Modifiers.VIRTUAL |
4175                         Modifiers.SEALED |
4176                         Modifiers.OVERRIDE |
4177                         Modifiers.UNSAFE |
4178                         Modifiers.EXTERN |
4179                         Modifiers.ABSTRACT;
4180
4181                 public string IndexerName;
4182                 public string InterfaceIndexerName;
4183
4184                 //
4185                 // Are we implementing an interface ?
4186                 //
4187                 bool IsImplementing = false;
4188                 
4189                 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4190                                 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4191                         : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4192                                 attrs, loc)
4193                 {
4194                         ExplicitInterfaceName = int_type;
4195                 }
4196
4197                 public override bool Define (TypeContainer parent)
4198                 {
4199                         PropertyAttributes prop_attr =
4200                                 PropertyAttributes.RTSpecialName |
4201                                 PropertyAttributes.SpecialName;
4202                         
4203                         if (!DoDefine (parent))
4204                                 return false;
4205
4206                         IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4207                         if (IndexerName == null)
4208                                 IndexerName = "Item";
4209                         else if (IsExplicitImpl)
4210                                 Report.Error (592, Location,
4211                                               "Attribute 'IndexerName' is not valid on this declaration " +
4212                                               "type. It is valid on `property' declarations only.");
4213
4214                         ShortName = IndexerName;
4215                         if (IsExplicitImpl) {
4216                                 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4217                                 Name = InterfaceType.FullName + "." + IndexerName;
4218                         } else {
4219                                 InterfaceIndexerName = IndexerName;
4220                                 Name = ShortName;
4221                         }
4222
4223                         if (!CheckBase (parent))
4224                                 return false;
4225
4226                         if (Get != null){
4227                                 InternalParameters ip = new InternalParameters (parent, Parameters);
4228
4229                                 GetData = new MethodData (this, "get", MemberType,
4230                                                           ParameterTypes, ip, CallingConventions.Standard,
4231                                                           Get.OptAttributes, ModFlags, flags, false);
4232
4233                                 if (!GetData.Define (parent))
4234                                         return false;
4235
4236                                 GetBuilder = GetData.MethodBuilder;
4237                         }
4238                         
4239                         if (Set != null){
4240                                 int top = ParameterTypes.Length;
4241                                 Type [] set_pars = new Type [top + 1];
4242                                 ParameterTypes.CopyTo (set_pars, 0);
4243                                 set_pars [top] = MemberType;
4244
4245                                 Parameter [] fixed_parms = Parameters.FixedParameters;
4246
4247                                 if (fixed_parms == null){
4248                                         throw new Exception ("We currently do not support only array arguments in an indexer");
4249                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4250                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4251                                         //
4252                                         // Here is the problem: the `value' parameter has
4253                                         // to come *after* the array parameter in the declaration
4254                                         // like this:
4255                                         // X (object [] x, Type value)
4256                                         // .param [0]
4257                                         //
4258                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4259                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4260                                         
4261                                 }
4262                                 
4263                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4264
4265
4266                                 fixed_parms.CopyTo (tmp, 0);
4267                                 tmp [fixed_parms.Length] = new Parameter (
4268                                         Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4269
4270                                 Parameters set_formal_params = new Parameters (tmp, null, Location);
4271                                 
4272                                 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4273
4274                                 SetData = new MethodData (this, "set", TypeManager.void_type,
4275                                                           set_pars, ip, CallingConventions.Standard,
4276                                                           Set.OptAttributes, ModFlags, flags, false);
4277
4278                                 if (!SetData.Define (parent))
4279                                         return false;
4280
4281                                 SetBuilder = SetData.MethodBuilder;
4282                         }
4283
4284                         //
4285                         // Now name the parameters
4286                         //
4287                         Parameter [] p = Parameters.FixedParameters;
4288                         if (p != null) {
4289                                 int i;
4290                                 
4291                                 for (i = 0; i < p.Length; ++i) {
4292                                         if (Get != null)
4293                                                 GetBuilder.DefineParameter (
4294                                                         i + 1, p [i].Attributes, p [i].Name);
4295
4296                                         if (Set != null)
4297                                                 SetBuilder.DefineParameter (
4298                                                         i + 1, p [i].Attributes, p [i].Name);
4299                                 }
4300                                 
4301
4302                                 if (Set != null)
4303                                         SetBuilder.DefineParameter (
4304                                                 i + 1, ParameterAttributes.None, /* was "value" */ this.Name);
4305                                         
4306                                 if (i != ParameterTypes.Length) {
4307                                         Parameter array_param = Parameters.ArrayParameter;
4308                                         SetBuilder.DefineParameter (
4309                                                 i + 1, array_param.Attributes, array_param.Name);
4310                                 }
4311                         }
4312
4313                         if (GetData != null)
4314                                 IsImplementing = GetData.IsImplementing;
4315                         else if (SetData != null)
4316                                 IsImplementing = SetData.IsImplementing;
4317
4318                         //
4319                         // Define the PropertyBuilder if one of the following conditions are met:
4320                         // a) we're not implementing an interface indexer.
4321                         // b) the indexer has a different IndexerName and this is no
4322                         //    explicit interface implementation.
4323                         //
4324                         if (!IsExplicitImpl) {
4325                                 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4326                                         IndexerName, prop_attr, MemberType, ParameterTypes);
4327
4328                                 if (GetData != null)
4329                                         PropertyBuilder.SetGetMethod (GetBuilder);
4330
4331                                 if (SetData != null)
4332                                         PropertyBuilder.SetSetMethod (SetBuilder);
4333                                 
4334                                 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4335                                                              ParameterTypes);
4336                         }
4337
4338                         return true;
4339                 }
4340         }
4341
4342         public class Operator : MemberCore {
4343
4344                 const int AllowedModifiers =
4345                         Modifiers.PUBLIC |
4346                         Modifiers.UNSAFE |
4347                         Modifiers.EXTERN |
4348                         Modifiers.STATIC;
4349
4350                 const int RequiredModifiers =
4351                         Modifiers.PUBLIC |
4352                         Modifiers.STATIC;
4353
4354                 public enum OpType : byte {
4355
4356                         // Unary operators
4357                         LogicalNot,
4358                         OnesComplement,
4359                         Increment,
4360                         Decrement,
4361                         True,
4362                         False,
4363
4364                         // Unary and Binary operators
4365                         Addition,
4366                         Subtraction,
4367
4368                         UnaryPlus,
4369                         UnaryNegation,
4370                         
4371                         // Binary operators
4372                         Multiply,
4373                         Division,
4374                         Modulus,
4375                         BitwiseAnd,
4376                         BitwiseOr,
4377                         ExclusiveOr,
4378                         LeftShift,
4379                         RightShift,
4380                         Equality,
4381                         Inequality,
4382                         GreaterThan,
4383                         LessThan,
4384                         GreaterThanOrEqual,
4385                         LessThanOrEqual,
4386
4387                         // Implicit and Explicit
4388                         Implicit,
4389                         Explicit
4390                 };
4391
4392                 public readonly OpType OperatorType;
4393                 public readonly Expression ReturnType;
4394                 public readonly Expression FirstArgType, SecondArgType;
4395                 public readonly string FirstArgName, SecondArgName;
4396                 public readonly Block  Block;
4397                 public Attributes      OptAttributes;
4398                 public MethodBuilder   OperatorMethodBuilder;
4399                 
4400                 public string MethodName;
4401                 public Method OperatorMethod;
4402
4403                 public Operator (OpType type, Expression ret_type, int flags,
4404                                  Expression arg1type, string arg1name,
4405                                  Expression arg2type, string arg2name,
4406                                  Block block, Attributes attrs, Location loc)
4407                         : base ("", loc)
4408                 {
4409                         OperatorType = type;
4410                         ReturnType = ret_type;
4411                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4412                         FirstArgType = arg1type;
4413                         FirstArgName = arg1name;
4414                         SecondArgType = arg2type;
4415                         SecondArgName = arg2name;
4416                         Block = block;
4417                         OptAttributes = attrs;
4418                 }
4419
4420                 string Prototype (TypeContainer parent)
4421                 {
4422                         return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4423                                 SecondArgType + ")";
4424                 }
4425                 
4426                 public override bool Define (TypeContainer parent)
4427                 {
4428                         int length = 1;
4429                         MethodName = "op_" + OperatorType;
4430                         
4431                         if (SecondArgType != null)
4432                                 length = 2;
4433                         
4434                         Parameter [] param_list = new Parameter [length];
4435
4436                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4437                                 Report.Error (
4438                                         558, Location, 
4439                                         "User defined operators `" +
4440                                         Prototype (parent) +
4441                                         "' must be declared static and public");
4442                                 return false;
4443                         }
4444
4445                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
4446                                                        Parameter.Modifier.NONE, null);
4447                         if (SecondArgType != null)
4448                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4449                                                                Parameter.Modifier.NONE, null);
4450                         
4451                         OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4452                                                      new Parameters (param_list, null, Location),
4453                                                      OptAttributes, Mono.CSharp.Location.Null);
4454
4455                         OperatorMethod.IsOperator = true;                       
4456                         OperatorMethod.Define (parent);
4457
4458                         if (OperatorMethod.MethodBuilder == null)
4459                                 return false;
4460                         
4461                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4462
4463                         Type [] param_types = OperatorMethod.ParameterTypes;
4464                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
4465                         Type return_type = OperatorMethod.GetReturnType ();
4466                         Type first_arg_type = param_types [0];
4467
4468                         // Rules for conversion operators
4469                         
4470                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4471                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
4472                                         Report.Error (
4473                                                 555, Location,
4474                                                 "User-defined conversion cannot take an object of the " +
4475                                                 "enclosing type and convert to an object of the enclosing" +
4476                                                 " type");
4477                                         return false;
4478                                 }
4479                                 
4480                                 if (first_arg_type != declaring_type && return_type != declaring_type){
4481                                         Report.Error (
4482                                                 556, Location, 
4483                                                 "User-defined conversion must convert to or from the " +
4484                                                 "enclosing type");
4485                                         return false;
4486                                 }
4487                                 
4488                                 if (first_arg_type == TypeManager.object_type ||
4489                                     return_type == TypeManager.object_type){
4490                                         Report.Error (
4491                                                 -8, Location,
4492                                                 "User-defined conversion cannot convert to or from " +
4493                                                 "object type");
4494                                         return false;
4495                                 }
4496
4497                                 if (first_arg_type.IsInterface || return_type.IsInterface){
4498                                         Report.Error (
4499                                                 552, Location,
4500                                                 "User-defined conversion cannot convert to or from an " +
4501                                                 "interface type");
4502                                         return false;
4503                                 }
4504                                 
4505                                 if (first_arg_type.IsSubclassOf (return_type) ||
4506                                     return_type.IsSubclassOf (first_arg_type)){
4507                                         Report.Error (
4508                                                 -10, Location,
4509                                                 "User-defined conversion cannot convert between types " +
4510                                                 "that derive from each other");
4511                                         return false;
4512                                 }
4513                         } else if (SecondArgType == null) {
4514                                 // Checks for Unary operators
4515                                 
4516                                 if (first_arg_type != declaring_type){
4517                                         Report.Error (
4518                                                 562, Location,
4519                                                 "The parameter of a unary operator must be the " +
4520                                                 "containing type");
4521                                         return false;
4522                                 }
4523                                 
4524                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4525                                         if (return_type != declaring_type){
4526                                                 Report.Error (
4527                                                         559, Location,
4528                                                         "The parameter and return type for ++ and -- " +
4529                                                         "must be the containing type");
4530                                                 return false;
4531                                         }
4532                                         
4533                                 }
4534                                 
4535                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4536                                         if (return_type != TypeManager.bool_type){
4537                                                 Report.Error (
4538                                                         215, Location,
4539                                                         "The return type of operator True or False " +
4540                                                         "must be bool");
4541                                                 return false;
4542                                         }
4543                                 }
4544                                 
4545                         } else {
4546                                 // Checks for Binary operators
4547                                 
4548                                 if (first_arg_type != declaring_type &&
4549                                     param_types [1] != declaring_type){
4550                                         Report.Error (
4551                                                 563, Location,
4552                                                 "One of the parameters of a binary operator must " +
4553                                                 "be the containing type");
4554                                         return false;
4555                                 }
4556                         }
4557
4558                         return true;
4559                 }
4560                 
4561                 public void Emit (TypeContainer parent)
4562                 {
4563                         EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4564                         Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4565
4566                         //
4567                         // abstract or extern methods have no bodies
4568                         //
4569                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4570                                 return;
4571                         
4572                         OperatorMethod.Block = Block;
4573                         OperatorMethod.Emit (parent);
4574                 }
4575
4576                 public static string GetName (OpType ot)
4577                 {
4578                         switch (ot){
4579                         case OpType.LogicalNot:
4580                                 return "!";
4581                         case OpType.OnesComplement:
4582                                 return "~";
4583                         case OpType.Increment:
4584                                 return "++";
4585                         case OpType.Decrement:
4586                                 return "--";
4587                         case OpType.True:
4588                                 return "true";
4589                         case OpType.False:
4590                                 return "false";
4591                         case OpType.Addition:
4592                                 return "+";
4593                         case OpType.Subtraction:
4594                                 return "-";
4595                         case OpType.UnaryPlus:
4596                                 return "+";
4597                         case OpType.UnaryNegation:
4598                                 return "-";
4599                         case OpType.Multiply:
4600                                 return "*";
4601                         case OpType.Division:
4602                                 return "/";
4603                         case OpType.Modulus:
4604                                 return "%";
4605                         case OpType.BitwiseAnd:
4606                                 return "&";
4607                         case OpType.BitwiseOr:
4608                                 return "|";
4609                         case OpType.ExclusiveOr:
4610                                 return "^";
4611                         case OpType.LeftShift:
4612                                 return "<<";
4613                         case OpType.RightShift:
4614                                 return ">>";
4615                         case OpType.Equality:
4616                                 return "==";
4617                         case OpType.Inequality:
4618                                 return "!=";
4619                         case OpType.GreaterThan:
4620                                 return ">";
4621                         case OpType.LessThan:
4622                                 return "<";
4623                         case OpType.GreaterThanOrEqual:
4624                                 return ">=";
4625                         case OpType.LessThanOrEqual:
4626                                 return "<=";
4627                         case OpType.Implicit:
4628                                 return "implicit";
4629                         case OpType.Explicit:
4630                                 return "explicit";
4631                         default: return "";
4632                         }
4633                 }
4634                 
4635                 public override string ToString ()
4636                 {
4637                         Type return_type = OperatorMethod.GetReturnType();
4638                         Type [] param_types = OperatorMethod.ParameterTypes;
4639                         
4640                         if (SecondArgType == null)
4641                                 return String.Format (
4642                                         "{0} operator {1}({2})",
4643                                         TypeManager.CSharpName (return_type),
4644                                         GetName (OperatorType),
4645                                         param_types [0]);
4646                         else
4647                                 return String.Format (
4648                                         "{0} operator {1}({2}, {3})",
4649                                         TypeManager.CSharpName (return_type),
4650                                         GetName (OperatorType),
4651                                         param_types [0], param_types [1]);
4652                 }
4653         }
4654
4655         //
4656         // This is used to compare method signatures
4657         //
4658         struct MethodSignature {
4659                 public string Name;
4660                 public Type RetType;
4661                 public Type [] Parameters;
4662                 
4663                 /// <summary>
4664                 ///    This delegate is used to extract methods which have the
4665                 ///    same signature as the argument
4666                 /// </summary>
4667                 public static MemberFilter method_signature_filter;
4668
4669                 /// <summary>
4670                 ///    This delegate is used to extract methods which have the
4671                 ///    same signature as the argument except for the name
4672                 /// </summary>
4673                 public static MemberFilter method_signature_noname_filter;
4674
4675                 /// <summary>
4676                 ///   This delegate is used to extract inheritable methods which
4677                 ///   have the same signature as the argument.  By inheritable,
4678                 ///   this means that we have permissions to override the method
4679                 ///   from the current assembly and class
4680                 /// </summary>
4681                 public static MemberFilter inheritable_method_signature_filter;
4682
4683                 /// <summary>
4684                 ///   This delegate is used to extract inheritable methods which
4685                 ///   have the same signature as the argument.  By inheritable,
4686                 ///   this means that we have permissions to override the method
4687                 ///   from the current assembly and class
4688                 /// </summary>
4689                 public static MemberFilter inheritable_property_signature_filter;
4690                 
4691                 static MethodSignature ()
4692                 {
4693                         method_signature_filter = new MemberFilter (MemberSignatureCompare);
4694                         method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName);
4695                         inheritable_method_signature_filter = new MemberFilter (
4696                                 InheritableMemberSignatureCompare);
4697                         inheritable_property_signature_filter = new MemberFilter (
4698                                 InheritablePropertySignatureCompare);
4699                 }
4700                 
4701                 public MethodSignature (string name, Type ret_type, Type [] parameters)
4702                 {
4703                         Name = name;
4704                         RetType = ret_type;
4705
4706                         if (parameters == null)
4707                                 Parameters = TypeManager.NoTypes;
4708                         else
4709                                 Parameters = parameters;
4710                 }
4711                 
4712                 public override int GetHashCode ()
4713                 {
4714                         return Name.GetHashCode ();
4715                 }
4716
4717                 public override bool Equals (Object o)
4718                 {
4719                         MethodSignature other = (MethodSignature) o;
4720
4721                         if (other.Name != Name)
4722                                 return false;
4723
4724                         if (other.RetType != RetType)
4725                                 return false;
4726                         
4727                         if (Parameters == null){
4728                                 if (other.Parameters == null)
4729                                         return true;
4730                                 return false;
4731                         }
4732
4733                         if (other.Parameters == null)
4734                                 return false;
4735                         
4736                         int c = Parameters.Length;
4737                         if (other.Parameters.Length != c)
4738                                 return false;
4739
4740                         for (int i = 0; i < c; i++)
4741                                 if (other.Parameters [i] != Parameters [i])
4742                                         return false;
4743
4744                         return true;
4745                 }
4746
4747                 static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria)
4748                 {
4749                         return MemberSignatureCompare (m, filter_criteria, false);
4750                 }
4751
4752                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4753                 {
4754                         return MemberSignatureCompare (m, filter_criteria, true);
4755                 }
4756
4757                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name)
4758                 {
4759                         MethodSignature sig = (MethodSignature) filter_criteria;
4760
4761                         if (use_name && (m.Name != sig.Name))
4762                                 return false;
4763
4764                         Type ReturnType;
4765                         MethodInfo mi = m as MethodInfo;
4766                         PropertyInfo pi = m as PropertyInfo;
4767
4768                         if (mi != null)
4769                                 ReturnType = mi.ReturnType;
4770                         else if (pi != null)
4771                                 ReturnType = pi.PropertyType;
4772                         else
4773                                 return false;
4774                         
4775                         //
4776                         // we use sig.RetType == null to mean `do not check the
4777                         // method return value.  
4778                         //
4779                         if (sig.RetType != null)
4780                                 if (ReturnType != sig.RetType)
4781                                         return false;
4782
4783                         Type [] args;
4784                         if (mi != null)
4785                                 args = TypeManager.GetArgumentTypes (mi);
4786                         else
4787                                 args = TypeManager.GetArgumentTypes (pi);
4788                         Type [] sigp = sig.Parameters;
4789
4790                         if (args.Length != sigp.Length)
4791                                 return false;
4792
4793                         for (int i = args.Length; i > 0; ){
4794                                 i--;
4795                                 if (args [i] != sigp [i])
4796                                         return false;
4797                         }
4798                         return true;
4799                 }
4800
4801                 //
4802                 // This filter should be used when we are requesting methods that
4803                 // we want to override.
4804                 //
4805                 // This makes a number of assumptions, for example
4806                 // that the methods being extracted are of a parent
4807                 // class (this means we know implicitly that we are
4808                 // being called to find out about members by a derived
4809                 // class).
4810                 // 
4811                 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4812                 {
4813                         if (MemberSignatureCompare (m, filter_criteria)){
4814                                 MethodInfo mi = (MethodInfo) m;
4815                                 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4816
4817                                 // If only accessible to the current class.
4818                                 if (prot == MethodAttributes.Private)
4819                                         return false;
4820
4821                                 // If only accessible to the defining assembly or 
4822                                 if (prot == MethodAttributes.FamANDAssem ||
4823                                     prot == MethodAttributes.Assembly){
4824                                         if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4825                                                 return true;
4826                                         else
4827                                                 return false;
4828                                 }
4829
4830                                 // Anything else (FamOrAssembly and Public) is fine
4831                                 return true;
4832                         }
4833                         return false;
4834                 }
4835
4836                 //
4837                 // This filter should be used when we are requesting properties that
4838                 // we want to override.
4839                 //
4840                 // This makes a number of assumptions, for example
4841                 // that the methods being extracted are of a parent
4842                 // class (this means we know implicitly that we are
4843                 // being called to find out about members by a derived
4844                 // class).
4845                 // 
4846                 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4847                 {
4848                         if (MemberSignatureCompare (m, filter_criteria)){
4849                                 PropertyInfo pi = (PropertyInfo) m;
4850
4851                                 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4852                                 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4853
4854                                 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4855
4856                                 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4857
4858                                 // If only accessible to the current class.
4859                                 if (prot == MethodAttributes.Private)
4860                                         return false;
4861
4862                                 // If only accessible to the defining assembly or 
4863                                 if (prot == MethodAttributes.FamANDAssem ||
4864                                     prot == MethodAttributes.Assembly){
4865                                         if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4866                                                 return true;
4867                                         else
4868                                                 return false;
4869                                 }
4870
4871                                 // Anything else (FamOrAssembly and Public) is fine
4872                                 return true;
4873                         }
4874                         return false;
4875                 }
4876         }
4877 }