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