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