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