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