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