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