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