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