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