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