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