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