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