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