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