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