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