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