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