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