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