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