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