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