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