**** Merged from MCS ****
[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                                         Attributes attr = p [i].OptAttributes;
2290                                         if (attr != null)
2291                                                 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2292                                 }
2293                         }
2294
2295                         if (Parameters.ArrayParameter != null){
2296                                 ParameterBuilder pb;
2297                                 Parameter array_param = Parameters.ArrayParameter;
2298                                 
2299                                 if (mb == null)
2300                                         pb = cb.DefineParameter (
2301                                                 i + 1, array_param.Attributes,
2302                                                 array_param.Name);
2303                                 else
2304                                         pb = mb.DefineParameter (
2305                                                 i + 1, array_param.Attributes,
2306                                                 array_param.Name);
2307                                         
2308                                 CustomAttributeBuilder a = new CustomAttributeBuilder (
2309                                         TypeManager.cons_param_array_attribute, new object [0]);
2310                                 
2311                                 pb.SetCustomAttribute (a);
2312                         }
2313                 }
2314         }
2315         
2316         public class Method : MethodCore {
2317                 public MethodBuilder MethodBuilder;
2318                 public MethodData MethodData;
2319
2320                 /// <summary>
2321                 ///   Modifiers allowed in a class declaration
2322                 /// </summary>
2323                 const int AllowedModifiers =
2324                         Modifiers.NEW |
2325                         Modifiers.PUBLIC |
2326                         Modifiers.PROTECTED |
2327                         Modifiers.INTERNAL |
2328                         Modifiers.PRIVATE |
2329                         Modifiers.STATIC |
2330                         Modifiers.VIRTUAL |
2331                         Modifiers.NONVIRTUAL |
2332                         Modifiers.OVERRIDE |
2333                         Modifiers.ABSTRACT |
2334                         Modifiers.UNSAFE |
2335                         Modifiers.EXTERN|
2336                         Modifiers.SHADOWS;
2337
2338                 //
2339                 // return_type can be "null" for VOID values.
2340                 //
2341                 public Method (Expression return_type, int mod, string name, Parameters parameters,
2342                                Attributes attrs, Location l)
2343                         : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2344                 { 
2345                         Implements = null;
2346                 }
2347
2348                 public Method (Expression return_type, int mod, string name, Parameters parameters,
2349                         Attributes attrs, ArrayList impl_what, Location l)
2350                         : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2351                 { 
2352                         Implements = impl_what;
2353                 }
2354
2355                 //
2356                 // Returns the `System.Type' for the ReturnType of this
2357                 // function.  Provides a nice cache.  (used between semantic analysis
2358                 // and actual code generation
2359                 //
2360                 public Type GetReturnType ()
2361                 {
2362                         return MemberType;
2363                 }
2364
2365                 void DuplicateEntryPoint (MethodInfo b, Location location)
2366                 {
2367                                 Report.Error (
2368                                                 30738, location,
2369                                                 "Program `" + CodeGen.FileName +
2370                                                 "'  has more than one entry point defined: `" +
2371                                                 TypeManager.MonoBASIC_Signature(b) + "'");
2372                 }
2373
2374                 void Report28 (MethodInfo b)
2375                 {
2376                         if (RootContext.WarningLevel < 4) 
2377                                 return;
2378                                 
2379                         Report.Warning (
2380                                         28, Location,
2381                                         "`" + TypeManager.MonoBASIC_Signature(b) +
2382                                         "' has the wrong signature to be an entry point");
2383                 }
2384
2385                 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2386                 {
2387                         if (b.ReturnType != TypeManager.void_type &&
2388                                 b.ReturnType != TypeManager.int32_type)
2389                                         return false;
2390
2391                         if (pinfo.Count == 0)
2392                                         return true;
2393
2394                         if (pinfo.Count > 1)
2395                                         return false;
2396
2397                         Type t = pinfo.ParameterType(0);
2398                         if (t.IsArray &&
2399                                 (t.GetArrayRank() == 1) &&
2400                                 (t.GetElementType() == TypeManager.string_type) &&
2401                                 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2402                                         return true;
2403                         else
2404                                         return false;
2405                 }
2406
2407                 //
2408                 // Checks our base implementation if any
2409                 //
2410                 protected override bool CheckBase (TypeContainer parent)
2411                 {
2412                         // Check whether arguments were correct.
2413                         if (!DoDefineParameters (parent))
2414                                 return false;
2415
2416                         MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2417                         if (!IsOperator) {
2418                                 MemberList mi_this;
2419
2420                                 mi_this = TypeContainer.FindMembers (
2421                                         parent.TypeBuilder, MemberTypes.Method,
2422                                         BindingFlags.NonPublic | BindingFlags.Public |
2423                                         BindingFlags.Static | BindingFlags.Instance |
2424                                         BindingFlags.DeclaredOnly,
2425                                         MethodSignature.method_signature_filter, ms);
2426
2427                                 if (mi_this.Count > 0) {
2428                                         Report.Error (111, Location, "Class `" + parent.Name + "' " +
2429                                                       "already defines a member called `" + Name + "' " +
2430                                                       "with the same parameter types");
2431                                         return false;
2432                                 }
2433                         }
2434
2435                         //
2436                         // Verify if the parent has a type with the same name, and then
2437                         // check whether we have to create a new slot for it or not.
2438                         //
2439                         Type ptype = parent.TypeBuilder.BaseType;
2440
2441                         // ptype is only null for System.Object while compiling corlib.
2442                         if (ptype != null){
2443                                 MemberList mi, mi_static, mi_instance;
2444
2445                                 mi_static = TypeContainer.FindMembers (
2446                                         ptype, MemberTypes.Method,
2447                                         BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2448                                         MethodSignature.inheritable_method_signature_filter, ms);
2449
2450                                 mi_instance = TypeContainer.FindMembers (
2451                                         ptype, MemberTypes.Method,
2452                                         BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2453                                         MethodSignature.inheritable_method_signature_filter,
2454                                         ms);
2455
2456                                 if (mi_instance.Count > 0){
2457                                         mi = mi_instance;
2458                                 } else if (mi_static.Count > 0)
2459                                         mi = mi_static;
2460                                 else
2461                                         mi = null;
2462
2463                                 if (mi != null && mi.Count > 0){
2464                                         parent_method = (MethodInfo) mi [0];
2465                                         string name = parent_method.DeclaringType.Name + "." +
2466                                                 parent_method.Name;
2467
2468                                         if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2469                                                 return false;
2470
2471                                         if ((ModFlags & Modifiers.NEW) == 0) {
2472                                                 Type parent_ret = TypeManager.TypeToCoreType (
2473                                                         parent_method.ReturnType);
2474
2475                                                 if (parent_ret != MemberType) {
2476                                                         Report.Error (
2477                                                                 508, parent.MakeName (Name) + ": cannot " +
2478                                                                 "change return type when overriding " +
2479                                                                 "inherited member " + name);
2480                                                         return false;
2481                                                 }
2482                                         }
2483                                 } else {
2484                                         /*if ((ModFlags & Modifiers.NEW) != 0)
2485                                                 WarningNotHiding (parent);*/
2486
2487                                         if ((ModFlags & Modifiers.OVERRIDE) != 0){
2488                                                 Report.Error (30284, Location,
2489                                                               parent.MakeName (Name) +
2490                                                               " : No suitable methods found to override");
2491                                         }
2492                                         if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0) \r
2493                                         {
2494                                                 if ((ModFlags & Modifiers.NONVIRTUAL) != 0)\r
2495                                                 {
2496                                                         Report.Error (31088, Location,
2497                                                                 parent.MakeName (Name) + " : Cannot " +
2498                                                                 "be declared NotOverridable since this method is " +
2499                                                                 "not maked as Overrides");
2500                                                 }
2501                                         }
2502                                         // if a member of module is not inherited from Object class
2503                                         // can not be declared protected
2504                                         if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
2505                                                 Report.Error (31066, Location,
2506                                                                 "'Sub' or 'Function' inside a 'Module' can not be declared as " +
2507                                                                 "'Protected' or 'Protected Friend'");
2508                                 }
2509                         }
2510                         /* else if ((ModFlags & Modifiers.NEW) != 0)
2511                                 WarningNotHiding (parent);
2512                         */
2513
2514                         return true;
2515                 }
2516
2517                 //
2518                 // Creates the type
2519                 //
2520                 public override bool Define (TypeContainer parent)
2521                 {
2522                         if (!DoDefine (parent))
2523                                 return false;
2524
2525                         if (!CheckBase (parent))
2526                                 return false;
2527
2528                         if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
2529                                 Report.Error (31067, Location,
2530                                         "'Sub' or 'Function' inside a 'Structure' can not be declared as " +
2531                                         "'Protected' or 'Protected Friend'");
2532
2533                         CallingConventions cc = GetCallingConvention (parent is Class);
2534
2535                         MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2536                                                      ParameterInfo, cc, OptAttributes,
2537                                                      ModFlags, flags, true);
2538
2539                         if (!MethodData.Define (parent))
2540                                 return false;
2541
2542                         MethodBuilder = MethodData.MethodBuilder;
2543                         
2544                         //
2545                         // This is used to track the Entry Point,
2546                         //
2547                         if (Name.ToUpper() == "MAIN" &&
2548                             ((ModFlags & Modifiers.STATIC) != 0) && 
2549                             (RootContext.MainClass == null ||
2550                              RootContext.MainClass == parent.TypeBuilder.FullName ||
2551                              (RootContext.RootNamespace != null &&
2552                                   RootContext.RootNamespace.Length > 0 &&
2553                                   (RootContext.RootNamespace + "." + RootContext.MainClass) == parent.TypeBuilder.FullName))) {
2554                                 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2555                                         if (RootContext.EntryPoint == null) {
2556                                                 RootContext.EntryPoint = MethodBuilder;
2557                                                 RootContext.EntryPointLocation = Location;
2558                                         } else {
2559                                                 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2560                                                 DuplicateEntryPoint (MethodBuilder, Location);
2561                                         }
2562                                 } else                                  
2563                                         Report28(MethodBuilder);
2564                         }
2565
2566                         return true;
2567                 }
2568
2569                 //
2570                 // Emits the code
2571                 // 
2572                 public void Emit (TypeContainer parent)
2573                 {
2574                         MethodData.Emit (parent, Block, this);
2575                 }
2576         }
2577
2578         public abstract class ConstructorInitializer {
2579                 ArrayList argument_list;
2580                 ConstructorInfo parent_constructor;
2581                 Parameters parameters;
2582                 Location loc;
2583                 public bool implicit_initialization;
2584                 
2585                 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2586                                                Location loc)
2587                 {
2588                         this.argument_list = argument_list;
2589                         this.parameters = parameters;
2590                         this.loc = loc;
2591                         this.implicit_initialization = false;
2592                 }
2593
2594                 public ArrayList Arguments {
2595                         get {
2596                                 return argument_list;
2597                         }
2598                 }
2599
2600                 public ConstructorInfo ParentConstructor
2601                 {
2602                         get\r
2603                         {
2604                                 return parent_constructor;
2605                         }
2606                 }
2607         
2608                 public bool Resolve (EmitContext ec)
2609                 {
2610                         Expression parent_constructor_group;
2611                         Type t;
2612
2613                         ec.CurrentBlock = new Block (null, true, parameters);
2614
2615                         if (argument_list != null){
2616                                 foreach (Argument a in argument_list){
2617                                         if (!a.Resolve (ec, loc))
2618                                                 return false;
2619                                 }
2620                         }
2621
2622                         ec.CurrentBlock = null;
2623
2624                         if (this is ConstructorBaseInitializer) {
2625                                 if (ec.ContainerType.BaseType == null)
2626                                         return true;
2627
2628                                 t = ec.ContainerType.BaseType;
2629                                 if (ec.ContainerType.IsValueType){
2630                                         Report.Error (522, loc,
2631                                                 "structs cannot call base class constructors");
2632                                         return false;
2633                                 }
2634                         }\r
2635                         else
2636                                 t = ec.ContainerType;
2637                         
2638                         parent_constructor_group = Expression.MemberLookup (
2639                                 ec, t, t, ".ctor", 
2640                                 MemberTypes.Constructor,
2641                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2642                                 loc);
2643                         
2644                         if (parent_constructor_group == null){
2645                                 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2646                                 return false;
2647                         }
2648
2649                         parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
2650                                 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2651
2652                         if (parent_constructor == null) {
2653                                 if (this.implicit_initialization)
2654                                         Report.Error (30148, loc, "Must declare 'MyBase.New' in the constructor " +\r
2655                                         "of the class '" + ec.TypeContainer.Name + "' with appropriate arguments, since the base class '" +\r
2656                                                 t.FullName + "' does not contain a definition of 'New' without any parameter");
2657                                 else
2658                                         Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2659
2660                                 return false;
2661                         }
2662
2663                         return true;
2664                 }
2665
2666                 public void Emit (EmitContext ec)
2667                 {
2668                         if (parent_constructor != null){
2669                                 if (ec.IsStatic)
2670                                         Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2671                                 else
2672                                         Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2673                         }
2674                 }
2675
2676
2677         }
2678
2679         public class ConstructorBaseInitializer : ConstructorInitializer {
2680                 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2681                         base (argument_list, pars, l)
2682                 {
2683                 }
2684         }
2685
2686         public class ConstructorThisInitializer : ConstructorInitializer {
2687                 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2688                         base (argument_list, pars, l)
2689                 {
2690                 }
2691         }
2692         
2693         public class Constructor : MethodCore {
2694                 public ConstructorBuilder ConstructorBuilder;
2695                 public ConstructorInitializer Initializer;
2696                 new public Attributes OptAttributes;
2697
2698                 // <summary>
2699                 //   Modifiers allowed for a constructor.
2700                 // </summary>
2701                 public const int AllowedModifiers =
2702                         Modifiers.PUBLIC |
2703                         Modifiers.PROTECTED |
2704                         Modifiers.INTERNAL |
2705                         Modifiers.STATIC |
2706                         Modifiers.UNSAFE |
2707                         Modifiers.EXTERN |              
2708                         Modifiers.PRIVATE;
2709
2710                 //
2711                 // The spec claims that static is not permitted, but
2712                 // my very own code has static constructors.
2713                 //
2714                 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2715                         : base (null, 0, AllowedModifiers, name, null, args, l)
2716                 {
2717                         Initializer = init;
2718                 }
2719
2720                 public Constructor (string name, int mod, Parameters args, ConstructorInitializer init, Location l)
2721                         : base (null, mod, AllowedModifiers, name, null, args, l)
2722                 {
2723                         Initializer = init;
2724                 }
2725
2726                 //
2727                 // Returns true if this is a default constructor
2728                 //
2729                 public bool IsDefault ()
2730                 {
2731                         if ((ModFlags & Modifiers.STATIC) != 0)
2732                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2733                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2734                         
2735                         else
2736                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2737                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2738                                         (Initializer is ConstructorBaseInitializer) &&
2739                                         (Initializer.Arguments == null);
2740                 }
2741
2742                 //
2743                 // Creates the ConstructorBuilder
2744                 //
2745                 public override bool Define (TypeContainer parent)
2746                 {
2747                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
2748                                                MethodAttributes.SpecialName);
2749
2750                         if (parent.EventHandlers != null) {
2751                                 ArrayList hdlrs = parent.EventHandlers;
2752                                 foreach(Statement stmt in hdlrs)
2753                     this.Block.AddStatement (stmt);
2754                         }
2755
2756
2757                         // Check if arguments were correct.
2758                         if (!DoDefineParameters (parent))
2759                                 return false;
2760
2761                         if ((ModFlags & Modifiers.STATIC) != 0) {
2762                                 ca |= MethodAttributes.Static;
2763
2764                                 if (this.Parameters != Parameters.EmptyReadOnlyParameters)
2765                                         Report.Error (
2766                                                 30479, Location, 
2767                                                 "Shared constructor can not have parameters");
2768
2769                                 if ((ModFlags & Modifiers.Accessibility) != 0)
2770                                         Report.Error (
2771                                                 30480, Location, 
2772                                                 "Shared constructor can not be declared " +
2773                                                 "explicitly as public, private, friend or protected");
2774
2775                                 if (this.Initializer != null)
2776                                         Report.Error (
2777                                                 30043, Location, 
2778                                                 "Keywords like MyBase, MyClass, Me are not " +
2779                                                 "valid inside a Shared Constructor");
2780                         }
2781                         else {
2782                                 if (parent is Struct && ParameterTypes.Length == 0)     {
2783                                         Report.Error (
2784                                                 30629, Location, 
2785                                                 "Structs can not contain explicit parameterless " +
2786                                                 "constructors");
2787                                         return false;
2788                                 }
2789                                 ca |= MethodAttributes.HideBySig;
2790
2791                                 if ((ModFlags & Modifiers.PUBLIC) != 0)
2792                                         ca |= MethodAttributes.Public;
2793                                 else if ((ModFlags & Modifiers.PROTECTED) != 0) {
2794                                         if ((ModFlags & Modifiers.INTERNAL) != 0)
2795                                                 ca |= MethodAttributes.FamORAssem;
2796                                         else 
2797                                                 ca |= MethodAttributes.Family;
2798                                 }\r
2799                                 else if ((ModFlags & Modifiers.INTERNAL) != 0)
2800                                         ca |= MethodAttributes.Assembly;
2801                                 else if (IsDefault ())
2802                                         ca |= MethodAttributes.Public;
2803                                 else
2804                                         ca |= MethodAttributes.Private;
2805                         }
2806
2807                         ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2808                                 ca, GetCallingConvention (parent is Class), ParameterTypes);
2809
2810                         //
2811                         // HACK because System.Reflection.Emit is lame
2812                         //
2813                         if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2814                                 Report.Error (
2815                                         111, Location,
2816                                         "Class `" +parent.Name+ "' already contains a definition with the " +
2817                                         "same return value and parameter types for constructor `" + Name
2818                                         + "'");
2819                                 return false;
2820                         }
2821
2822                         return true;
2823                 }
2824
2825                 //
2826                 // Emits the code
2827                 //
2828                 public void Emit (TypeContainer parent)
2829                 {
2830                         ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2831                         EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2832
2833                         if ((ModFlags & Modifiers.STATIC) == 0){
2834                                 if (parent is Class && Initializer == null) {
2835                                         Initializer = new ConstructorBaseInitializer (
2836                                                 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2837                                         Initializer.implicit_initialization = true;
2838                                 }
2839
2840                                 //
2841                                 // Spec mandates that Initializers will not have
2842                                 // `this' access
2843                                 //
2844                                 ec.IsStatic = true;
2845                                 if (Initializer != null && !Initializer.Resolve (ec))
2846                                         return;
2847                                 ec.IsStatic = false;
2848                         }
2849
2850                         LabelParameters (ec, ParameterTypes, ConstructorBuilder);
2851                         
2852                         //
2853                         // Classes can have base initializers and instance field initializers.
2854                         //
2855                         if (parent is Class){
2856                                 if ((ModFlags & Modifiers.STATIC) == 0)
2857                                         parent.EmitFieldInitializers (ec);
2858                         }
2859
2860                         if (Initializer != null) {
2861                                 if (this.ConstructorBuilder.Equals (Initializer.ParentConstructor))
2862                                         Report.Error (
2863                                                 30297, Location,
2864                                                 "A constructor can not call itself" );
2865
2866                                 Initializer.Emit (ec);
2867                         }
2868                         
2869                         if ((ModFlags & Modifiers.STATIC) != 0)
2870                                 parent.EmitFieldInitializers (ec);
2871
2872                         Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2873
2874                         // If this is a non-static `struct' constructor and doesn't have any
2875                         // initializer, it must initialize all of the struct's fields.
2876                         if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2877                             (Initializer == null))
2878                                 Block.AddThisVariable (parent, Location);
2879
2880                         ec.EmitTopBlock (Block, ParameterInfo, Location);
2881                 }
2882         }
2883
2884         public class MethodData {
2885                 //
2886                 // The return type of this method
2887                 //
2888                 public readonly Type ReturnType;
2889                 public readonly Type[] ParameterTypes;
2890                 public readonly InternalParameters ParameterInfo;
2891                 public readonly CallingConventions CallingConventions;
2892                 public readonly Attributes OptAttributes;
2893                 public readonly Location Location;
2894
2895                 //
2896                 // Are we implementing an interface ?
2897                 //
2898                 public bool IsImplementing = false;
2899
2900                 //
2901                 // Protected data.
2902                 //
2903                 protected MemberBase member;
2904                 protected int modifiers;
2905                 protected MethodAttributes flags;
2906                 protected bool is_method;
2907                 protected string accessor_name;
2908                 ArrayList conditionals;
2909
2910                 MethodBuilder builder = null;
2911                 public MethodBuilder MethodBuilder {
2912                         get {
2913                                 return builder;
2914                         }
2915                 }
2916
2917                 public MethodData (MemberBase member, string name, Type return_type,
2918                                    Type [] parameter_types, InternalParameters parameters,
2919                                    CallingConventions cc, Attributes opt_attrs,
2920                                    int modifiers, MethodAttributes flags, bool is_method)
2921                 {
2922                         this.member = member;
2923                         this.accessor_name = name;
2924                         this.ReturnType = return_type;
2925                         this.ParameterTypes = parameter_types;
2926                         this.ParameterInfo = parameters;
2927                         this.CallingConventions = cc;
2928                         this.OptAttributes = opt_attrs;
2929                         this.modifiers = modifiers;
2930                         this.flags = flags;
2931                         this.is_method = is_method;
2932                         this.Location = member.Location;
2933                         this.conditionals = new ArrayList ();
2934                 }
2935
2936                 //
2937                 // Attributes.
2938                 //
2939                 Attribute dllimport_attribute = null;
2940                 string obsolete = null;
2941                 bool obsolete_error = false;
2942
2943                 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2944                 {
2945                         if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2946                                 return true;
2947
2948                         foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2949                                 if (asec.Attributes == null)
2950                                         continue;
2951                                         
2952                                 foreach (Attribute a in asec.Attributes) {
2953                                         if (a.Name == "Conditional") {
2954                                                 if (!ApplyConditionalAttribute (a))
2955                                                         return false;
2956                                         } else if (a.Name == "Obsolete") {
2957                                                 if (!ApplyObsoleteAttribute (a))
2958                                                         return false;
2959                                         } else if (a.Name.IndexOf ("DllImport") != -1) {
2960                                                 if (!is_method) {
2961                                                         a.Type = TypeManager.dllimport_type;
2962                                                         Attribute.Error_AttributeNotValidForElement (a, Location);
2963                                                         return false;
2964                                                 }
2965                                                 if (!ApplyDllImportAttribute (a))
2966                                                         return false;
2967                                         }
2968                                 }
2969                         }
2970
2971                         return true;
2972                 }
2973
2974                 //
2975                 // Applies the `DllImport' attribute to the method.
2976                 //
2977                 protected virtual bool ApplyDllImportAttribute (Attribute a)
2978                 {
2979                         const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2980                         if ((modifiers & extern_static) != extern_static) {
2981                                 Report.Error (601, Location,
2982                                               "The DllImport attribute must be specified on a method " +
2983                                               "marked `static' and `extern'.");
2984                                 return false;
2985                         }
2986
2987                         flags |= MethodAttributes.PinvokeImpl;
2988                         dllimport_attribute = a;
2989                         return true;
2990                 }
2991
2992                 //
2993                 // Applies the `Obsolete' attribute to the method.
2994                 //
2995                 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2996                 {
2997                         if (obsolete != null) {
2998                                 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2999                                 return false;
3000                         }
3001
3002                         obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3003                         return obsolete != null;
3004                 }
3005
3006                 //
3007                 // Applies the `Conditional' attribute to the method.
3008                 //
3009                 protected virtual bool ApplyConditionalAttribute (Attribute a)
3010                 {
3011                         // The Conditional attribute is only valid on methods.
3012                         if (!is_method) {
3013                                 Attribute.Error_AttributeNotValidForElement (a, Location);
3014                                 return false;
3015                         }
3016
3017                         string condition = a.Conditional_GetConditionName ();
3018
3019                         if (condition == null)
3020                                 return false;
3021
3022                         if (ReturnType != TypeManager.void_type) {
3023                                 Report.Error (578, Location,
3024                                               "Conditional not valid on `" + member.Name + "' " +
3025                                               "because its return type is not void");
3026                                 return false;
3027                         }
3028
3029                         if ((modifiers & Modifiers.OVERRIDE) != 0) {
3030                                 Report.Error (243, Location,
3031                                               "Conditional not valid on `" + member.Name + "' " +
3032                                               "because it is an override method");
3033                                 return false;
3034                         }
3035
3036                         if (member.IsExplicitImpl) {
3037                                 Report.Error (577, Location,
3038                                               "Conditional not valid on `" + member.Name + "' " +
3039                                               "because it is an explicit interface implementation");
3040                                 return false;
3041                         }
3042
3043                         if (IsImplementing) {
3044                                 Report.Error (623, Location,
3045                                               "Conditional not valid on `" + member.Name + "' " +
3046                                               "because it is an interface method");
3047                                 return false;
3048                         }
3049
3050                         conditionals.Add (condition);
3051
3052                         return true;
3053                 }
3054
3055                 //
3056                 // Checks whether this method should be ignored due to its Conditional attributes.
3057                 //
3058                 bool ShouldIgnore (Location loc)
3059                 {
3060                         // When we're overriding a virtual method, we implicitly inherit the
3061                         // Conditional attributes from our parent.
3062                         if (member.ParentMethod != null) {
3063                                 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3064                                         member.ParentMethod, loc);
3065
3066                                 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3067                                         return true;
3068                         }
3069
3070                         foreach (string condition in conditionals)
3071                                 if (RootContext.AllDefines [condition] == null)
3072                                         return true;
3073
3074                         return false;
3075                 }
3076
3077                 //
3078                 // Returns the TypeManager.MethodFlags for this method.
3079                 // This emits an error 619 / warning 618 if the method is obsolete.
3080                 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3081                 //
3082                 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3083                 {
3084                         TypeManager.MethodFlags flags = 0;
3085
3086                         if (obsolete != null) {
3087                                 if (obsolete_error) {
3088                                         Report.Error (619, loc, "Method `" + member.Name +
3089                                                       "' is obsolete: `" + obsolete + "'");
3090                                         return TypeManager.MethodFlags.IsObsoleteError;
3091                                 } else
3092                                         Report.Warning (618, loc, "Method `" + member.Name +
3093                                                         "' is obsolete: `" + obsolete + "'");
3094
3095                                 flags |= TypeManager.MethodFlags.IsObsolete;
3096                         }
3097
3098                         if (ShouldIgnore (loc))
3099                             flags |= TypeManager.MethodFlags.ShouldIgnore;
3100
3101                         return flags;
3102                 }
3103                 
3104                 //
3105                 // Search all the interface bases recursively for unimplemented methods
3106                 //
3107                 bool SearchBasesForAbstractMethods (
3108                         TypeContainer parent, Type iface_type, 
3109                         string method_name, ref ArrayList implementing_list, 
3110                         ref ArrayList implementing_iface)
3111                 {
3112                         MethodInfo implementing = null;
3113                         bool IsImplementing = false;
3114                         Type current_iface_type = iface_type;
3115
3116                                 if (member is Indexer)
3117                                         implementing = parent.Pending.IsAbstractIndexer (
3118                                         current_iface_type , ReturnType, ParameterTypes);
3119                                 else
3120                                         implementing = parent.Pending.IsAbstractMethod (
3121                                         current_iface_type, method_name, ReturnType, ParameterTypes);
3122
3123                                 if (implementing != null) {
3124                                         if (!implementing_list.Contains (implementing)) {
3125                                                 implementing_list.Add (implementing);
3126                                                 implementing_iface.Add(current_iface_type);
3127                                         }
3128                                         IsImplementing = true;
3129                                 } else {
3130                                         Type[] current_iface_types = current_iface_type.GetInterfaces();
3131                                         if (current_iface_types.Length == 0)
3132                                                 return false;
3133
3134                                         foreach (Type curr_iface_type in current_iface_types) {
3135                                                 IsImplementing = SearchBasesForAbstractMethods (
3136                                                         parent, curr_iface_type, method_name, 
3137                                                         ref implementing_list, ref implementing_iface);
3138
3139                                                 if (IsImplementing)
3140                                                         break;
3141                                         }
3142                                 }
3143
3144                         return IsImplementing;
3145                 }
3146
3147                 public virtual bool Define (TypeContainer parent)
3148                 {
3149                         MethodInfo implementing = null;
3150                         ArrayList implementing_list = null;
3151                         ArrayList implementing_iface = null;
3152                         string method_name, name, prefix, impl_method_name;
3153                         int pos = -1;
3154
3155                         if (OptAttributes != null)
3156                                 if (!ApplyAttributes (OptAttributes, is_method))
3157                                         return false;
3158
3159                         if (accessor_name != null)
3160                                 name = accessor_name + "_" + member.ShortName;
3161                         else
3162                                 name = member.ShortName;
3163
3164                         method_name = name;
3165                         impl_method_name = name;
3166
3167                         if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
3168                                 if (parent.Pending == null)
3169                                         implementing = null;
3170                                 else if (member is Indexer)
3171                                         implementing = parent.Pending.IsAbstractIndexer (
3172                                                 (Type) parent.TypeBuilder.BaseType, 
3173                                                 ReturnType, ParameterTypes);
3174                                 else
3175                                         implementing = parent.Pending.IsAbstractMethod (
3176                                                 (Type) parent.TypeBuilder.BaseType, name, 
3177                                                 ReturnType, ParameterTypes);
3178                                 
3179                                 if (implementing != null)\r
3180                                         IsImplementing = true;
3181                         }
3182
3183                         if (member.Implements != null) {
3184                                 implementing_list = new ArrayList();
3185                                 implementing_iface = new ArrayList();
3186
3187                                 foreach (Expression Impl in member.Implements) {
3188                                         name = Impl.ToString();
3189                                         prefix = name.Substring(0, name.LastIndexOf("."));
3190                                         name = name.Substring(name.LastIndexOf(".") + 1);
3191
3192                                         if (accessor_name != null)
3193                                                 impl_method_name = accessor_name + "_" + name;
3194                                         else
3195                                                 impl_method_name = name;
3196
3197                                         Type current_iface_type = (Type) member.InterfaceTypes[++pos];
3198                                         IsImplementing = SearchBasesForAbstractMethods (
3199                                                 parent, current_iface_type, impl_method_name, 
3200                                                 ref implementing_list, ref implementing_iface);
3201
3202                                         if (IsImplementing == false) {
3203                                                 TypeContainer.Error_NotInterfaceMember (
3204                                                         Location, name, prefix);
3205                                                 return false;
3206                                         }
3207                                 }
3208                         } 
3209
3210                         //
3211                         // For implicit implementations, make sure we are public, for
3212                         // explicit implementations, make sure we are private.
3213                         //
3214                         //if (IsImplementing){
3215                                 //
3216                                 // Setting null inside this block will trigger a more
3217                                 // verbose error reporting for missing interface implementations
3218                                 //
3219                                 // The "candidate" function has been flagged already
3220                                 // but it wont get cleared
3221                                 //
3222                         /*      if (!member.IsExplicitImpl){
3223                                         //
3224                                         // We already catch different accessibility settings
3225                                         // so we just need to check that we are not private
3226                                         //
3227                                         if ((modifiers & Modifiers.PRIVATE) != 0)
3228                                                 implementing = null;
3229                                         
3230                                         //
3231                                         // Static is not allowed
3232                                         //
3233                                         if ((modifiers & Modifiers.STATIC) != 0)
3234                                                 implementing = null;
3235                                 } else {
3236                                         if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3237                                                 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3238                                                 implementing = null;
3239                                         }
3240                                 }*/
3241                         //}
3242                         
3243                         //
3244                         // If implementing is still valid, set flags
3245                         //
3246                         if (IsImplementing){
3247                                 //
3248                                 // When implementing interface methods, set NewSlot.
3249                                 //
3250                                 if (implementing_list != null && implementing_list.Count != 0)
3251                                                 flags |= MethodAttributes.NewSlot;
3252
3253                                 flags |=
3254                                         MethodAttributes.Virtual |
3255                                         MethodAttributes.HideBySig;
3256                         }
3257
3258                         //
3259                         // Create the MethodBuilder for the method
3260                         //
3261                         if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3262                                 if ((modifiers & Modifiers.STATIC) == 0) {
3263                                         Report.Error (601, Location,
3264                                                       "The DllImport attribute must be specified on " +
3265                                                       "a method marked 'static' and 'extern'.");
3266                                         return false;
3267                                 }
3268                                 
3269                                 EmitContext ec = new EmitContext (
3270                                         parent, Location, null, ReturnType, modifiers);
3271                                 
3272                                 builder = dllimport_attribute.DefinePInvokeMethod (
3273                                         ec, parent.TypeBuilder, method_name, flags,
3274                                         ReturnType, ParameterTypes);
3275                         } else
3276                                 builder = parent.TypeBuilder.DefineMethod (
3277                                         method_name, flags, CallingConventions,
3278                                         ReturnType, ParameterTypes);
3279
3280                         if (builder == null)
3281                                 return false;
3282
3283                         if (IsImplementing) {
3284                                 //
3285                                 // implement abstract methods from abstract classes
3286                                 //
3287                                 if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
3288                                         if (member is Indexer)
3289                                                 parent.Pending.ImplementIndexer (
3290                                                         (Type) parent.TypeBuilder.BaseType, 
3291                                                         builder, ReturnType,
3292                                                         ParameterTypes, true);
3293                                         else
3294                                                 parent.Pending.ImplementMethod (
3295                                                         (Type) parent.TypeBuilder.BaseType, 
3296                                                         name, ReturnType,
3297                                                         ParameterTypes, member.IsExplicitImpl);
3298                                 }
3299                                 
3300                                 //
3301                                 // implement abstract methods of interfaces
3302                                 //
3303                                 if (member.Implements != null)  {
3304                                         pos = 0;
3305                                         foreach (MethodInfo Impl in implementing_list)  {
3306                                                 if (member is Indexer)
3307                                                         parent.Pending.ImplementIndexer (
3308                                                                 (Type) implementing_iface[pos++],
3309                                                                 builder, ReturnType,
3310                                                                 ParameterTypes, true);
3311                                                 else
3312                                                         parent.Pending.ImplementMethod (
3313                                                                 (Type) implementing_iface[pos++],
3314                                                                 Impl.Name, ReturnType,
3315                                                                 ParameterTypes, member.IsExplicitImpl);
3316
3317                                                 parent.TypeBuilder.DefineMethodOverride (
3318                                                         builder, Impl);
3319                                         }
3320                                 }
3321                                 
3322                         }
3323
3324                         if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3325                                 Report.Error (111, Location,
3326                                               "Class `" + parent.Name +
3327                                               "' already contains a definition with the " +
3328                                               "same return value and parameter types as the " +
3329                                               "'get' method of property `" + member.Name + "'");
3330                                 return false;
3331                         }
3332
3333                         TypeManager.AddMethod (builder, this);
3334                         return true;
3335                 }
3336
3337                 //
3338                 // Emits the code
3339                 // 
3340                 public virtual void Emit (TypeContainer parent, Block block, object kind)
3341                 {
3342                         ILGenerator ig;
3343                         EmitContext ec;
3344
3345                         if ((flags & MethodAttributes.PinvokeImpl) == 0)
3346                                 ig = builder.GetILGenerator ();
3347                         else
3348                                 ig = null;
3349
3350                         ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3351
3352                         if (OptAttributes != null)
3353                                 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3354
3355                         if (member is MethodCore)
3356                                 ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
3357
3358                         //
3359                         // abstract or extern methods have no bodies
3360                         //
3361                         if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3362                                 if (block == null)
3363                                         return;
3364
3365                                 //
3366                                 // abstract or extern methods have no bodies.
3367                                 //
3368                                 if ((modifiers & Modifiers.ABSTRACT) != 0)
3369                                         Report.Error (
3370                                                 500, Location, "Abstract method `" +
3371                                                 TypeManager.MonoBASIC_Signature (builder) +
3372                                                 "' can not have a body");
3373
3374                                 if ((modifiers & Modifiers.EXTERN) != 0)
3375                                         Report.Error (
3376                                                 179, Location, "External method `" +
3377                                                 TypeManager.MonoBASIC_Signature (builder) +
3378                                                 "' can not have a body");
3379
3380                                 return;
3381                         }
3382
3383                         //
3384                         // Methods must have a body unless they're extern or abstract
3385                         //
3386                         if (block == null) {
3387                                 Report.Error (
3388                                         501, Location, "Method `" +
3389                                         TypeManager.MonoBASIC_Signature (builder) +
3390                                         "' must declare a body since it is not marked " +
3391                                         "abstract or extern");
3392                                 return;
3393                         }
3394
3395                         //
3396                         // Handle destructors specially
3397                         //
3398                         // FIXME: This code generates buggy code
3399                         //
3400                         if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3401                                 EmitDestructor (ec, block);
3402                         else {
3403                                 ISymbolWriter sw = CodeGen.SymbolWriter;
3404
3405                                 if ((sw != null) && !Location.IsNull (Location) &&
3406                                     !Location.IsNull (block.EndLocation)) {
3407                                         Location end = block.EndLocation;
3408                                         MethodToken token = MethodBuilder.GetToken ();
3409                                         sw.OpenMethod (new SymbolToken (token.Token));
3410                                         // Avoid error if we don't support debugging for the platform
3411                                         try {
3412                                                 sw.SetMethodSourceRange (Location.SymbolDocument,
3413                                                                          Location.Row, 0,
3414                                                                          end.SymbolDocument,
3415                                                                          end.Row, 0);
3416                                         } catch (Exception) {
3417                                         }
3418
3419                                         ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3420
3421                                         sw.CloseMethod ();
3422                                 } else
3423                                         ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3424                         }
3425                 }
3426
3427                 void EmitDestructor (EmitContext ec, Block block)
3428                 {
3429                         ILGenerator ig = ec.ig;
3430                         
3431                         Label finish = ig.DefineLabel ();
3432                         bool old_in_try = ec.InTry;
3433                         
3434                         ig.BeginExceptionBlock ();
3435                         ec.InTry = true;
3436                         ec.ReturnLabel = finish;
3437                         ec.HasReturnLabel = true;
3438                         ec.EmitTopBlock (block, null, Location);
3439                         ec.InTry = old_in_try;
3440                         
3441                         // ig.MarkLabel (finish);
3442                         bool old_in_finally = ec.InFinally;
3443                         ec.InFinally = true;
3444                         ig.BeginFinallyBlock ();
3445                         
3446                         if (ec.ContainerType.BaseType != null) {
3447                                 Expression member_lookup = Expression.MemberLookup (
3448                                         ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3449                                         MemberTypes.Method, Expression.AllBindingFlags, Location);
3450
3451                                 if (member_lookup != null){
3452                                         MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3453                                 
3454                                         ig.Emit (OpCodes.Ldarg_0);
3455                                         ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3456                                 }
3457                         }
3458                         ec.InFinally = old_in_finally;
3459                         
3460                         ig.EndExceptionBlock ();
3461                         //ig.MarkLabel (ec.ReturnLabel);
3462                         ig.Emit (OpCodes.Ret);
3463                 }
3464         }
3465
3466         abstract public class MemberBase : MemberCore {
3467                 public Expression Type;
3468                 public readonly Attributes OptAttributes;
3469                 public ArrayList Implements;
3470
3471                 protected MethodAttributes flags;
3472
3473                 //
3474                 // The "short" name of this property / indexer / event.  This is the
3475                 // name without the explicit interface.
3476                 //
3477                 public string ShortName;
3478
3479                 //
3480                 // The type of this property / indexer / event
3481                 //
3482                 public Type MemberType;
3483
3484                 //
3485                 // If true, this is an explicit interface implementation
3486                 //
3487                 public bool IsExplicitImpl = false;
3488
3489                 //
3490                 // The name of the interface we are explicitly implementing
3491                 //
3492                 public string ExplicitInterfaceName = null;
3493
3494                 //
3495                 // If true, the interface type we are explicitly implementing
3496                 //
3497                 public Type InterfaceType = null;
3498                 public ArrayList InterfaceTypes = null;
3499
3500                 //
3501                 // The method we're overriding if this is an override method.
3502                 //
3503                 protected MethodInfo parent_method = null;
3504                 public MethodInfo ParentMethod {
3505                         get {
3506                                 return parent_method;
3507                         }
3508                 }
3509
3510                 //
3511                 // The constructor is only exposed to our children
3512                 //
3513                 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3514                                       Attributes attrs, Location loc)
3515                         : base (name, loc)
3516                 {
3517                         Type = type;
3518                         ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PUBLIC, loc);
3519                         OptAttributes = attrs;
3520                 }
3521
3522                 protected virtual bool CheckBase (TypeContainer parent)
3523                 {
3524                         return true;
3525                 }
3526
3527                 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3528                 {
3529                         bool error = false;
3530
3531                         foreach (Type partype in parameters){
3532                                 if (partype.IsPointer && !UnsafeOK (parent))
3533                                         error = true;
3534
3535                                 if (parent.AsAccessible (partype, ModFlags))
3536                                         continue;
3537
3538                                 if (this is Indexer)
3539                                         Report.Error (55, Location,
3540                                                       "Inconsistent accessibility: parameter type `" +
3541                                                       TypeManager.MonoBASIC_Name (partype) + "' is less " +
3542                                                       "accessible than indexer `" + Name + "'");
3543                                 else
3544                                         Report.Error (51, Location,
3545                                                       "Inconsistent accessibility: parameter type `" +
3546                                                       TypeManager.MonoBASIC_Name (partype) + "' is less " +
3547                                                       "accessible than method `" + Name + "'");
3548                                 error = true;
3549                         }
3550
3551                         return !error;
3552                 }
3553
3554                 protected virtual bool DoDefine (TypeContainer parent)
3555                 {
3556                         if (Name == null)
3557                                 Name = "this";
3558
3559                         if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3560                                 return false;
3561
3562                         flags = Modifiers.MethodAttr (ModFlags);
3563
3564                         // Lookup Type, verify validity
3565                         MemberType = parent.ResolveType (Type, false, Location);
3566                         if (MemberType == null)
3567                                 return false;
3568
3569                         // check for whether the Interface is implemented by the class
3570                         if (Implements != null) {
3571                                 InterfaceTypes = new ArrayList ();
3572                                 foreach (Expression Impls in Implements) {
3573                                         string iname = Impls.ToString();
3574                                         iname = iname.Substring(0, iname.LastIndexOf("."));
3575                                         bool iface_found = false;
3576
3577                                         InterfaceType  = RootContext.LookupType (
3578                                                 parent, iname, false, Location);
3579                                         if (InterfaceType == null)
3580                                                 return false;
3581
3582                                         InterfaceTypes.Add (InterfaceType);
3583                                         Type[] tbases = parent.TypeBuilder.GetInterfaces();
3584 \r
3585                                     if (tbases.Length != 0)     {
3586                                                 ArrayList bases = new ArrayList();
3587                                                 TypeManager.ExpandAllInterfaces (tbases, ref bases);
3588
3589                                                 foreach (Type tbase in bases) {
3590                                                         string bname = tbase.Name;
3591                                                         if (bname.LastIndexOf(".") != -1)
3592                                                                 bname = bname.Substring(bname.LastIndexOf("."));
3593
3594                                                         if (bname == iname)     {
3595                                                                 iface_found = true;
3596                                                                 break;
3597                                                         }
3598                                                 }
3599                                         }
3600
3601                                         if (!iface_found) {
3602                                                 Report.Error (31035, Location,
3603                                                         "Class '" + parent.Name + "' doesn't implement interface '" + iname + "'");
3604                                                 return false;
3605                                         }
3606                                 }
3607                         }
3608
3609                         // verify accessibility
3610                         if (!parent.AsAccessible (MemberType, ModFlags)) {
3611                                 if (this is Property)
3612                                         Report.Error (53, Location,
3613                                                       "Inconsistent accessibility: property type `" +
3614                                                       TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3615                                                       "accessible than property `" + Name + "'");
3616                                 else if (this is Indexer)
3617                                         Report.Error (54, Location,
3618                                                       "Inconsistent accessibility: indexer return type `" +
3619                                                       TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3620                                                       "accessible than indexer `" + Name + "'");
3621                                 else if (this is Method)
3622                                         Report.Error (50, Location,
3623                                                       "Inconsistent accessibility: return type `" +
3624                                                       TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3625                                                       "accessible than method `" + Name + "'");
3626                                 else
3627                                         Report.Error (52, Location,
3628                                                       "Inconsistent accessibility: field type `" +
3629                                                       TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3630                                                       "accessible than field `" + Name + "'");
3631                                 return false;
3632                         }
3633
3634                         if (MemberType.IsPointer && !UnsafeOK (parent))
3635                                 return false;
3636                         
3637                         //
3638                         // Check for explicit interface implementation
3639                         //
3640                         if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)) {
3641                                 int pos = Name.LastIndexOf (".");
3642
3643                                 ExplicitInterfaceName = Name.Substring (0, pos);
3644                                 ShortName = Name.Substring (pos + 1);
3645                         } else
3646                                 ShortName = Name;
3647
3648                         return true;
3649                 }
3650         }
3651
3652         //
3653         // Fields and Events both generate FieldBuilders, we use this to share 
3654         // their common bits.  This is also used to flag usage of the field
3655         //
3656         abstract public class FieldBase : MemberBase {
3657                 public FieldBuilder  FieldBuilder;
3658                 public Status status;
3659
3660                 [Flags]
3661                 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3662
3663                 //
3664                 // The constructor is only exposed to our children
3665                 //
3666                 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3667                                      object init, Attributes attrs, Location loc)
3668                         : base (type, mod, allowed_mod, name, attrs, loc)
3669                 {
3670                         this.init = init;
3671                 }
3672
3673                 //
3674                 // Whether this field has an initializer.
3675                 //
3676                 public bool HasInitializer {
3677                         get {
3678                                 return init != null;
3679                         }
3680                 }
3681
3682                 // Private.
3683                 readonly Object init;
3684                 Expression init_expr;
3685                 bool init_expr_initialized = false;
3686
3687                 //
3688                 // Resolves and returns the field initializer.
3689                 //
3690                 public Expression GetInitializerExpression (EmitContext ec)
3691                 {
3692                         if (init_expr_initialized)
3693                                 return init_expr;
3694
3695                         Expression e;
3696                         if (init is Expression)
3697                                 e = (Expression) init;
3698                         else
3699                                 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3700
3701                         ec.IsFieldInitializer = true;
3702                         e = e.DoResolve (ec);
3703                         ec.IsFieldInitializer = false;
3704
3705                         init_expr = e;
3706                         init_expr_initialized = true;
3707
3708                         return init_expr;
3709                 }
3710
3711         }
3712
3713         //
3714         // The Field class is used to represents class/struct fields during parsing.
3715         //
3716         public class Field : FieldBase {
3717                 // <summary>
3718                 //   Modifiers allowed in a class declaration
3719                 // </summary>
3720                 const int AllowedModifiers =
3721                         Modifiers.SHADOWS |
3722                         Modifiers.PUBLIC |
3723                         Modifiers.PROTECTED |
3724                         Modifiers.INTERNAL |
3725                         Modifiers.PRIVATE |
3726                         Modifiers.STATIC |
3727                    //     Modifiers.VOLATILE |
3728                    //     Modifiers.UNSAFE |
3729                         Modifiers.READONLY;
3730
3731                 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3732                               Attributes attrs, Location loc)
3733                         : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3734                 {
3735                 }
3736
3737                 public override bool Define (TypeContainer parent)
3738                 {
3739                         Type t = parent.ResolveType (Type, false, Location);
3740                         
3741                         if (t == null)
3742                                 return false;
3743
3744                         if (!parent.AsAccessible (t, ModFlags)) {
3745                                 Report.Error (52, Location,
3746                                               "Inconsistent accessibility: field type `" +
3747                                               TypeManager.MonoBASIC_Name (t) + "' is less " +
3748                                               "accessible than field `" + Name + "'");
3749                                 return false;
3750                         }
3751
3752                         if (t.IsPointer && !UnsafeOK (parent))
3753                                 return false;
3754                                 
3755                         Type ptype = parent.TypeBuilder.BaseType;
3756
3757                         // ptype is only null for System.Object while compiling corlib.
3758                         if (ptype != null){
3759                                 MemberList list = TypeContainer.FindMembers (
3760                                         ptype, MemberTypes.Field,
3761                                         BindingFlags.Public |
3762                                         BindingFlags.Static | BindingFlags.Instance,
3763                                         System.Type.FilterName, Name);
3764
3765                                 if (RootContext.WarningLevel > 1){      
3766                                         if ((list.Count > 0) && ((ModFlags & Modifiers.SHADOWS) == 0)) \r
3767                                         {
3768                                                 Report.Warning (
3769                                                         40004, 2, Location, 
3770                                                         "Variable '" + Name + "' should be declared " +
3771                                                         "Shadows since the base type '" + ptype.Name + 
3772                                                         "' has a variable with same name");
3773
3774                                                 ModFlags |= Modifiers.SHADOWS;
3775                                         }
3776                                 }
3777                                 if (list.Count == 0)
3778                                         // if a member of module is not inherited from Object class
3779                                         // can not be declared protected
3780                                         if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
3781                                         Report.Error (30593, Location,
3782                                                 "'Variable' inside a 'Module' can not be " +
3783                                                 "declared as 'Protected'");
3784                         }
3785                         
3786                         if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
3787                                 Report.Error (30435, Location,
3788                                         "'Variable' inside a 'Structure' can not be " +
3789                                         "declared as 'Protected'");
3790
3791                         if ((ModFlags & Modifiers.VOLATILE) != 0){
3792                                 if (!t.IsClass){
3793                                         if (TypeManager.IsEnumType (t))
3794                                                 t = TypeManager.EnumToUnderlying (t);
3795
3796                                         if (!((t == TypeManager.bool_type) ||
3797                                               (t == TypeManager.sbyte_type) ||
3798                                               (t == TypeManager.byte_type) ||
3799                                               (t == TypeManager.short_type) ||    
3800                                               (t == TypeManager.ushort_type) ||
3801                                               (t == TypeManager.int32_type) ||    
3802                                               (t == TypeManager.uint32_type) ||    
3803                                               (t == TypeManager.char_type) ||    
3804                                               (t == TypeManager.float_type))){
3805                                                 Report.Error (
3806                                                         677, Location, parent.MakeName (Name) +
3807                                                         " A volatile field can not be of type `" +
3808                                                         TypeManager.MonoBASIC_Name (t) + "'");
3809                                                 return false;
3810                                         }
3811                                 }
3812                         }
3813
3814                         FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3815
3816                         if (parent is Struct && 
3817                             ((fa & FieldAttributes.Static) == 0) &&
3818                             t == parent.TypeBuilder &&
3819                             !TypeManager.IsBuiltinType (t)){
3820                                 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name + 
3821                                               "' causes a cycle in the structure layout");
3822                                 return false;
3823                         }
3824                         FieldBuilder = parent.TypeBuilder.DefineField (
3825                                 Name, t, Modifiers.FieldAttr (ModFlags));
3826
3827                         TypeManager.RegisterFieldBase (FieldBuilder, this);
3828                         return true;
3829                 }
3830
3831                 public void Emit (TypeContainer tc)
3832                 {
3833                         EmitContext ec = new EmitContext (tc, Location, null,
3834                                                           FieldBuilder.FieldType, ModFlags);
3835
3836                         Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
3837                 }
3838         }
3839
3840         //
3841         // `set' and `get' accessors are represented with an Accessor.
3842         // 
3843         public class Accessor {
3844                 //
3845                 // Null if the accessor is empty, or a Block if not
3846                 //
3847                 public Block Block;
3848                 public Attributes OptAttributes;
3849                 
3850                 public Accessor (Block b, Attributes attrs)
3851                 {
3852                         Block = b;
3853                         OptAttributes = attrs;
3854                 }
3855         }
3856
3857         //
3858         // Properties and Indexers both generate PropertyBuilders, we use this to share 
3859         // their common bits.
3860         //
3861         abstract public class PropertyBase : MethodCore {
3862                 public Accessor Get, Set;
3863                 public PropertyBuilder PropertyBuilder;
3864                 public MethodBuilder GetBuilder, SetBuilder;
3865                 public MethodData GetData, SetData;
3866
3867                 protected EmitContext ec;
3868
3869                 public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
3870                                      Parameters parameters, Accessor get_block, Accessor set_block,
3871                                      Attributes attrs, Location loc)
3872                         : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
3873                 {
3874                         Get = get_block;
3875                         Set = set_block;
3876                 }
3877
3878                 protected override bool DoDefine (TypeContainer parent)
3879                 {
3880                         if (!base.DoDefine (parent))
3881                                 return false;
3882
3883                         ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3884
3885                         return true;
3886                 }
3887
3888                 //
3889                 // Checks our base implementation if any
3890                 //
3891                 protected override bool CheckBase (TypeContainer container)
3892                 {
3893                         base.CheckBase (container);
3894                         
3895                         // Check whether arguments were correct.
3896                         if (!DoDefineParameters (container))
3897                                 return false;
3898
3899                         if (IsExplicitImpl)
3900                                 return true;
3901
3902                         MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
3903                         if (!IsOperator) \r
3904                         {
3905                                 MemberList mi_this;
3906
3907                                 mi_this = TypeContainer.FindMembers (
3908                                         container.TypeBuilder, MemberTypes.Property,
3909                                         BindingFlags.NonPublic | BindingFlags.Public |
3910                                         BindingFlags.Static | BindingFlags.Instance |
3911                                         BindingFlags.DeclaredOnly,
3912                                         MethodSignature.method_signature_filter, ms);
3913
3914                                 if (mi_this.Count > 0) {
3915                                         Report.Error (111, Location, "Class `" + container.Name + "' " +
3916                                                 "already defines a member called `" + Name + "' " +
3917                                                 "with the same parameter types");
3918                                         return false;
3919                                 }
3920                         }
3921
3922                         if (container is Interface)
3923                                 return true;
3924
3925                         Type retval = null;
3926                         if ((ModFlags & Modifiers.READONLY) != 0)
3927                                 retval = MemberType;
3928
3929                         string report_name;
3930                         MethodSignature base_ms;
3931                         if (this is Indexer) {
3932                                 string name, base_name;
3933
3934                                 report_name = "this";
3935                                 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
3936                                 ms = new MethodSignature (name, null, ParameterTypes);
3937                                 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
3938                                 base_ms = new MethodSignature (base_name, retval, ParameterTypes);
3939                         } else {
3940                                 report_name = Name;
3941                                 ms = base_ms = new MethodSignature (Name, retval, ParameterTypes);
3942                         }
3943
3944                         //
3945                         // Verify if the parent has a type with the same name, and then
3946                         // check whether we have to create a new slot for it or not.
3947                         //
3948                         Type ptype = container.TypeBuilder.BaseType;
3949
3950                         MemberInfo parent_member = null;
3951                         MemberList mi, mi_static, mi_instance;
3952
3953                         //
3954                         // Find properties with the same name on the base class
3955                         //
3956                         mi_static = TypeContainer.FindMembers (
3957                                 ptype, MemberTypes.Property,
3958                                 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3959                                 MethodSignature.inheritable_property_signature_filter, base_ms);
3960
3961                         mi_instance = TypeContainer.FindMembers (
3962                                 ptype, MemberTypes.Property,
3963                                 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3964                                 MethodSignature.inheritable_property_signature_filter,
3965                                 base_ms);
3966
3967
3968                         if (mi_instance.Count > 0)
3969                                 mi = mi_instance;
3970                         else if (mi_static.Count > 0)
3971                                 mi = mi_static;
3972                         else
3973                                 mi = null;
3974
3975                         if (mi != null && mi.Count > 0) \r
3976                                 parent_member = (PropertyInfo) mi [0];
3977 \r
3978                         if (parent_member is PropertyInfo) {
3979                                 PropertyInfo parent_property = (PropertyInfo)parent_member;
3980
3981                                 string name = parent_property.DeclaringType.Name + "." +
3982                                         parent_property.Name;
3983
3984                                 MethodInfo get, set, parent_method;
3985                                 get = parent_property.GetGetMethod (true);
3986                                 set = parent_property.GetSetMethod (true);
3987
3988                                 if (get != null)
3989                                         parent_method = get;
3990                                 else if (set != null)
3991                                         parent_method = set;
3992                                 else
3993                                         throw new Exception ("Internal error!");
3994
3995                                 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
3996                                         return false;
3997
3998                                 if ((ModFlags & Modifiers.NEW) == 0) {
3999                                         Type parent_type = TypeManager.TypeToCoreType (
4000                                                 parent_property.PropertyType);
4001
4002                                         if (parent_type != MemberType) {
4003                                                 Report.Error (
4004                                                         508, Location, container.MakeName (Name) + ": cannot " +
4005                                                         "change return type when overriding " +
4006                                                         "inherited member " + name);
4007                                                 return false;
4008                                         }
4009                                 }
4010                         } else if (parent_member == null) {
4011                                 /*if ((ModFlags & Modifiers.NEW) != 0)
4012                                         WarningNotHiding (container);
4013                                 */
4014                                 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
4015                                         if (this is Indexer)
4016                                                 Report.Error (115, Location,
4017                                                         container.MakeName (Name) +
4018                                                         " no suitable indexers found to override");
4019                                         else
4020                                                 Report.Error (115, Location,
4021                                                         container.MakeName (Name) +
4022                                                         " no suitable properties found to override");
4023                                         return false;
4024                                 }
4025
4026                                 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0) {
4027                                         if ((ModFlags & Modifiers.NONVIRTUAL) != 0)     {
4028                                                 Report.Error (31088, Location,
4029                                                         container.MakeName (Name) + " : Cannot " +
4030                                                         "be declared NotOverridable since this method is " +
4031                                                         "not maked as Overrides");
4032                                         }
4033                                 }
4034                                 // if a member of module is not inherited from Object class
4035                                 // can not be declared protected
4036                                 if ((container is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
4037                                         Report.Error (31066, Location,
4038                                                 "'Property' inside a 'Module' can not be declared as " +
4039                                                 "'Protected' or 'Protected Friend'");
4040                         }
4041                         return true;
4042                 }
4043
4044                 public virtual void Emit (TypeContainer tc)
4045                 {
4046                         //
4047                         // The PropertyBuilder can be null for explicit implementations, in that
4048                         // case, we do not actually emit the ".property", so there is nowhere to
4049                         // put the attribute
4050                         //
4051                         if (PropertyBuilder != null)
4052                                 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
4053 /*
4054                         if (GetData != null)
4055                                 GetData.Emit (tc, Get.Block, Get);
4056
4057                         if (SetData != null)
4058                                 SetData.Emit (tc, Set.Block, Set);
4059 */                              
4060                 }
4061         }
4062                         
4063         public class Property : PropertyBase {
4064                 const int AllowedModifiers =
4065                         Modifiers.NEW |
4066                         Modifiers.PUBLIC |
4067                         Modifiers.PROTECTED |
4068                         Modifiers.INTERNAL |
4069                         Modifiers.PRIVATE |
4070                         Modifiers.STATIC |
4071                         Modifiers.SEALED |
4072                         Modifiers.OVERRIDE |
4073                         Modifiers.ABSTRACT |
4074                     Modifiers.UNSAFE |
4075                         Modifiers.EXTERN |
4076                         Modifiers.VIRTUAL |
4077                         Modifiers.NONVIRTUAL |
4078                         Modifiers.DEFAULT |
4079                         Modifiers.READONLY |
4080                         Modifiers.WRITEONLY |
4081                         Modifiers.SHADOWS;
4082
4083                 string set_parameter_name;
4084                 Parameters get_params;
4085                 Parameters set_params;
4086                 
4087                 public Property (Expression type, string name, int mod_flags,
4088                                 Accessor get_block, Accessor set_block,
4089                                 Attributes attrs, Location loc, string set_name, 
4090                                 Parameters p_get, Parameters p_set, ArrayList impl_what)
4091                         : base (type, name, mod_flags, AllowedModifiers,
4092                                 p_set,
4093                                 get_block, set_block, attrs, loc)
4094                 {
4095                         set_parameter_name = set_name;
4096                         get_params = p_get;
4097                         set_params = p_set;
4098                         Implements = impl_what;
4099                 }               
4100                 
4101                 public Property (Expression type, string name, int mod_flags,
4102                                  Accessor get_block, Accessor set_block,
4103                                  Attributes attrs, Location loc)
4104                         : this (type, name, mod_flags, get_block, set_block, attrs, loc, 
4105                                         "Value", Parameters.EmptyReadOnlyParameters, Parameters.EmptyReadOnlyParameters, null)
4106                 {
4107                 }
4108
4109                 public override bool Define (TypeContainer parent)
4110                 {
4111                         Type [] g_parameters=null, s_parameters=null;
4112                         Parameter [] g_parms, s_parms;
4113                         InternalParameters g_ip=null, s_ip=null;
4114
4115                         if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
4116                                 Report.Error (30435, Location,
4117                                         "'Property' inside a 'Structure' can not be declared as " +
4118                                         "'Protected' or 'Protected Friend'");
4119
4120                         if (!DoDefine (parent))
4121                                 return false;
4122
4123                         if (!CheckBase (parent))
4124                                 return false;
4125
4126                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4127
4128                         if (Get == null) {
4129                                 if ((ModFlags & Modifiers.WRITEONLY) == 0)
4130                                         Report.Error (
4131                                                 30124, Location,
4132                                                 "Property without 'Get' accessor must have a 'WriteOnly' modifier");
4133                         }
4134                         else {
4135                                 if (get_params == Parameters.EmptyReadOnlyParameters) {
4136                                         g_parameters = TypeManager.NoTypes;
4137                                         g_ip = new InternalParameters (
4138                                                         parent, Parameters.EmptyReadOnlyParameters);
4139                                 } else  {
4140                                         g_parameters = new Type [get_params.FixedParameters.Length];
4141                                         for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
4142                                                 g_parameters[i] = get_params.FixedParameters[i].ParameterType;
4143                                         }
4144                                         g_parms = new Parameter [get_params.FixedParameters.Length];
4145                                         for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
4146                                                 Parameter tp = get_params.FixedParameters[i];
4147                                                 g_parms[i] = new Parameter (tp.TypeName, tp.Name,
4148                                                         Parameter.Modifier.NONE, null);
4149                                         }
4150                                         g_ip = new InternalParameters (
4151                                                 parent, new Parameters (g_parms, null, Location));
4152                                 }
4153
4154                                 GetData = new MethodData (this, "get", MemberType,
4155                                                           g_parameters, g_ip, CallingConventions.Standard,
4156                                                           Get.OptAttributes, ModFlags, flags, false);
4157
4158                                 if (!GetData.Define (parent))
4159                                         return false;
4160
4161                                 GetBuilder = GetData.MethodBuilder;
4162                         }
4163
4164                         if (Set == null) {
4165                                 if ((ModFlags & Modifiers.READONLY) == 0)
4166                                         Report.Error (
4167                                                 30124, Location,
4168                                                 "Property without 'Set' accessor must have a 'ReadOnly' modifier");
4169                                                 
4170                         }
4171                         else \r
4172                         {
4173                                 if (set_params == Parameters.EmptyReadOnlyParameters) 
4174                                 {
4175                                         s_parameters = new Type [1];
4176                                         s_parameters [0] = MemberType;
4177
4178                                         s_parms = new Parameter [1];
4179                                         s_parms [0] = new Parameter (Type, set_parameter_name, 
4180                                                 Parameter.Modifier.NONE, null);
4181                                 } else {
4182                                         s_parameters = new Type [set_params.FixedParameters.Length];
4183                                         for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
4184                                                 s_parameters[i] = set_params.FixedParameters[i].ParameterType;
4185                                         }
4186
4187                                         s_parms = new Parameter [set_params.FixedParameters.Length];
4188                                         for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
4189                                                 Parameter tp = set_params.FixedParameters[i];
4190                                                 s_parms[i] = new Parameter (tp.TypeName, tp.Name,
4191                                                         Parameter.Modifier.NONE, null);
4192                                         }
4193                                 }
4194
4195                                 s_ip = new InternalParameters (
4196                                         parent, new Parameters (s_parms, null, Location));
4197
4198                                 SetData = new MethodData (this, "set", TypeManager.void_type,
4199                                         s_parameters, s_ip, CallingConventions.Standard,
4200                                         Set.OptAttributes, ModFlags, flags, false);
4201
4202                                 if (!SetData.Define (parent))
4203                                         return false;
4204
4205                                 SetBuilder = SetData.MethodBuilder;
4206                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, 
4207                                         set_parameter_name); 
4208                         }
4209
4210                         // FIXME - PropertyAttributes.HasDefault ?
4211                         
4212                         PropertyAttributes prop_attr =
4213                         PropertyAttributes.RTSpecialName |
4214                         PropertyAttributes.SpecialName;
4215
4216                         if (!IsExplicitImpl){
4217                                 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4218                                         Name, prop_attr, MemberType, null);
4219                                 
4220                                 PropertyBuilder.SetGetMethod (GetBuilder);
4221                                 PropertyBuilder.SetSetMethod (SetBuilder);
4222
4223                                 //
4224                                 // HACK for the reasons exposed above
4225                                 //
4226                                 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4227                                         Report.Error (
4228                                                 111, Location,
4229                                                 "Class `" + parent.Name +
4230                                                 "' already contains a definition for the property `" +
4231                                                 Name + "'");
4232                                         return false;
4233                                 }
4234                         }
4235                         return true;
4236                 }
4237
4238                 public override void Emit (TypeContainer tc)
4239                 {
4240                         base.Emit (tc);
4241                         
4242                         if (GetData != null) 
4243                         {
4244                                 Parameters = get_params;
4245                                 GetData.Emit (tc, Get.Block, Get);
4246                         }
4247
4248                         if (SetData != null) 
4249                         {
4250                                 Parameters = set_params;
4251                                 SetData.Emit (tc, Set.Block, Set);
4252                         }
4253                                 
4254                 }
4255         }
4256
4257         /// </summary>
4258         ///  Gigantic workaround  for lameness in SRE follows :
4259         ///  This class derives from EventInfo and attempts to basically
4260         ///  wrap around the EventBuilder so that FindMembers can quickly
4261         ///  return this in it search for members
4262         /// </summary>
4263         public class MyEventBuilder : EventInfo {
4264                 
4265                 //
4266                 // We use this to "point" to our Builder which is
4267                 // not really a MemberInfo
4268                 //
4269                 EventBuilder MyBuilder;
4270                 
4271                 //
4272                 // We "catch" and wrap these methods
4273                 //
4274                 MethodInfo raise, remove, add;
4275
4276                 EventAttributes attributes;
4277                 Type declaring_type, reflected_type, event_type;
4278                 string name;
4279
4280                 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4281                 {
4282                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4283
4284                         // And now store the values in our own fields.
4285                         
4286                         declaring_type = type_builder;
4287
4288                         reflected_type = type_builder;
4289                         
4290                         attributes = event_attr;
4291                         this.name = name;
4292                         this.event_type = event_type;
4293                 }
4294                 
4295                 //
4296                 // Methods that you have to override.  Note that you only need 
4297                 // to "implement" the variants that take the argument (those are
4298                 // the "abstract" methods, the others (GetAddMethod()) are 
4299                 // regular.
4300                 //
4301                 public override MethodInfo GetAddMethod (bool nonPublic)
4302                 {
4303                         return add;
4304                 }
4305                 
4306                 public override MethodInfo GetRemoveMethod (bool nonPublic)
4307                 {
4308                         return remove;
4309                 }
4310                 
4311                 public override MethodInfo GetRaiseMethod (bool nonPublic)
4312                 {
4313                         return raise;
4314                 }
4315                 
4316                 //
4317                 // These methods make "MyEventInfo" look like a Builder
4318                 //
4319                 public void SetRaiseMethod (MethodBuilder raiseMethod)
4320                 {
4321                         raise = raiseMethod;
4322                         MyBuilder.SetRaiseMethod (raiseMethod);
4323                 }
4324
4325                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4326                 {
4327                         remove = removeMethod;
4328                         MyBuilder.SetRemoveOnMethod (removeMethod);
4329                 }
4330
4331                 public void SetAddOnMethod (MethodBuilder addMethod)
4332                 {
4333                         add = addMethod;
4334                         MyBuilder.SetAddOnMethod (addMethod);
4335                 }
4336
4337                 public void SetCustomAttribute (CustomAttributeBuilder cb)
4338                 {
4339                         MyBuilder.SetCustomAttribute (cb);
4340                 }
4341                 
4342                 public override object [] GetCustomAttributes (bool inherit)
4343                 {
4344                         // FIXME : There's nothing which can be seemingly done here because
4345                         // we have no way of getting at the custom attribute objects of the
4346                         // EventBuilder !
4347                         return null;
4348                 }
4349
4350                 public override object [] GetCustomAttributes (Type t, bool inherit)
4351                 {
4352                         // FIXME : Same here !
4353                         return null;
4354                 }
4355
4356                 public override bool IsDefined (Type t, bool b)
4357                 {
4358                         return true;
4359                 }
4360
4361                 public override EventAttributes Attributes {
4362                         get {
4363                                 return attributes;
4364                         }
4365                 }
4366
4367                 public override string Name {
4368                         get {
4369                                 return name;
4370                         }
4371                 }
4372
4373                 public override Type DeclaringType {
4374                         get {
4375                                 return declaring_type;
4376                         }
4377                 }
4378
4379                 public override Type ReflectedType {
4380                         get {
4381                                 return reflected_type;
4382                         }
4383                 }
4384
4385                 public Type EventType {
4386                         get {
4387                                 return event_type;
4388                         }
4389                 }
4390         }
4391         
4392         public class Event : FieldBase {
4393                 const int AllowedModifiers =
4394                         Modifiers.NEW |
4395                         Modifiers.PUBLIC |
4396                         Modifiers.PROTECTED |
4397                         Modifiers.INTERNAL |
4398                         Modifiers.PRIVATE |
4399                         Modifiers.STATIC |
4400                         Modifiers.VIRTUAL |
4401                         Modifiers.SEALED |
4402                         Modifiers.OVERRIDE |
4403                         Modifiers.UNSAFE |
4404                         Modifiers.ABSTRACT;
4405
4406                 public readonly Accessor  Add;
4407                 public readonly Accessor  Remove;
4408                 public MyEventBuilder     EventBuilder;
4409
4410                 MethodBuilder AddBuilder, RemoveBuilder;
4411                 MethodData AddData, RemoveData;
4412                 
4413                 public Event (Expression type, string name, Object init, int mod, Accessor add,
4414                               Accessor remove, Attributes attrs, Location loc)
4415                         : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4416                 {
4417                         Add = add;
4418                         Remove = remove;
4419                         Implements = null;
4420                 }
4421
4422                 public Event (Expression type, string name, Object init, int mod, Accessor add,
4423                         Accessor remove, Attributes attrs, ArrayList impl_what, Location loc)
4424                         : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4425                 {
4426                         Add = add;
4427                         Remove = remove;
4428                         Implements = impl_what;
4429                 }
4430                 
4431
4432                 public override bool Define (TypeContainer parent)
4433                 {
4434                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4435
4436                         if (!DoDefine (parent))
4437                                 return false;
4438
4439                         if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4440                                 Report.Error (31044, Location, "'" + parent.Name + "." + Name +
4441                                               "' : event must be of a delegate type");
4442                                 return false;
4443                         }
4444
4445                         Type [] parameter_types = new Type [1];
4446                         parameter_types [0] = MemberType;
4447
4448                         Parameter [] parms = new Parameter [1];
4449                         parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4450                         InternalParameters ip = new InternalParameters (
4451                                 parent, new Parameters (parms, null, Location)); 
4452
4453                         if (!CheckBase (parent))
4454                                 return false;
4455
4456                         //
4457                         // Now define the accessors
4458                         //
4459                         AddData = new MethodData (this, "add", TypeManager.void_type,
4460                                                   parameter_types, ip, CallingConventions.Standard,
4461                                                   (Add != null) ? Add.OptAttributes : null,
4462                                                   ModFlags, flags, false);
4463
4464                         if (!AddData.Define (parent))
4465                                 return false;
4466
4467                         AddBuilder = AddData.MethodBuilder;
4468                         AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4469
4470                         RemoveData = new MethodData (this, "remove", TypeManager.void_type,
4471                                                      parameter_types, ip, CallingConventions.Standard,
4472                                                      (Remove != null) ? Remove.OptAttributes : null,
4473                                                      ModFlags, flags, false);
4474
4475                         if (!RemoveData.Define (parent))
4476                                 return false;
4477
4478                         RemoveBuilder = RemoveData.MethodBuilder;
4479                         RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name);
4480
4481                         if (!IsExplicitImpl){
4482                                 EventBuilder = new MyEventBuilder (
4483                                         parent.TypeBuilder, Name, e_attr, MemberType);
4484                                         
4485                                 if (Add == null && Remove == null) {
4486                                         FieldBuilder = parent.TypeBuilder.DefineField (
4487                                                 Name, MemberType,
4488                                                 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4489                                         TypeManager.RegisterPrivateFieldOfEvent (
4490                                                 (EventInfo) EventBuilder, FieldBuilder);
4491                                         TypeManager.RegisterFieldBase (FieldBuilder, this);
4492                                 }
4493                         
4494                                 EventBuilder.SetAddOnMethod (AddBuilder);
4495                                 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4496
4497                                 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4498                                         Report.Error (111, Location,
4499                                                       "Class `" + parent.Name +
4500                                                       "' already contains a definition for the event `" +
4501                                                       Name + "'");
4502                                         return false;
4503                                 }
4504                         }
4505                         
4506                         return true;
4507                 }
4508
4509                 void EmitDefaultMethod (EmitContext ec, bool is_add)
4510                 {
4511                         ILGenerator ig = ec.ig;
4512                         MethodInfo method = null;
4513                         
4514                         if (is_add)
4515                                 method = TypeManager.delegate_combine_delegate_delegate;
4516                         else
4517                                 method = TypeManager.delegate_remove_delegate_delegate;
4518
4519                         if ((ModFlags & Modifiers.STATIC) != 0) {
4520                                 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4521                                 ig.Emit (OpCodes.Ldarg_0);
4522                                 ig.Emit (OpCodes.Call, method);
4523                                 ig.Emit (OpCodes.Castclass, MemberType);
4524                                 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4525                         } else {
4526                                 ig.Emit (OpCodes.Ldarg_0);
4527                                 ig.Emit (OpCodes.Ldarg_0);
4528                                 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4529                                 ig.Emit (OpCodes.Ldarg_1);
4530                                 ig.Emit (OpCodes.Call, method);
4531                                 ig.Emit (OpCodes.Castclass, MemberType);
4532                                 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4533                         }
4534                         ig.Emit (OpCodes.Ret);
4535                 }
4536
4537                 public void Emit (TypeContainer tc)
4538                 {
4539                         EmitContext ec;
4540
4541                         ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4542                         Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
4543
4544                         if (Add != null)
4545                                 AddData.Emit (tc, Add.Block, Add);
4546                         else {
4547                                 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4548                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4549                                 EmitDefaultMethod (ec, true);
4550                         }
4551
4552                         if (Remove != null)
4553                                 RemoveData.Emit (tc, Remove.Block, Remove);
4554                         else {
4555                                 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4556                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4557                                 EmitDefaultMethod (ec, false);
4558                         }
4559                 }
4560                 
4561         }
4562
4563         //
4564         // FIXME: This does not handle:
4565         //
4566         //   int INTERFACENAME [ args ]
4567         //   Does not 
4568         //
4569         // Only:
4570         // 
4571         // int this [ args ]
4572  
4573         public class Indexer : PropertyBase {
4574
4575                 const int AllowedModifiers =
4576                         Modifiers.NEW |
4577                         Modifiers.PUBLIC |
4578                         Modifiers.PROTECTED |
4579                         Modifiers.INTERNAL |
4580                         Modifiers.PRIVATE |
4581                         Modifiers.VIRTUAL |
4582                         Modifiers.SEALED |
4583                         Modifiers.OVERRIDE |
4584                         Modifiers.UNSAFE |
4585                         Modifiers.EXTERN |
4586                         Modifiers.ABSTRACT;
4587
4588                 public string IndexerName;
4589                 public string InterfaceIndexerName;
4590
4591                 //
4592                 // Are we implementing an interface ?
4593                 //
4594                 bool IsImplementing = false;
4595                 
4596                 public Indexer (Expression type, string int_type, int flags, Parameters parameters,
4597                                 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
4598                         : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4599                                 attrs, loc)
4600                 {
4601                         ExplicitInterfaceName = int_type;
4602                 }
4603
4604                 public override bool Define (TypeContainer parent)
4605                 {
4606                         PropertyAttributes prop_attr =
4607                                 PropertyAttributes.RTSpecialName |
4608                                 PropertyAttributes.SpecialName;
4609                         
4610                         if (!DoDefine (parent))
4611                                 return false;
4612
4613                         IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4614                         if (IndexerName == null)
4615                                 IndexerName = "Item";
4616                         else if (IsExplicitImpl)
4617                                 Report.Error (592, Location,
4618                                               "Attribute 'IndexerName' is not valid on this declaration " +
4619                                               "type. It is valid on `property' declarations only.");
4620
4621                         ShortName = IndexerName;
4622                         if (IsExplicitImpl) {
4623                                 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4624                                 Name = InterfaceType.FullName + "." + IndexerName;
4625                         } else {
4626                                 InterfaceIndexerName = IndexerName;
4627                                 Name = ShortName;
4628                         }
4629
4630                         if (!CheckBase (parent))
4631                                 return false;
4632
4633                         if (Get != null){
4634                                 InternalParameters ip = new InternalParameters (parent, Parameters);
4635
4636                                 GetData = new MethodData (this, "get", MemberType,
4637                                                           ParameterTypes, ip, CallingConventions.Standard,
4638                                                           Get.OptAttributes, ModFlags, flags, false);
4639
4640                                 if (!GetData.Define (parent))
4641                                         return false;
4642
4643                                 GetBuilder = GetData.MethodBuilder;
4644                         }
4645                         
4646                         if (Set != null){
4647                                 int top = ParameterTypes.Length;
4648                                 Type [] set_pars = new Type [top + 1];
4649                                 ParameterTypes.CopyTo (set_pars, 0);
4650                                 set_pars [top] = MemberType;
4651
4652                                 Parameter [] fixed_parms = Parameters.FixedParameters;
4653
4654                                 if (fixed_parms == null){
4655                                         throw new Exception ("We currently do not support only array arguments in an indexer");
4656                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4657                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4658                                         //
4659                                         // Here is the problem: the `value' parameter has
4660                                         // to come *after* the array parameter in the declaration
4661                                         // like this:
4662                                         // X (object [] x, Type value)
4663                                         // .param [0]
4664                                         //
4665                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4666                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4667                                         
4668                                 }
4669                                 
4670                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4671
4672
4673                                 fixed_parms.CopyTo (tmp, 0);
4674                                 tmp [fixed_parms.Length] = new Parameter (
4675                                         Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4676
4677                                 Parameters set_formal_params = new Parameters (tmp, null, Location);
4678                                 
4679                                 InternalParameters ip = new InternalParameters (parent, set_formal_params);
4680
4681                                 SetData = new MethodData (this, "set", TypeManager.void_type,
4682                                                           set_pars, ip, CallingConventions.Standard,
4683                                                           Set.OptAttributes, ModFlags, flags, false);
4684
4685                                 if (!SetData.Define (parent))
4686                                         return false;
4687
4688                                 SetBuilder = SetData.MethodBuilder;
4689                         }
4690
4691                         //
4692                         // Now name the parameters
4693                         //
4694                         Parameter [] p = Parameters.FixedParameters;
4695                         if (p != null) {
4696                                 int i;
4697                                 
4698                                 for (i = 0; i < p.Length; ++i) {
4699                                         if (Get != null)
4700                                                 GetBuilder.DefineParameter (
4701                                                         i + 1, p [i].Attributes, p [i].Name);
4702
4703                                         if (Set != null)
4704                                                 SetBuilder.DefineParameter (
4705                                                         i + 1, p [i].Attributes, p [i].Name);
4706                                 }
4707                                 
4708
4709                                 if (Set != null)
4710                                         SetBuilder.DefineParameter (
4711                                                 i + 1, ParameterAttributes.None, /* was "value" */ this.Name);
4712                                         
4713                                 if (i != ParameterTypes.Length) {
4714                                         Parameter array_param = Parameters.ArrayParameter;
4715                                         SetBuilder.DefineParameter (
4716                                                 i + 1, array_param.Attributes, array_param.Name);
4717                                 }
4718                         }
4719
4720                         if (GetData != null)
4721                                 IsImplementing = GetData.IsImplementing;
4722                         else if (SetData != null)
4723                                 IsImplementing = SetData.IsImplementing;
4724
4725                         //
4726                         // Define the PropertyBuilder if one of the following conditions are met:
4727                         // a) we're not implementing an interface indexer.
4728                         // b) the indexer has a different IndexerName and this is no
4729                         //    explicit interface implementation.
4730                         //
4731                         if (!IsExplicitImpl) {
4732                                 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4733                                         IndexerName, prop_attr, MemberType, ParameterTypes);
4734
4735                                 if (GetData != null)
4736                                         PropertyBuilder.SetGetMethod (GetBuilder);
4737
4738                                 if (SetData != null)
4739                                         PropertyBuilder.SetSetMethod (SetBuilder);
4740                                 
4741                                 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4742                                                              ParameterTypes);
4743                         }
4744
4745                         return true;
4746                 }
4747         }
4748
4749         public class Operator : MemberCore {
4750
4751                 const int AllowedModifiers =
4752                         Modifiers.PUBLIC |
4753                         Modifiers.UNSAFE |
4754                         Modifiers.EXTERN |
4755                         Modifiers.STATIC;
4756
4757                 const int RequiredModifiers =
4758                         Modifiers.PUBLIC |
4759                         Modifiers.STATIC;
4760
4761                 public enum OpType : byte {
4762
4763                         // Unary operators
4764                         LogicalNot,
4765                         OnesComplement,
4766                         Increment,
4767                         Decrement,
4768                         True,
4769                         False,
4770
4771                         // Unary and Binary operators
4772                         Addition,
4773                         Subtraction,
4774
4775                         UnaryPlus,
4776                         UnaryNegation,
4777                         
4778                         // Binary operators
4779                         Multiply,
4780                         Division,
4781                         Modulus,
4782                         BitwiseAnd,
4783                         BitwiseOr,
4784                         ExclusiveOr,
4785                         LeftShift,
4786                         RightShift,
4787                         Equality,
4788                         Inequality,
4789                         GreaterThan,
4790                         LessThan,
4791                         GreaterThanOrEqual,
4792                         LessThanOrEqual,
4793
4794                         // Implicit and Explicit
4795                         Implicit,
4796                         Explicit
4797                 };
4798
4799                 public readonly OpType OperatorType;
4800                 public readonly Expression ReturnType;
4801                 public readonly Expression FirstArgType, SecondArgType;
4802                 public readonly string FirstArgName, SecondArgName;
4803                 public readonly Block  Block;
4804                 public Attributes      OptAttributes;
4805                 public MethodBuilder   OperatorMethodBuilder;
4806                 
4807                 public string MethodName;
4808                 public Method OperatorMethod;
4809
4810                 public Operator (OpType type, Expression ret_type, int flags,
4811                                  Expression arg1type, string arg1name,
4812                                  Expression arg2type, string arg2name,
4813                                  Block block, Attributes attrs, Location loc)
4814                         : base ("", loc)
4815                 {
4816                         OperatorType = type;
4817                         ReturnType = ret_type;
4818                         ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
4819                         FirstArgType = arg1type;
4820                         FirstArgName = arg1name;
4821                         SecondArgType = arg2type;
4822                         SecondArgName = arg2name;
4823                         Block = block;
4824                         OptAttributes = attrs;
4825                 }
4826
4827                 string Prototype (TypeContainer parent)
4828                 {
4829                         return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4830                                 SecondArgType + ")";
4831                 }
4832                 
4833                 public override bool Define (TypeContainer parent)
4834                 {
4835                         int length = 1;
4836                         MethodName = "op_" + OperatorType;
4837                         
4838                         if (SecondArgType != null)
4839                                 length = 2;
4840                         
4841                         Parameter [] param_list = new Parameter [length];
4842
4843                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4844                                 Report.Error (
4845                                         558, Location, 
4846                                         "User defined operators `" +
4847                                         Prototype (parent) +
4848                                         "' must be declared static and public");
4849                                 return false;
4850                         }
4851
4852                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
4853                                                        Parameter.Modifier.NONE, null);
4854                         if (SecondArgType != null)
4855                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4856                                                                Parameter.Modifier.NONE, null);
4857                         
4858                         OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4859                                                      new Parameters (param_list, null, Location),
4860                                                      OptAttributes, Mono.MonoBASIC.Location.Null);
4861
4862                         OperatorMethod.IsOperator = true;                       
4863                         OperatorMethod.Define (parent);
4864
4865                         if (OperatorMethod.MethodBuilder == null)
4866                                 return false;
4867                         
4868                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4869
4870                         Type [] param_types = OperatorMethod.ParameterTypes;
4871                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
4872                         Type return_type = OperatorMethod.GetReturnType ();
4873                         Type first_arg_type = param_types [0];
4874
4875                         // Rules for conversion operators
4876                         
4877                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4878                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
4879                                         Report.Error (
4880                                                 555, Location,
4881                                                 "User-defined conversion cannot take an object of the " +
4882                                                 "enclosing type and convert to an object of the enclosing" +
4883                                                 " type");
4884                                         return false;
4885                                 }
4886                                 
4887                                 if (first_arg_type != declaring_type && return_type != declaring_type){
4888                                         Report.Error (
4889                                                 556, Location, 
4890                                                 "User-defined conversion must convert to or from the " +
4891                                                 "enclosing type");
4892                                         return false;
4893                                 }
4894                                 
4895                                 if (first_arg_type == TypeManager.object_type ||
4896                                     return_type == TypeManager.object_type){
4897                                         Report.Error (
4898                                                 -8, Location,
4899                                                 "User-defined conversion cannot convert to or from " +
4900                                                 "object type");
4901                                         return false;
4902                                 }
4903
4904                                 if (first_arg_type.IsInterface || return_type.IsInterface){
4905                                         Report.Error (
4906                                                 552, Location,
4907                                                 "User-defined conversion cannot convert to or from an " +
4908                                                 "interface type");
4909                                         return false;
4910                                 }
4911                                 
4912                                 if (first_arg_type.IsSubclassOf (return_type) ||
4913                                     return_type.IsSubclassOf (first_arg_type)){
4914                                         Report.Error (
4915                                                 -10, Location,
4916                                                 "User-defined conversion cannot convert between types " +
4917                                                 "that derive from each other");
4918                                         return false;
4919                                 }
4920                         } else if (SecondArgType == null) {
4921                                 // Checks for Unary operators
4922                                 
4923                                 if (first_arg_type != declaring_type){
4924                                         Report.Error (
4925                                                 562, Location,
4926                                                 "The parameter of a unary operator must be the " +
4927                                                 "containing type");
4928                                         return false;
4929                                 }
4930                                 
4931                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4932                                         if (return_type != declaring_type){
4933                                                 Report.Error (
4934                                                         559, Location,
4935                                                         "The parameter and return type for ++ and -- " +
4936                                                         "must be the containing type");
4937                                                 return false;
4938                                         }
4939                                         
4940                                 }
4941                                 
4942                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4943                                         if (return_type != TypeManager.bool_type){
4944                                                 Report.Error (
4945                                                         215, Location,
4946                                                         "The return type of operator True or False " +
4947                                                         "must be bool");
4948                                                 return false;
4949                                         }
4950                                 }
4951                                 
4952                         } else {
4953                                 // Checks for Binary operators
4954                                 
4955                                 if (first_arg_type != declaring_type &&
4956                                     param_types [1] != declaring_type){
4957                                         Report.Error (
4958                                                 563, Location,
4959                                                 "One of the parameters of a binary operator must " +
4960                                                 "be the containing type");
4961                                         return false;
4962                                 }
4963                         }
4964
4965                         return true;
4966                 }
4967                 
4968                 public void Emit (TypeContainer parent)
4969                 {
4970                         EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4971                         Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4972
4973                         //
4974                         // abstract or extern methods have no bodies
4975                         //
4976                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4977                                 return;
4978                         
4979                         OperatorMethod.Block = Block;
4980                         OperatorMethod.Emit (parent);
4981                 }
4982
4983                 public static string GetName (OpType ot)
4984                 {
4985                         switch (ot){
4986                         case OpType.LogicalNot:
4987                                 return "!";
4988                         case OpType.OnesComplement:
4989                                 return "~";
4990                         case OpType.Increment:
4991                                 return "++";
4992                         case OpType.Decrement:
4993                                 return "--";
4994                         case OpType.True:
4995                                 return "true";
4996                         case OpType.False:
4997                                 return "false";
4998                         case OpType.Addition:
4999                                 return "+";
5000                         case OpType.Subtraction:
5001                                 return "-";
5002                         case OpType.UnaryPlus:
5003                                 return "+";
5004                         case OpType.UnaryNegation:
5005                                 return "-";
5006                         case OpType.Multiply:
5007                                 return "*";
5008                         case OpType.Division:
5009                                 return "/";
5010                         case OpType.Modulus:
5011                                 return "%";
5012                         case OpType.BitwiseAnd:
5013                                 return "&";
5014                         case OpType.BitwiseOr:
5015                                 return "|";
5016                         case OpType.ExclusiveOr:
5017                                 return "^";
5018                         case OpType.LeftShift:
5019                                 return "<<";
5020                         case OpType.RightShift:
5021                                 return ">>";
5022                         case OpType.Equality:
5023                                 return "==";
5024                         case OpType.Inequality:
5025                                 return "!=";
5026                         case OpType.GreaterThan:
5027                                 return ">";
5028                         case OpType.LessThan:
5029                                 return "<";
5030                         case OpType.GreaterThanOrEqual:
5031                                 return ">=";
5032                         case OpType.LessThanOrEqual:
5033                                 return "<=";
5034                         case OpType.Implicit:
5035                                 return "implicit";
5036                         case OpType.Explicit:
5037                                 return "explicit";
5038                         default: return "";
5039                         }
5040                 }
5041                 
5042                 public override string ToString ()
5043                 {
5044                         Type return_type = OperatorMethod.GetReturnType();
5045                         Type [] param_types = OperatorMethod.ParameterTypes;
5046                         
5047                         if (SecondArgType == null)
5048                                 return String.Format (
5049                                         "{0} operator {1}({2})",
5050                                         TypeManager.MonoBASIC_Name (return_type),
5051                                         GetName (OperatorType),
5052                                         param_types [0]);
5053                         else
5054                                 return String.Format (
5055                                         "{0} operator {1}({2}, {3})",
5056                                         TypeManager.MonoBASIC_Name (return_type),
5057                                         GetName (OperatorType),
5058                                         param_types [0], param_types [1]);
5059                 }
5060         }
5061
5062         //
5063         // This is used to compare method signatures
5064         //
5065         struct MethodSignature {
5066                 public string Name;
5067                 public Type RetType;
5068                 public Type [] Parameters;
5069                 
5070                 /// <summary>
5071                 ///    This delegate is used to extract methods which have the
5072                 ///    same signature as the argument
5073                 /// </summary>
5074                 public static MemberFilter method_signature_filter;
5075
5076                 /// <summary>
5077                 ///    This delegate is used to extract methods which have the
5078                 ///    same signature as the argument except for the name
5079                 /// </summary>
5080                 public static MemberFilter method_signature_noname_filter;
5081
5082                 /// <summary>
5083                 ///   This delegate is used to extract inheritable methods which
5084                 ///   have the same signature as the argument.  By inheritable,
5085                 ///   this means that we have permissions to override the method
5086                 ///   from the current assembly and class
5087                 /// </summary>
5088                 public static MemberFilter inheritable_method_signature_filter;
5089
5090                 /// <summary>
5091                 ///   This delegate is used to extract inheritable methods which
5092                 ///   have the same signature as the argument.  By inheritable,
5093                 ///   this means that we have permissions to override the method
5094                 ///   from the current assembly and class
5095                 /// </summary>
5096                 public static MemberFilter inheritable_property_signature_filter;
5097                 
5098                 static MethodSignature ()
5099                 {
5100                         method_signature_filter = new MemberFilter (MemberSignatureCompare);
5101                         method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName);
5102                         inheritable_method_signature_filter = new MemberFilter (
5103                                 InheritableMemberSignatureCompare);
5104                         inheritable_property_signature_filter = new MemberFilter (
5105                                 InheritablePropertySignatureCompare);
5106                 }
5107                 
5108                 public MethodSignature (string name, Type ret_type, Type [] parameters)
5109                 {
5110                         Name = name;
5111                         RetType = ret_type;
5112
5113                         if (parameters == null)
5114                                 Parameters = TypeManager.NoTypes;
5115                         else
5116                                 Parameters = parameters;
5117                 }
5118                 
5119                 public override int GetHashCode ()
5120                 {
5121                         return Name.GetHashCode ();
5122                 }
5123
5124                 public override bool Equals (Object o)
5125                 {
5126                         MethodSignature other = (MethodSignature) o;
5127
5128                         if (other.Name != Name)
5129                                 return false;
5130
5131                         if (other.RetType != RetType)
5132                                 return false;
5133                         
5134                         if (Parameters == null){
5135                                 if (other.Parameters == null)
5136                                         return true;
5137                                 return false;
5138                         }
5139
5140                         if (other.Parameters == null)
5141                                 return false;
5142                         
5143                         int c = Parameters.Length;
5144                         if (other.Parameters.Length != c)
5145                                 return false;
5146
5147                         for (int i = 0; i < c; i++)
5148                                 if (other.Parameters [i] != Parameters [i])
5149                                         return false;
5150
5151                         return true;
5152                 }
5153
5154                 static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria)
5155                 {
5156                         return MemberSignatureCompare (m, filter_criteria, false);
5157                 }
5158
5159                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
5160                 {
5161                         return MemberSignatureCompare (m, filter_criteria, true);
5162                 }
5163
5164                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name)
5165                 {
5166                         MethodSignature sig = (MethodSignature) filter_criteria;
5167
5168                         if (use_name && (m.Name != sig.Name))
5169                                 return false;
5170
5171                         Type ReturnType;
5172                         MethodInfo mi = m as MethodInfo;
5173                         PropertyInfo pi = m as PropertyInfo;
5174
5175                         if (mi != null)
5176                                 ReturnType = mi.ReturnType;
5177                         else if (pi != null)
5178                                 ReturnType = pi.PropertyType;
5179                         else
5180                                 return false;
5181
5182                         //
5183                         // we use sig.RetType == null to mean `do not check the
5184                         // method return value.  
5185                         //
5186                         if (sig.RetType != null)
5187                                 if (ReturnType != sig.RetType)
5188                                         return false;
5189
5190                         Type [] args;
5191                         if (mi != null)
5192                                 args = TypeManager.GetArgumentTypes (mi);
5193                         else
5194                                 args = TypeManager.GetArgumentTypes (pi);
5195
5196                         Type [] sigp = sig.Parameters;
5197
5198                         if (args.Length != sigp.Length)
5199                                 return false;
5200
5201                         for (int i = args.Length; i > 0; ){
5202                                 i--;
5203                                 if (args [i] != sigp [i])
5204                                         return false;
5205                         }
5206                         return true;
5207                 }
5208
5209                 //
5210                 // This filter should be used when we are requesting methods that
5211                 // we want to override.
5212                 //
5213                 // This makes a number of assumptions, for example
5214                 // that the methods being extracted are of a parent
5215                 // class (this means we know implicitly that we are
5216                 // being called to find out about members by a derived
5217                 // class).
5218                 // 
5219                 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
5220                 {
5221                         if (MemberSignatureCompare (m, filter_criteria)){
5222                                 MethodInfo mi = (MethodInfo) m;
5223                                 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5224
5225                                 // If only accessible to the current class.
5226                                 if (prot == MethodAttributes.Private)
5227                                         return false;
5228
5229                                 // If only accessible to the defining assembly or 
5230                                 if (prot == MethodAttributes.FamANDAssem ||
5231                                     prot == MethodAttributes.Assembly){
5232                                         if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
5233                                                 return true;
5234                                         else
5235                                                 return false;
5236                                 }
5237
5238                                 // Anything else (FamOrAssembly and Public) is fine
5239                                 return true;
5240                         }
5241                         return false;
5242                 }
5243
5244                 //
5245                 // This filter should be used when we are requesting properties that
5246                 // we want to override.
5247                 //
5248                 // This makes a number of assumptions, for example
5249                 // that the methods being extracted are of a parent
5250                 // class (this means we know implicitly that we are
5251                 // being called to find out about members by a derived
5252                 // class).
5253                 // 
5254                 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
5255                 {
5256                 if (MemberSignatureCompare (m, filter_criteria)){
5257                                 PropertyInfo pi = (PropertyInfo) m;
5258
5259                                 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
5260                                 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
5261
5262                                 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
5263
5264                                 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5265
5266                                 // If only accessible to the current class.
5267                                 if (prot == MethodAttributes.Private)
5268                                         return false;
5269
5270                                 // If only accessible to the defining assembly or 
5271                                 if (prot == MethodAttributes.FamANDAssem ||
5272                                     prot == MethodAttributes.Assembly){
5273                                         if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
5274                                                 return true;
5275                                         else
5276                                                 return false;
5277                                 }
5278
5279                                 // Anything else (FamOrAssembly and Public) is fine
5280                                 return true;
5281                         }
5282                         return false;
5283                 }
5284         }
5285 }