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