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