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