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