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