628ec85c84024c5928971779dabb607f07ed4eb2
[mono.git] / mcs / mcs / class.cs
1 //
2 // class.cs: Class and Struct handlers
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 //          Martin Baulig (martin@gnome.org)
6 //
7 // Licensed under the terms of the GNU GPL
8 //
9 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
10 //
11 //
12 //  2002-10-11  Miguel de Icaza  <miguel@ximian.com>
13 //
14 //      * class.cs: Following the comment from 2002-09-26 to AddMethod, I
15 //      have fixed a remaining problem: not every AddXXXX was adding a
16 //      fully qualified name.  
17 //
18 //      Now everyone registers a fully qualified name in the DeclSpace as
19 //      being defined instead of the partial name.  
20 //
21 //      Downsides: we are slower than we need to be due to the excess
22 //      copies and the names being registered this way.  
23 //
24 //      The reason for this is that we currently depend (on the corlib
25 //      bootstrap for instance) that types are fully qualified, because
26 //      we dump all the types in the namespace, and we should really have
27 //      types inserted into the proper namespace, so we can only store the
28 //      basenames in the defined_names array.
29 //
30 //
31 #define CACHE
32 using System;
33 using System.Collections;
34 using System.Reflection;
35 using System.Reflection.Emit;
36 using System.Runtime.CompilerServices;
37 using System.Runtime.InteropServices;
38
39 namespace Mono.CSharp {
40
41         /// <summary>
42         ///   This is the base class for structs and classes.  
43         /// </summary>
44         public class TypeContainer : DeclSpace, IMemberContainer {
45                 // Holds a list of classes and structures
46                 ArrayList types;
47
48                 // Holds the list of properties
49                 ArrayList properties;
50
51                 // Holds the list of enumerations
52                 ArrayList enums;
53
54                 // Holds the list of delegates
55                 ArrayList delegates;
56                 
57                 // Holds the list of constructors
58                 ArrayList instance_constructors;
59
60                 // Holds the list of fields
61                 ArrayList fields;
62
63                 // Holds a list of fields that have initializers
64                 ArrayList initialized_fields;
65
66                 // Holds a list of static fields that have initializers
67                 ArrayList initialized_static_fields;
68
69                 // Holds the list of constants
70                 ArrayList constants;
71
72                 // Holds the list of
73                 ArrayList interfaces;
74
75                 // Holds order in which interfaces must be closed
76                 ArrayList interface_order;
77                 
78                 // Holds the methods.
79                 ArrayList methods;
80
81                 // Holds the events
82                 ArrayList events;
83
84                 // Holds the indexers
85                 ArrayList indexers;
86
87                 // Holds the operators
88                 ArrayList operators;
89
90                 // The emit context for toplevel objects.
91                 EmitContext ec;
92                 
93                 //
94                 // Pointers to the default constructor and the default static constructor
95                 //
96                 Constructor default_constructor;
97                 Constructor default_static_constructor;
98
99                 //
100                 // Whether we have seen a static constructor for this class or not
101                 //
102                 public bool UserDefinedStaticConstructor = false;
103
104                 //
105                 // Whether we have at least one non-static field
106                 //
107                 bool have_nonstatic_fields = false;
108                 
109                 //
110                 // This one is computed after we can distinguish interfaces
111                 // from classes from the arraylist `type_bases' 
112                 //
113                 string     base_class_name;
114
115                 ArrayList type_bases;
116
117                 bool members_defined;
118                 bool members_defined_ok;
119
120                 // The interfaces we implement.
121                 TypeExpr [] ifaces;
122                 Type[] base_inteface_types;
123
124                 // The parent member container and our member cache
125                 IMemberContainer parent_container;
126                 MemberCache member_cache;
127                 
128                 //
129                 // The indexer name for this class
130                 //
131                 public string IndexerName;
132
133                 public TypeContainer ():
134                         this (null, null, "", null, new Location (-1)) {
135                 }
136
137                 public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
138                         : base (ns, parent, name, attrs, l)
139                 {
140                         types = new ArrayList ();
141
142                         base_class_name = null;
143                 }
144
145                 public AdditionResult AddConstant (Const constant)
146                 {
147                         AdditionResult res;
148                         string basename = constant.Name;
149                         string fullname = Name + "." + basename;
150
151                         if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
152                                 return res;
153                         
154                         if (constants == null)
155                                 constants = new ArrayList ();
156
157                         constants.Add (constant);
158                         DefineName (fullname, constant);
159
160                         return AdditionResult.Success;
161                 }
162
163                 public AdditionResult AddEnum (Mono.CSharp.Enum e)
164                 {
165                         AdditionResult res;
166
167                         if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
168                                 return res;
169
170                         if (enums == null)
171                                 enums = new ArrayList ();
172
173                         enums.Add (e);
174                         DefineName (e.Name, e);
175
176                         return AdditionResult.Success;
177                 }
178                 
179                 public AdditionResult AddClass (Class c)
180                 {
181                         AdditionResult res;
182                         string name = c.Basename;
183                         
184                         if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
185                                 return res;
186
187                         DefineName (c.Name, c);
188                         types.Add (c);
189
190                         return AdditionResult.Success;
191                 }
192
193                 public AdditionResult AddStruct (Struct s)
194                 {
195                         AdditionResult res;
196                         string name = s.Basename;
197                         
198                         if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
199                                 return res;
200
201                         DefineName (s.Name, s);
202                         types.Add (s);
203
204                         return AdditionResult.Success;
205                 }
206
207                 public AdditionResult AddDelegate (Delegate d)
208                 {
209                         AdditionResult res;
210                         string name = d.Basename;
211                         
212                         if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
213                                 return res;
214
215                         if (delegates == null)
216                                 delegates = new ArrayList ();
217                         
218                         DefineName (d.Name, d);
219                         delegates.Add (d);
220
221                         return AdditionResult.Success;
222                 }
223
224                 public AdditionResult AddMethod (Method method)
225                 {
226                         string basename = method.Name;
227                         string fullname = Name + "." + basename;
228
229                         Object value = defined_names [fullname];
230
231                         if (value != null && (!(value is Method)))
232                                 return AdditionResult.NameExists;
233
234                         if (basename == Basename)
235                                 return AdditionResult.EnclosingClash;
236
237                         if (methods == null)
238                                 methods = new ArrayList ();
239
240                         if (method.Name.IndexOf ('.') != -1)
241                                 methods.Insert (0, method);
242                         else 
243                                 methods.Add (method);
244                         
245                         if (value == null)
246                                 DefineName (fullname, method);
247
248                         return AdditionResult.Success;
249                 }
250
251                 public AdditionResult AddConstructor (Constructor c)
252                 {
253                         if (c.Name != Basename) 
254                                 return AdditionResult.NotAConstructor;
255
256                         bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
257                         
258                         if (is_static){
259                                 UserDefinedStaticConstructor = true;
260                                 if (default_static_constructor != null)
261                                         return AdditionResult.MethodExists;
262
263                                 default_static_constructor = c;
264                         } else {
265                                 if (c.IsDefault ()){
266                                         if (default_constructor != null)
267                                                 return AdditionResult.MethodExists;
268                                         default_constructor = c;
269                                 }
270                                 
271                                 if (instance_constructors == null)
272                                         instance_constructors = new ArrayList ();
273                                 
274                                 instance_constructors.Add (c);
275                         }
276                         
277                         return AdditionResult.Success;
278                 }
279                 
280                 public AdditionResult AddInterface (Interface iface)
281                 {
282                         AdditionResult res;
283                         string name = iface.Basename;
284                         
285                         if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
286                                 return res;
287                         
288                         if (interfaces == null)
289                                 interfaces = new ArrayList ();
290                         interfaces.Add (iface);
291                         DefineName (iface.Name, iface);
292                         
293                         return AdditionResult.Success;
294                 }
295
296                 public AdditionResult AddField (Field field)
297                 {
298                         AdditionResult res;
299                         string basename = field.Name;
300                         string fullname = Name + "." + basename;
301
302                         if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
303                                 return res;
304                         
305                         if (fields == null)
306                                 fields = new ArrayList ();
307                         
308                         fields.Add (field);
309                         
310                         if (field.HasInitializer){
311                                 if ((field.ModFlags & Modifiers.STATIC) != 0){
312                                         if (initialized_static_fields == null)
313                                                 initialized_static_fields = new ArrayList ();
314
315                                         initialized_static_fields.Add (field);
316
317                                 } else {
318                                         if (initialized_fields == null)
319                                                 initialized_fields = new ArrayList ();
320                                 
321                                         initialized_fields.Add (field);
322                                 }
323                         }
324
325                         if ((field.ModFlags & Modifiers.STATIC) == 0)
326                                 have_nonstatic_fields = true;
327
328                         DefineName (fullname, field);
329                         return AdditionResult.Success;
330                 }
331
332                 public AdditionResult AddProperty (Property prop)
333                 {
334                         AdditionResult res;
335
336                         if ((res = AddProperty (prop, prop.Name)) != AdditionResult.Success)
337                                 return res;
338
339                         if (prop.Get != null) {
340                                 if ((res = AddProperty (prop, "get_" + prop.Name)) != AdditionResult.Success)
341                                         return res;
342                         }
343
344                         if (prop.Set != null) {
345                                 if ((res = AddProperty (prop, "set_" + prop.Name)) != AdditionResult.Success)
346                                 return res;
347                         }
348
349                         if (properties == null)
350                                 properties = new ArrayList ();
351
352                         if (prop.Name.IndexOf ('.') != -1)
353                                 properties.Insert (0, prop);
354                         else
355                                 properties.Add (prop);
356
357                         return AdditionResult.Success;
358                 }
359
360                 AdditionResult AddProperty (Property prop, string basename)
361                 {
362                         AdditionResult res;
363                         string fullname = Name + "." + basename;
364
365                         if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
366                                 return res;
367
368                         DefineName (fullname, prop);
369
370                         return AdditionResult.Success;
371                 }
372
373                 public AdditionResult AddEvent (Event e)
374                 {
375                         AdditionResult res;
376                         string basename = e.Name;
377                         string fullname = Name + "." + basename;
378
379                         if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
380                                 return res;
381
382                         if (events == null)
383                                 events = new ArrayList ();
384                         
385                         events.Add (e);
386                         DefineName (fullname, e);
387
388                         return AdditionResult.Success;
389                 }
390
391                 public void AddIndexer (Indexer i)
392                 {
393                         if (indexers == null)
394                                 indexers = new ArrayList ();
395
396                         if (i.ExplicitInterfaceName != null)
397                                 indexers.Insert (0, i);
398                         else
399                                 indexers.Add (i);
400                 }
401
402                 public AdditionResult AddOperator (Operator op)
403                 {
404                         if (operators == null)
405                                 operators = new ArrayList ();
406
407                         operators.Add (op);
408
409                         string basename = op.Name;
410                         string fullname = Name + "." + basename;
411                         if (!defined_names.Contains (fullname))
412                         {
413                                 DefineName (fullname, op);
414                         }
415                         return AdditionResult.Success;
416                 }
417
418                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
419                 {
420                         if (a.Type == TypeManager.default_member_type) {
421                                 if (Indexers != null) {
422                                         Report.Error (646, a.Location,
423                                                       "Cannot specify the DefaultMember attribute on" +
424                                                       " a type containing an indexer");
425                                         return;
426                                 }
427                         }
428                         
429                         base.ApplyAttributeBuilder (a, cb);
430                 } 
431
432                 public override AttributeTargets AttributeTargets {
433                         get {
434                                 throw new NotSupportedException ();
435                         }
436                 }
437
438                 public void RegisterOrder (Interface iface)
439                 {
440                         if (interface_order == null)
441                                 interface_order = new ArrayList ();
442
443                         interface_order.Add (iface);
444                 }
445                 
446                 public ArrayList Types {
447                         get {
448                                 return types;
449                         }
450                 }
451
452                 public ArrayList Methods {
453                         get {
454                                 return methods;
455                         }
456                 }
457
458                 public ArrayList Constants {
459                         get {
460                                 return constants;
461                         }
462                 }
463
464                 public ArrayList Interfaces {
465                         get {
466                                 return interfaces;
467                         }
468                 }
469                 
470                 public string Base {
471                         get {
472                                 return base_class_name;
473                         }
474                 }
475                 
476                 public ArrayList Bases {
477                         get {
478                                 return type_bases;
479                         }
480
481                         set {
482                                 type_bases = value;
483                         }
484                 }
485
486                 public ArrayList Fields {
487                         get {
488                                 return fields;
489                         }
490
491                         set {
492                                 fields = value;
493                         }
494                 }
495
496                 public ArrayList InstanceConstructors {
497                         get {
498                                 return instance_constructors;
499                         }
500                 }
501
502                 public ArrayList Properties {
503                         get {
504                                 return properties;
505                         }
506                 }
507
508                 public ArrayList Events {
509                         get {
510                                 return events;
511                         }
512                 }
513                 
514                 public ArrayList Enums {
515                         get {
516                                 return enums;
517                         }
518                 }
519
520                 public ArrayList Indexers {
521                         get {
522                                 return indexers;
523                         }
524                 }
525
526                 public ArrayList Operators {
527                         get {
528                                 return operators;
529                         }
530                 }
531
532                 public ArrayList Delegates {
533                         get {
534                                 return delegates;
535                         }
536                 }
537
538                 public virtual TypeAttributes TypeAttr {
539                         get {
540                                 return Modifiers.TypeAttr (ModFlags, this);
541                         }
542                 }
543
544                 //
545                 // Emits the instance field initializers
546                 //
547                 public bool EmitFieldInitializers (EmitContext ec)
548                 {
549                         ArrayList fields;
550                         Expression instance_expr;
551                         
552                         if (ec.IsStatic){
553                                 fields = initialized_static_fields;
554                                 instance_expr = null;
555                         } else {
556                                 fields = initialized_fields;
557                                 instance_expr = new This (Location.Null).Resolve (ec);
558                         }
559
560                         if (fields == null)
561                                 return true;
562
563                         foreach (Field f in fields){
564                                 Expression e = f.GetInitializerExpression (ec);
565                                 if (e == null)
566                                         return false;
567
568                                 Location l = f.Location;
569                                 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
570                                 fe.InstanceExpression = instance_expr;
571                                 ExpressionStatement a = new Assign (fe, e, l);
572
573                                 a = a.ResolveStatement (ec);
574                                 if (a == null)
575                                         return false;
576
577                                 a.EmitStatement (ec);
578                         }
579
580                         return true;
581                 }
582                 
583                 //
584                 // Defines the default constructors
585                 //
586                 void DefineDefaultConstructor (bool is_static)
587                 {
588                         Constructor c;
589
590                         // The default constructor is public
591                         // If the class is abstract, the default constructor is protected
592                         // The default static constructor is private
593
594                         int mods = Modifiers.PUBLIC;
595                         if (is_static)
596                                 mods = Modifiers.STATIC | Modifiers.PRIVATE;
597                         else if ((ModFlags & Modifiers.ABSTRACT) != 0)
598                                 mods = Modifiers.PROTECTED;
599
600                         c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
601                                              new ConstructorBaseInitializer (
602                                                      null, Parameters.EmptyReadOnlyParameters,
603                                                      Location),
604                                              Location);
605                         
606                         AddConstructor (c);
607                         
608                         c.Block = new ToplevelBlock (null, Location);
609                         
610                 }
611
612                 public void ReportStructInitializedInstanceError ()
613                 {
614                         string n = TypeBuilder.FullName;
615                         
616                         foreach (Field f in initialized_fields){
617                                 Report.Error (
618                                         573, Location,
619                                         "`" + n + "." + f.Name + "': can not have " +
620                                         "instance field initializers in structs");
621                         }
622                 }
623
624                 /// <remarks>
625                 ///  The pending methods that need to be implemented (interfaces or abstract methods)
626                 /// </remarks>
627                 public PendingImplementation Pending;
628
629                 /// <summary>
630                 ///   This function computes the Base class and also the
631                 ///   list of interfaces that the class or struct @c implements.
632                 ///   
633                 ///   The return value is an array (might be null) of
634                 ///   interfaces implemented (as Types).
635                 ///   
636                 ///   The @parent argument is set to the parent object or null
637                 ///   if this is `System.Object'. 
638                 /// </summary>
639                 TypeExpr [] GetClassBases (bool is_class, bool is_iface,
640                                            out TypeExpr parent, out bool error)
641                 {
642                         ArrayList bases = Bases;
643                         int count;
644                         int start, j, i;
645
646                         error = false;
647
648                         if (is_class || is_iface)
649                                 parent = null;
650                         else
651                                 parent = TypeManager.system_valuetype_expr;
652
653                         if (bases == null){
654                                 if (is_class){
655                                         if (RootContext.StdLib)
656                                                 parent = TypeManager.system_object_expr;
657                                         else if (Name != "System.Object")
658                                                 parent = TypeManager.system_object_expr;
659                                 } else {
660                                         //
661                                         // If we are compiling our runtime,
662                                         // and we are defining ValueType, then our
663                                         // parent is `System.Object'.
664                                         //
665                                         if (!RootContext.StdLib && Name == "System.ValueType")
666                                                 parent = TypeManager.system_object_expr;
667                                 }
668
669                                 return null;
670                         }
671
672                         //
673                         // Bases should be null if there are no bases at all
674                         //
675                         count = bases.Count;
676
677                         if (is_class){
678                                 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
679
680                                 if (name == null){
681                                         error = true;
682                                         return null;
683                                 }
684
685                                 if (name.IsClass){
686                                         parent = name;
687                                         start = 1;
688                                 } else {
689                                         parent = TypeManager.system_object_expr;
690                                         start = 0;
691                                 }
692                                 if (name.IsSealed){
693                                         string detail = "";
694                                         
695                                         if (name.IsValueType)
696                                                 detail = " (a class can not inherit from a struct/enum)";
697                                         
698                                         Report.Error (509, "class `"+ Name +
699                                                       "': Cannot inherit from sealed class `"+
700                                                       name.Name + "'" + detail);
701                                         error = true;
702                                         return null;
703                                 }
704
705                                 if (!parent.CanInheritFrom ()){
706                                         Report.Error (644, Location,
707                                                       "`{0}' cannot inherit from special class `{1}'",
708                                                       Name, parent.Name);
709                                         error = true;
710                                         return null;
711                                 }
712
713                                 if (!parent.AsAccessible (this, ModFlags))
714                                         Report.Error (60, Location,
715                                                       "Inconsistent accessibility: base class `" +
716                                                       name.Name + "' is less accessible than class `" +
717                                                       Name + "'");
718
719                         } else {
720                                 start = 0;
721                         }
722
723                         if (parent != null)
724                                 base_class_name = parent.Name;
725
726                         TypeExpr [] ifaces = new TypeExpr [count-start];
727                         
728                         for (i = start, j = 0; i < count; i++, j++){
729                                 Expression name = (Expression) bases [i];
730                                 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
731                                 if (resolved == null)
732                                         return null;
733                                 
734                                 bases [i] = resolved;
735
736                                 if (is_class == false && !resolved.IsInterface){
737                                         Report.Error (527, "In Struct `" + Name + "', type `"+
738                                                       name +"' is not an interface");
739                                         error = true;
740                                         return null;
741                                 }
742                                 
743                                 if (resolved.IsClass) {
744                                         if (parent != null){
745                                                 Report.Error (527, "In Class `" + Name + "', type `"+
746                                                               name+"' is not an interface");
747                                                 error = true;
748                                                 return null;
749                                         }
750                                 }
751
752                                 for (int x = 0; x < j; x++) {
753                                         if (resolved.Equals (ifaces [x])) {
754                                                 Report.Error (528, "`" + name + "' is already listed in interface list");
755                                                 error = true;
756                                                 return null;
757                                         }
758                                 }
759
760                                 if (is_iface &&
761                                     !resolved.AsAccessible (Parent, ModFlags))
762                                         Report.Error (61, Location,
763                                                       "Inconsistent accessibility: base interface `" +
764                                                       name + "' is less accessible than interface `" +
765                                                       Name + "'");
766
767                                 ifaces [j] = resolved;
768                         }
769
770                         return TypeManager.ExpandInterfaces (ifaces);
771                 }
772
773                 bool error = false;
774                 
775                 //
776                 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
777                 //
778                 public override TypeBuilder DefineType ()
779                 {
780                         TypeExpr parent;
781                         bool is_class, is_iface;
782
783                         if (TypeBuilder != null)
784                                 return TypeBuilder;
785
786                         if (error)
787                                 return null;
788                         
789                         if (InTransit) {
790                                 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
791                                 error = true;
792                                 return null;
793                         }
794                         
795                         InTransit = true;
796
797                         if (this is Interface) {
798                                 is_iface = true;
799                                 is_class = false;
800                         } else {
801                                 is_iface = false;
802                                 if (this is Class)
803                                         is_class = true;
804                                 else
805                                         is_class = false;
806                         }
807
808                         ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
809
810                         ifaces = GetClassBases (is_class, is_iface, out parent, out error); 
811
812                         if (error)
813                                 return null;
814
815                         if (!is_class && TypeManager.value_type == null)
816                                 throw new Exception ();
817
818                         TypeAttributes type_attributes = TypeAttr;
819
820                         Type ptype;
821                         if (parent != null)
822                                 ptype = parent.ResolveType (ec);
823                         else
824                                 ptype = null;
825
826                         if (IsTopLevel){
827                                 if (TypeManager.NamespaceClash (Name, Location)) {
828                                         error = true;
829                                         return null;
830                                 }
831                                 
832                                 ModuleBuilder builder = CodeGen.Module.Builder;
833                                 TypeBuilder = builder.DefineType (
834                                         Name, type_attributes, ptype, null);
835                         } else {
836                                 TypeBuilder builder = Parent.DefineType ();
837                                 if (builder == null)
838                                         return null;
839                                 
840                                 TypeBuilder = builder.DefineNestedType (
841                                         Basename, type_attributes, ptype, null);
842                         }
843                                 
844                         //
845                         // Structs with no fields need to have at least one byte.
846                         // The right thing would be to set the PackingSize in a DefineType
847                         // but there are no functions that allow interfaces *and* the size to
848                         // be specified.
849                         //
850
851                         if (!is_class && !is_iface && !have_nonstatic_fields){
852                                 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
853                                                          FieldAttributes.Private);
854                         }
855
856                         // add interfaces that were not added at type creation
857                         if (ifaces != null) {
858                                 base_inteface_types = new Type[ifaces.Length];
859                                 for (int i = 0; i < ifaces.Length; ++i) {
860                                         Type itype = ifaces [i].ResolveType (ec);
861                                         TypeBuilder.AddInterfaceImplementation (itype);
862                                         base_inteface_types [i] = itype;
863                                 }
864                         }
865
866                         //
867                         // Finish the setup for the EmitContext
868                         //
869                         ec.ContainerType = TypeBuilder;
870
871                         TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
872
873                         if ((parent != null) && parent.IsAttribute) {
874                                 RootContext.RegisterAttribute (this);
875                         } else
876                                 RootContext.RegisterOrder (this); 
877                                 
878                         if (Interfaces != null) {
879                                 foreach (Interface iface in Interfaces)
880                                         if (iface.DefineType () == null) {
881                                                 error = true;
882                                                 return null;
883                                         }
884                         }
885                         
886                         if (Types != null) {
887                                 foreach (TypeContainer tc in Types)
888                                         if (tc.DefineType () == null) {
889                                                 error = true;
890                                                 return null;
891                                         }
892                         }
893
894                         if (Delegates != null) {
895                                 foreach (Delegate d in Delegates)
896                                         if (d.DefineType () == null) {
897                                                 error = true;
898                                                 return null;
899                                         }
900                         }
901
902                         if (Enums != null) {
903                                 foreach (Enum en in Enums)
904                                         if (en.DefineType () == null) {
905                                                 error = true;
906                                                 return null;
907                                         }
908                         }
909
910                         InTransit = false;
911                         return TypeBuilder;
912                 }
913
914
915                 /// <summary>
916                 ///   Defines the MemberCore objects that are in the `list' Arraylist
917                 ///
918                 ///   The `defined_names' array contains a list of members defined in
919                 ///   a base class
920                 /// </summary>
921                 static ArrayList remove_list = new ArrayList ();
922                 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
923                 {
924                         int idx;
925                         
926                         remove_list.Clear ();
927
928                         foreach (MemberCore mc in list){
929
930                                 if (defined_names != null)
931                                         idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
932                                 else
933                                         idx = -1;
934
935                                 if (idx < 0){
936                                         if (RootContext.WarningLevel >= 4){
937                                                 if ((mc.ModFlags & Modifiers.NEW) != 0)
938                                                         Warning_KeywordNewNotRequired (mc.Location, mc);
939                                         }
940                                 } else if (mc is MethodCore)
941                                         ((MethodCore) mc).OverridesSomething = true;
942
943                                 if (!mc.Define (this)){
944                                         remove_list.Add (mc);
945                                         continue;
946                                 }
947                                                 
948                                 if (idx < 0)
949                                         continue;
950
951                                 MemberInfo match = defined_names [idx];
952
953                                 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
954                                         continue;
955
956                                 //
957                                 // If we are both methods, let the method resolution emit warnings
958                                 //
959                                 if (match is MethodBase && mc is MethodCore)
960                                         continue; 
961
962                                 if ((mc.ModFlags & Modifiers.NEW) == 0) {
963                                         if (mc is Event) {
964                                                 if (!(match is EventInfo)) {
965                                                         Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
966                                                         return;
967                                                 }
968
969                                                 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
970                                                         continue;
971                                         }
972
973                                         Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
974                                 }
975                         }
976                         
977                         foreach (object o in remove_list)
978                                 list.Remove (o);
979                         
980                         remove_list.Clear ();
981                 }
982
983                 //
984                 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
985                 // class is consistent.  Either it is `Item' or it is the name defined by all the
986                 // indexers with the `IndexerName' attribute.
987                 //
988                 // Turns out that the IndexerNameAttribute is applied to each indexer,
989                 // but it is never emitted, instead a DefaultMember attribute is attached
990                 // to the class.
991                 //
992                 void DefineIndexers ()
993                 {
994                         string class_indexer_name = null;
995
996                         //
997                         // If there's both an explicit and an implicit interface implementation, the
998                         // explicit one actually implements the interface while the other one is just
999                         // a normal indexer.  See bug #37714.
1000                         //
1001
1002                         // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1003                         bool seen_normal_indexers = false;
1004
1005                         foreach (Indexer i in Indexers) {
1006                                 string name;
1007
1008                                 i.Define (this);
1009
1010                                 name = i.IndexerName;
1011
1012                                 if (i.InterfaceType != null) {
1013                                         if (seen_normal_indexers)
1014                                                 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1015                                         continue;
1016                                 }
1017
1018                                 seen_normal_indexers = true;
1019
1020                                 if (class_indexer_name == null)
1021                                         class_indexer_name = name;
1022                                 else if (name != class_indexer_name)
1023                                         Report.Error (668, "Two indexers have different names, " +
1024                                                       " you should use the same name for all your indexers");
1025                         }
1026
1027                         if (seen_normal_indexers && class_indexer_name == null)
1028                                 class_indexer_name = "Item";
1029                         IndexerName = class_indexer_name;
1030                 }
1031
1032                 static void Error_KeywordNotAllowed (Location loc)
1033                 {
1034                         Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1035                 }
1036
1037                 /// <summary>
1038                 ///   Populates our TypeBuilder with fields and methods
1039                 /// </summary>
1040                 public override bool DefineMembers (TypeContainer container)
1041                 {
1042                         if (members_defined)
1043                                 return members_defined_ok;
1044
1045                         members_defined_ok = DoDefineMembers ();
1046                         members_defined = true;
1047
1048                         return members_defined_ok;
1049                 }
1050
1051                 bool DoDefineMembers ()
1052                 {
1053                         MemberInfo [] defined_names = null;
1054
1055                         //
1056                         // We need to be able to use the member cache while we are checking/defining
1057                         //
1058 #if CACHE
1059                         if (TypeBuilder.BaseType != null)
1060                                 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1061 #endif
1062
1063                         if (interface_order != null){
1064                                 foreach (Interface iface in interface_order)
1065                                         if ((iface.ModFlags & Modifiers.NEW) == 0)
1066                                                 iface.DefineMembers (this);
1067                                         else
1068                                                 Error_KeywordNotAllowed (iface.Location);
1069                         }
1070
1071                         if (RootContext.WarningLevel > 1){
1072                                 Type ptype;
1073
1074                                 //
1075                                 // This code throws an exception in the comparer
1076                                 // I guess the string is not an object?
1077                                 //
1078                                 ptype = TypeBuilder.BaseType;
1079                                 if (ptype != null){
1080                                         defined_names = (MemberInfo []) FindMembers (
1081                                                 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1082                                                 BindingFlags.Public | BindingFlags.Instance |
1083                                                 BindingFlags.Static, null, null);
1084
1085                                         Array.Sort (defined_names, mif_compare);
1086                                 }
1087                         }
1088
1089                         Class pclass = Parent as Class;
1090                         if (pclass != null) {
1091                                 string pname = null;
1092                                 Type ptype = null;
1093                                 Type t = pclass.TypeBuilder.BaseType;
1094                                 while ((t != null) && (ptype == null)) {
1095                                         pname = t.FullName + "." + Basename;
1096                                         ptype = RootContext.LookupType (this, pname, true, Location.Null);
1097                                         t = t.BaseType;
1098                                 }
1099
1100                                 if ((ModFlags & Modifiers.NEW) != 0) {
1101                                         if (ptype == null)
1102                                                 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1103                                                                 "inherited member. The keyword new is not required.");
1104                                 } else if (ptype != null) {
1105                                         Report.Warning (108, Location, "The keyword new is required on `" +
1106                                                         Name + "' because it hides inherited member '" +
1107                                                         pname + "'.");
1108                                 }
1109                         } else if ((ModFlags & Modifiers.NEW) != 0)
1110                                 Error_KeywordNotAllowed (Location);
1111
1112                         if (constants != null)
1113                                 DefineMembers (constants, defined_names);
1114
1115                         if (fields != null)
1116                                 DefineMembers (fields, defined_names);
1117
1118                         if (this is Class){
1119                                 if (instance_constructors == null){
1120                                         if (default_constructor == null)
1121                                                 DefineDefaultConstructor (false);
1122                                 }
1123
1124                                 if (initialized_static_fields != null &&
1125                                     default_static_constructor == null)
1126                                         DefineDefaultConstructor (true);
1127                         }
1128
1129                         if (this is Struct){
1130                                 //
1131                                 // Structs can not have initialized instance
1132                                 // fields
1133                                 //
1134                                 if (initialized_static_fields != null &&
1135                                     default_static_constructor == null)
1136                                         DefineDefaultConstructor (true);
1137
1138                                 if (initialized_fields != null)
1139                                         ReportStructInitializedInstanceError ();
1140                         }
1141
1142                         if (!(this is Interface))
1143                                 Pending = PendingImplementation.GetPendingImplementations (this);
1144                         
1145                         //
1146                         // Constructors are not in the defined_names array
1147                         //
1148                         if (instance_constructors != null)
1149                                 DefineMembers (instance_constructors, null);
1150                 
1151                         if (default_static_constructor != null)
1152                                 default_static_constructor.Define (this);
1153                         
1154                         if (methods != null)
1155                                 DefineMembers (methods, defined_names);
1156
1157                         if (properties != null)
1158                                 DefineMembers (properties, defined_names);
1159
1160                         if (events != null)
1161                                 DefineMembers (events, defined_names);
1162
1163                         if (indexers != null)
1164                                 DefineIndexers ();
1165
1166                         if (operators != null){
1167                                 DefineMembers (operators, null);
1168
1169                                 CheckPairedOperators ();
1170                         }
1171
1172                         if (enums != null)
1173                                 DefineMembers (enums, defined_names);
1174                         
1175                         if (delegates != null)
1176                                 DefineMembers (delegates, defined_names);
1177
1178 #if CACHE
1179                         member_cache = new MemberCache (this);
1180 #endif
1181
1182                         
1183                         return true;
1184                 }
1185
1186                 public override bool Define (TypeContainer container)
1187                 {
1188                         if (interface_order != null){
1189                                 foreach (Interface iface in interface_order)
1190                                         if ((iface.ModFlags & Modifiers.NEW) == 0)
1191                                                 iface.Define (this);
1192                         }
1193
1194                         return true;
1195                 }
1196
1197                 /// <summary>
1198                 ///   This function is based by a delegate to the FindMembers routine
1199                 /// </summary>
1200                 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1201                 {
1202                         return true;
1203                 }
1204
1205                 /// <summary>
1206                 ///   This filter is used by FindMembers, and we just keep
1207                 ///   a global for the filter to `AlwaysAccept'
1208                 /// </summary>
1209                 static MemberFilter accepting_filter;
1210
1211                 
1212                 /// <summary>
1213                 ///   A member comparission method based on name only
1214                 /// </summary>
1215                 static IComparer mif_compare;
1216
1217                 static TypeContainer ()
1218                 {
1219                         accepting_filter = new MemberFilter (AlwaysAccept);
1220                         mif_compare = new MemberInfoCompare ();
1221                 }
1222
1223                 public MethodInfo[] GetMethods ()
1224                 {
1225                         ArrayList members = new ArrayList ();
1226
1227                         DefineMembers (null);
1228
1229                         if (methods != null) {
1230                                 int len = methods.Count;
1231                                 for (int i = 0; i < len; i++) {
1232                                         Method m = (Method) methods [i];
1233
1234                                         members.Add (m.MethodBuilder);
1235                                 }
1236                         }
1237
1238                         if (operators != null) {
1239                                 int len = operators.Count;
1240                                 for (int i = 0; i < len; i++) {
1241                                         Operator o = (Operator) operators [i];
1242
1243                                         members.Add (o.OperatorMethodBuilder);
1244                                 }
1245                         }
1246
1247                         if (properties != null) {
1248                                 int len = properties.Count;
1249                                 for (int i = 0; i < len; i++) {
1250                                         Property p = (Property) properties [i];
1251
1252                                         if (p.GetBuilder != null)
1253                                                 members.Add (p.GetBuilder);
1254                                         if (p.SetBuilder != null)
1255                                                 members.Add (p.SetBuilder);
1256                                 }
1257                         }
1258                                 
1259                         if (indexers != null) {
1260                                 int len = indexers.Count;
1261                                 for (int i = 0; i < len; i++) {
1262                                         Indexer ix = (Indexer) indexers [i];
1263
1264                                         if (ix.GetBuilder != null)
1265                                                 members.Add (ix.GetBuilder);
1266                                         if (ix.SetBuilder != null)
1267                                                 members.Add (ix.SetBuilder);
1268                                 }
1269                         }
1270
1271                         if (events != null) {
1272                                 int len = events.Count;
1273                                 for (int i = 0; i < len; i++) {
1274                                         Event e = (Event) events [i];
1275
1276                                         if (e.AddBuilder != null)
1277                                                 members.Add (e.AddBuilder);
1278                                         if (e.RemoveBuilder != null)
1279                                                 members.Add (e.RemoveBuilder);
1280                                 }
1281                         }
1282
1283                         MethodInfo[] retMethods = new MethodInfo [members.Count];
1284                         members.CopyTo (retMethods, 0);
1285                         return retMethods;
1286                 }
1287                 
1288                 /// <summary>
1289                 ///   This method returns the members of this type just like Type.FindMembers would
1290                 ///   Only, we need to use this for types which are _being_ defined because MS' 
1291                 ///   implementation can't take care of that.
1292                 /// </summary>
1293                 //
1294                 // FIXME: return an empty static array instead of null, that cleans up
1295                 // some code and is consistent with some coding conventions I just found
1296                 // out existed ;-)
1297                 //
1298                 //
1299                 // Notice that in various cases we check if our field is non-null,
1300                 // something that would normally mean that there was a bug elsewhere.
1301                 //
1302                 // The problem happens while we are defining p-invoke methods, as those
1303                 // will trigger a FindMembers, but this happens before things are defined
1304                 //
1305                 // Since the whole process is a no-op, it is fine to check for null here.
1306                 //
1307                 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1308                                                         MemberFilter filter, object criteria)
1309                 {
1310                         ArrayList members = null;
1311
1312                         int modflags = 0;
1313                         if ((bf & BindingFlags.Public) != 0)
1314                                 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1315                                         Modifiers.INTERNAL;
1316                         if ((bf & BindingFlags.NonPublic) != 0)
1317                                 modflags |= Modifiers.PRIVATE;
1318
1319                         int static_mask = 0, static_flags = 0;
1320                         switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1321                         case BindingFlags.Static:
1322                                 static_mask = static_flags = Modifiers.STATIC;
1323                                 break;
1324
1325                         case BindingFlags.Instance:
1326                                 static_mask = Modifiers.STATIC;
1327                                 static_flags = 0;
1328                                 break;
1329
1330                         default:
1331                                 static_mask = static_flags = 0;
1332                                 break;
1333                         }
1334
1335                         Timer.StartTimer (TimerType.TcFindMembers);
1336
1337                         if (filter == null)
1338                                 filter = accepting_filter; 
1339
1340                         if ((mt & MemberTypes.Field) != 0) {
1341                                 if (fields != null) {
1342                                         int len = fields.Count;
1343                                         for (int i = 0; i < len; i++) {
1344                                                 Field f = (Field) fields [i];
1345                                                 
1346                                                 if ((f.ModFlags & modflags) == 0)
1347                                                         continue;
1348                                                 if ((f.ModFlags & static_mask) != static_flags)
1349                                                         continue;
1350
1351                                                 FieldBuilder fb = f.FieldBuilder;
1352                                                 if (fb != null && filter (fb, criteria) == true) {
1353                                                         if (members == null)
1354                                                                 members = new ArrayList ();
1355                                                         
1356                                                         members.Add (fb);
1357                                                 }
1358                                         }
1359                                 }
1360
1361                                 if (constants != null) {
1362                                         int len = constants.Count;
1363                                         for (int i = 0; i < len; i++) {
1364                                                 Const con = (Const) constants [i];
1365                                                 
1366                                                 if ((con.ModFlags & modflags) == 0)
1367                                                         continue;
1368                                                 if ((con.ModFlags & static_mask) != static_flags)
1369                                                         continue;
1370
1371                                                 FieldBuilder fb = con.FieldBuilder;
1372                                                 if (fb != null && filter (fb, criteria) == true) {
1373                                                         if (members == null)
1374                                                                 members = new ArrayList ();
1375                                                         
1376                                                         members.Add (fb);
1377                                                 }
1378                                         }
1379                                 }
1380                         }
1381
1382                         if ((mt & MemberTypes.Method) != 0) {
1383                                 if (methods != null) {
1384                                         int len = methods.Count;
1385                                         for (int i = 0; i < len; i++) {
1386                                                 Method m = (Method) methods [i];
1387                                                 
1388                                                 if ((m.ModFlags & modflags) == 0)
1389                                                         continue;
1390                                                 if ((m.ModFlags & static_mask) != static_flags)
1391                                                         continue;
1392                                                 
1393                                                 MethodBuilder mb = m.MethodBuilder;
1394
1395                                                 if (mb != null && filter (mb, criteria) == true) {
1396                                                         if (members == null)
1397                                                                 members = new ArrayList ();
1398                                                         
1399                                                         members.Add (mb);
1400                                                 }
1401                                         }
1402                                 }
1403
1404                                 if (operators != null) {
1405                                         int len = operators.Count;
1406                                         for (int i = 0; i < len; i++) {
1407                                                 Operator o = (Operator) operators [i];
1408                                                 
1409                                                 if ((o.ModFlags & modflags) == 0)
1410                                                         continue;
1411                                                 if ((o.ModFlags & static_mask) != static_flags)
1412                                                         continue;
1413                                                 
1414                                                 MethodBuilder ob = o.OperatorMethodBuilder;
1415                                                 if (ob != null && filter (ob, criteria) == true) {
1416                                                         if (members == null)
1417                                                                 members = new ArrayList ();
1418                                                         
1419                                                         members.Add (ob);
1420                                                 }
1421                                         }
1422                                 }
1423
1424                                 if (properties != null) {
1425                                         int len = properties.Count;
1426                                         for (int i = 0; i < len; i++) {
1427                                                 Property p = (Property) properties [i];
1428                                                 
1429                                                 if ((p.ModFlags & modflags) == 0)
1430                                                         continue;
1431                                                 if ((p.ModFlags & static_mask) != static_flags)
1432                                                         continue;
1433                                                 
1434                                                 MethodBuilder b;
1435
1436                                                 b = p.GetBuilder;
1437                                                 if (b != null && filter (b, criteria) == true) {
1438                                                         if (members == null)
1439                                                                 members = new ArrayList ();
1440                                                         
1441                                                         members.Add (b);
1442                                                 }
1443
1444                                                 b = p.SetBuilder;
1445                                                 if (b != null && filter (b, criteria) == true) {
1446                                                         if (members == null)
1447                                                                 members = new ArrayList ();
1448                                                         
1449                                                         members.Add (b);
1450                                                 }
1451                                         }
1452                                 }
1453                                 
1454                                 if (indexers != null) {
1455                                         int len = indexers.Count;
1456                                         for (int i = 0; i < len; i++) {
1457                                                 Indexer ix = (Indexer) indexers [i];
1458                                                 
1459                                                 if ((ix.ModFlags & modflags) == 0)
1460                                                         continue;
1461                                                 if ((ix.ModFlags & static_mask) != static_flags)
1462                                                         continue;
1463                                                 
1464                                                 MethodBuilder b;
1465
1466                                                 b = ix.GetBuilder;
1467                                                 if (b != null && filter (b, criteria) == true) {
1468                                                         if (members == null)
1469                                                                 members = new ArrayList ();
1470                                                         
1471                                                         members.Add (b);
1472                                                 }
1473
1474                                                 b = ix.SetBuilder;
1475                                                 if (b != null && filter (b, criteria) == true) {
1476                                                         if (members == null)
1477                                                                 members = new ArrayList ();
1478                                                         
1479                                                         members.Add (b);
1480                                                 }
1481                                         }
1482                                 }
1483                         }
1484
1485                         if ((mt & MemberTypes.Event) != 0) {
1486                                 if (events != null) {
1487                                         int len = events.Count;
1488                                         for (int i = 0; i < len; i++) {
1489                                                 Event e = (Event) events [i];
1490                                                 
1491                                                 if ((e.ModFlags & modflags) == 0)
1492                                                         continue;
1493                                                 if ((e.ModFlags & static_mask) != static_flags)
1494                                                         continue;
1495
1496                                                 MemberInfo eb = e.EventBuilder;
1497                                                 if (eb != null && filter (eb, criteria) == true) {
1498                                                         if (members == null)
1499                                                                 members = new ArrayList ();
1500                                                         
1501                                                         members.Add (e.EventBuilder);
1502                                                 }
1503                                         }
1504                                 }
1505                         }
1506                         
1507                         if ((mt & MemberTypes.Property) != 0){
1508                                 if (properties != null) {
1509                                         int len = properties.Count;
1510                                         for (int i = 0; i < len; i++) {
1511                                                 Property p = (Property) properties [i];
1512                                                 
1513                                                 if ((p.ModFlags & modflags) == 0)
1514                                                         continue;
1515                                                 if ((p.ModFlags & static_mask) != static_flags)
1516                                                         continue;
1517
1518                                                 MemberInfo pb = p.PropertyBuilder;
1519                                                 if (pb != null && filter (pb, criteria) == true) {
1520                                                         if (members == null)
1521                                                                 members = new ArrayList ();
1522                                                         
1523                                                         members.Add (p.PropertyBuilder);
1524                                                 }
1525                                         }
1526                                 }
1527
1528                                 if (indexers != null) {
1529                                         int len = indexers.Count;
1530                                         for (int i = 0; i < len; i++) {
1531                                                 Indexer ix = (Indexer) indexers [i];
1532                                                 
1533                                                 if ((ix.ModFlags & modflags) == 0)
1534                                                         continue;
1535                                                 if ((ix.ModFlags & static_mask) != static_flags)
1536                                                         continue;
1537
1538                                                 MemberInfo ib = ix.PropertyBuilder;
1539                                                 if (ib != null && filter (ib, criteria) == true) {
1540                                                         if (members == null)
1541                                                                 members = new ArrayList ();
1542                                                         
1543                                                         members.Add (ix.PropertyBuilder);
1544                                                 }
1545                                         }
1546                                 }
1547                         }
1548                         
1549                         if ((mt & MemberTypes.NestedType) != 0) {
1550                                 if (types != null) {
1551                                         int len = types.Count;
1552                                         for (int i = 0; i < len; i++) {
1553                                                 TypeContainer t = (TypeContainer) types [i];
1554                                                 
1555                                                 if ((t.ModFlags & modflags) == 0)
1556                                                         continue;
1557
1558                                                 TypeBuilder tb = t.TypeBuilder;
1559                                                 if (tb != null && (filter (tb, criteria) == true)) {
1560                                                         if (members == null)
1561                                                                 members = new ArrayList ();
1562                                                         
1563                                                         members.Add (tb);
1564                                                 }
1565                                         }
1566                                 }
1567
1568                                 if (enums != null) {
1569                                         int len = enums.Count;
1570                                         for (int i = 0; i < len; i++) {
1571                                                 Enum en = (Enum) enums [i];
1572                                                 
1573                                                 if ((en.ModFlags & modflags) == 0)
1574                                                         continue;
1575
1576                                                 TypeBuilder tb = en.TypeBuilder;
1577                                                 if (tb != null && (filter (tb, criteria) == true)) {
1578                                                         if (members == null)
1579                                                                 members = new ArrayList ();
1580                                                         
1581                                                         members.Add (tb);
1582                                                 }
1583                                         }
1584                                 }
1585                                 
1586                                 if (delegates != null) {
1587                                         int len = delegates.Count;
1588                                         for (int i = 0; i < len; i++) {
1589                                                 Delegate d = (Delegate) delegates [i];
1590                                                 
1591                                                 if ((d.ModFlags & modflags) == 0)
1592                                                         continue;
1593
1594                                                 TypeBuilder tb = d.TypeBuilder;
1595                                                 if (tb != null && (filter (tb, criteria) == true)) {
1596                                                         if (members == null)
1597                                                                 members = new ArrayList ();
1598                                                         
1599                                                         members.Add (tb);
1600                                                 }
1601                                         }
1602                                 }
1603
1604                                 if (interfaces != null) {
1605                                         int len = interfaces.Count;
1606                                         for (int i = 0; i < len; i++) {
1607                                                 Interface iface = (Interface) interfaces [i];
1608                                                 
1609                                                 if ((iface.ModFlags & modflags) == 0)
1610                                                         continue;
1611
1612                                                 TypeBuilder tb = iface.TypeBuilder;
1613                                                 if (tb != null && (filter (tb, criteria) == true)) {
1614                                                         if (members == null)
1615                                                                 members = new ArrayList ();
1616                                                         
1617                                                         members.Add (tb);
1618                                                 }
1619                                         }
1620                                 }
1621                         }
1622
1623                         if ((mt & MemberTypes.Constructor) != 0){
1624                                 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1625                                         int len = instance_constructors.Count;
1626                                         for (int i = 0; i < len; i++) {
1627                                                 Constructor c = (Constructor) instance_constructors [i];
1628                                                 
1629                                                 ConstructorBuilder cb = c.ConstructorBuilder;
1630                                                 if (cb != null && filter (cb, criteria) == true) {
1631                                                         if (members == null)
1632                                                                 members = new ArrayList ();
1633                                                         
1634                                                         members.Add (cb);
1635                                                 }
1636                                         }
1637                                 }
1638
1639                                 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1640                                         ConstructorBuilder cb =
1641                                                 default_static_constructor.ConstructorBuilder;
1642                                         
1643                                         if (cb != null && filter (cb, criteria) == true) {
1644                                                 if (members == null)
1645                                                         members = new ArrayList ();
1646                                                 
1647                                                 members.Add (cb);
1648                                         }
1649                                 }
1650                         }
1651
1652                         //
1653                         // Lookup members in parent if requested.
1654                         //
1655                         if ((bf & BindingFlags.DeclaredOnly) == 0) {
1656                                 if (TypeBuilder.BaseType != null) {
1657                                         MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1658                                         if (list.Count > 0) {
1659                                                 if (members == null)
1660                                                         members = new ArrayList ();
1661                                         
1662                                                 members.AddRange (list);
1663                                         }
1664                                 }
1665                                 if (base_inteface_types != null) {
1666                                         foreach (Type base_type in base_inteface_types) {
1667                                                 MemberList list = TypeContainer.FindMembers (base_type, mt, bf, filter, criteria);
1668
1669                                                 if (list.Count > 0) {
1670                                                         if (members == null)
1671                                                                 members = new ArrayList ();
1672                                                         members.AddRange (list);
1673                                                 }
1674                                         }
1675                                 }
1676                         }
1677
1678                         Timer.StopTimer (TimerType.TcFindMembers);
1679
1680                         if (members == null)
1681                                 return MemberList.Empty;
1682                         else
1683                                 return new MemberList (members);
1684                 }
1685
1686                 public override MemberCache MemberCache {
1687                         get {
1688                                 return member_cache;
1689                         }
1690                 }
1691
1692                 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1693                                                       MemberFilter filter, object criteria)
1694                 {
1695                         DeclSpace ds = TypeManager.LookupDeclSpace (t);
1696
1697                         if (ds != null)
1698                                 return ds.FindMembers (mt, bf, filter, criteria);
1699                         else
1700                                 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1701                         
1702                 }
1703
1704                 //
1705                 // FindMethods will look for methods not only in the type `t', but in
1706                 // any interfaces implemented by the type.
1707                 //
1708                 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1709                                                          MemberFilter filter, object criteria)
1710                 {
1711                         return null;
1712                 }
1713
1714                 /// <summary>
1715                 ///   Emits the values for the constants
1716                 /// </summary>
1717                 public void EmitConstants ()
1718                 {
1719                         if (constants != null)
1720                                 foreach (Const con in constants)
1721                                         con.Emit (this);
1722                         return;
1723                 }
1724
1725                 protected virtual void VerifyMembers (EmitContext ec)
1726                 {
1727                         //
1728                         // Check for internal or private fields that were never assigned
1729                         //
1730                         if (RootContext.WarningLevel >= 3) {
1731                                 if (fields != null){
1732                                         foreach (Field f in fields) {
1733                                                 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1734                                                         continue;
1735                                                 
1736                                                 if ((f.status & Field.Status.USED) == 0){
1737                                                         Report.Warning (
1738                                                                 169, f.Location, "Private field " +
1739                                                                 MakeName (f.Name) + " is never used");
1740                                                         continue;
1741                                                 }
1742                                                 
1743                                                 //
1744                                                 // Only report 649 on level 4
1745                                                 //
1746                                                 if (RootContext.WarningLevel < 4)
1747                                                         continue;
1748                                                 
1749                                                 if ((f.status & Field.Status.ASSIGNED) != 0)
1750                                                         continue;
1751                                                 
1752                                                 Report.Warning (
1753                                                         649, f.Location,
1754                                                         "Field " + MakeName (f.Name) + " is never assigned " +
1755                                                         " to and will always have its default value");
1756                                         }
1757                                 }
1758
1759                                 if (events != null){
1760                                         foreach (Event e in events){
1761                                                 if (e.status == 0)
1762                                                         Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1763                                         }
1764                                 }
1765                         }
1766                 }
1767
1768                 /// <summary>
1769                 ///   Emits the code, this step is performed after all
1770                 ///   the types, enumerations, constructors
1771                 /// </summary>
1772                 public void Emit ()
1773                 {
1774                         if (OptAttributes != null)
1775                                 OptAttributes.Emit (ec, this);
1776                                 
1777                         Emit (this);
1778
1779                         if (instance_constructors != null) {
1780                                 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && IsClsCompliaceRequired (this)) {
1781                                         bool has_compliant_args = false;
1782
1783                                         foreach (Constructor c in instance_constructors) {
1784                                                 c.Emit (this);
1785
1786                                                 if (has_compliant_args)
1787                                                         continue;
1788
1789                                                 has_compliant_args = c.HasCompliantArgs;
1790                                         }
1791                                         if (!has_compliant_args)
1792                                                 Report.Error_T (3015, Location, GetSignatureForError ());
1793                                 } else {
1794                                         foreach (Constructor c in instance_constructors)
1795                                                 c.Emit (this);
1796                                 }
1797                         }
1798
1799                         if (default_static_constructor != null)
1800                                 default_static_constructor.Emit (this);
1801                         
1802                         if (methods != null)
1803                                 foreach (Method m in methods)
1804                                         m.Emit (this);
1805
1806                         if (operators != null)
1807                                 foreach (Operator o in operators)
1808                                         o.Emit (this);
1809
1810                         if (properties != null)
1811                                 foreach (Property p in properties)
1812                                         p.Emit (this);
1813
1814                         if (indexers != null){
1815                                 foreach (Indexer ix in indexers)
1816                                         ix.Emit (this);
1817                                 if (IndexerName != null) {
1818                                         CustomAttributeBuilder cb = EmitDefaultMemberAttr ();
1819                                         TypeBuilder.SetCustomAttribute (cb);
1820                                 }
1821                         }
1822                         
1823                         if (fields != null)
1824                                 foreach (Field f in fields)
1825                                         f.Emit (this);
1826
1827                         if (events != null){
1828                                 foreach (Event e in Events)
1829                                         e.Emit (this);
1830                         }
1831
1832                         if (delegates != null) {
1833                                 foreach (Delegate d in Delegates) {
1834                                         d.Emit (this);
1835                                 }
1836                         }
1837
1838                         if (Pending != null)
1839                                 if (Pending.VerifyPendingMethods ())
1840                                         return;
1841
1842                         VerifyMembers (ec);
1843                         
1844 //                      if (types != null)
1845 //                              foreach (TypeContainer tc in types)
1846 //                                      tc.Emit ();
1847                 }
1848
1849                 CustomAttributeBuilder EmitDefaultMemberAttr ()
1850                 {
1851                         EmitContext ec = new EmitContext (this, Location, null, null, ModFlags);
1852
1853                         Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
1854                                                                  ".ctor", MemberTypes.Constructor,
1855                                                                  BindingFlags.Public | BindingFlags.Instance,
1856                                                                  Location.Null);
1857                         
1858                         MethodGroupExpr mg = (MethodGroupExpr) ml;
1859
1860                         MethodBase constructor = mg.Methods [0];
1861
1862                         string [] vals = { IndexerName };
1863
1864                         CustomAttributeBuilder cb = null;
1865                         try {
1866                                 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
1867                         } catch {
1868                                 Report.Warning (-100, "Can not set the indexer default member attribute");
1869                         }
1870
1871                         return cb;
1872                 }
1873
1874                 public override void CloseType ()
1875                 {
1876                         if ((caching_flags & Flags.CloseTypeCreated) != 0)
1877                                 return;
1878                         
1879                         try {
1880                                 caching_flags |= Flags.CloseTypeCreated;
1881                                 TypeBuilder.CreateType ();
1882                         } catch (TypeLoadException){
1883                                 //
1884                                 // This is fine, the code still created the type
1885                                 //
1886 //                              Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1887 //                              Console.WriteLine (e.Message);
1888                         } catch {
1889                                 Console.WriteLine ("In type: " + Name);
1890                                 throw;
1891                         }
1892                         
1893                         if (Enums != null)
1894                                 foreach (Enum en in Enums)
1895                                         en.CloseType ();
1896
1897                         if (interface_order != null){
1898                                 foreach (Interface iface in interface_order)
1899                                         iface.CloseType ();
1900                         }
1901                         
1902                         if (Types != null){
1903                                 foreach (TypeContainer tc in Types)
1904                                         if (tc is Struct)
1905                                                 tc.CloseType ();
1906
1907                                 foreach (TypeContainer tc in Types)
1908                                         if (!(tc is Struct))
1909                                                 tc.CloseType ();
1910                         }
1911
1912                         if (Delegates != null)
1913                                 foreach (Delegate d in Delegates)
1914                                         d.CloseType ();
1915                         
1916                         types = null;
1917                         properties = null;
1918                         enums = null;
1919                         delegates = null;
1920                         fields = null;
1921                         initialized_fields = null;
1922                         initialized_static_fields = null;
1923                         constants = null;
1924                         interfaces = null;
1925                         interface_order = null;
1926                         methods = null;
1927                         events = null;
1928                         indexers = null;
1929                         operators = null;
1930                         ec = null;
1931                         default_constructor = null;
1932                         default_static_constructor = null;
1933                         type_bases = null;
1934                         OptAttributes = null;
1935                         ifaces = null;
1936                         parent_container = null;
1937                         member_cache = null;
1938                 }
1939
1940                 public string MakeName (string n)
1941                 {
1942                         return "`" + Name + "." + n + "'";
1943                 }
1944
1945                 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1946                 {
1947                         Report.Warning (
1948                                 108, l, "The keyword new is required on " + 
1949                                 MakeName (mi.Name) + " because it hides `" +
1950                                 mi.ReflectedType.Name + "." + mi.Name + "'");
1951                 }
1952
1953                 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
1954                 {
1955                         Report.Warning (
1956                                 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1957                                 "inherited member, the keyword new is not required");
1958                 }
1959
1960                 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
1961                 {
1962                         Report.Error (
1963                                 72, l, MakeName (mi.Name) + " : cannot override; `" +
1964                                 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
1965                 }
1966                 
1967                 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1968                 {
1969                         return 0;
1970                 }
1971
1972                 //
1973                 // Performs the validation on a Method's modifiers (properties have
1974                 // the same properties).
1975                 //
1976                 public bool MethodModifiersValid (int flags, string n, Location loc)
1977                 {
1978                         const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1979                         const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1980                         const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1981                         bool ok = true;
1982                         
1983                         //
1984                         // At most one of static, virtual or override
1985                         //
1986                         if ((flags & Modifiers.STATIC) != 0){
1987                                 if ((flags & vao) != 0){
1988                                         Report.Error (
1989                                                 112, loc, "static method " + MakeName (n) + "can not be marked " +
1990                                                 "as virtual, abstract or override");
1991                                         ok = false;
1992                                 }
1993                         }
1994
1995                         if (this is Struct){
1996                                 if ((flags & va) != 0){
1997                                         Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1998                                         ok = false;
1999                                 }
2000                         }
2001
2002                         if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2003                                 Report.Error (
2004                                         113, loc, MakeName (n) +
2005                                         " marked as override cannot be marked as new or virtual");
2006                                 ok = false;
2007                         }
2008
2009                         //
2010                         // If the declaration includes the abstract modifier, then the
2011                         // declaration does not include static, virtual or extern
2012                         //
2013                         if ((flags & Modifiers.ABSTRACT) != 0){
2014                                 if ((flags & Modifiers.EXTERN) != 0){
2015                                         Report.Error (
2016                                                 180, loc, MakeName (n) + " can not be both abstract and extern");
2017                                         ok = false;
2018                                 }
2019
2020                                 if ((flags & Modifiers.VIRTUAL) != 0){
2021                                         Report.Error (
2022                                                 503, loc, MakeName (n) + " can not be both abstract and virtual");
2023                                         ok = false;
2024                                 }
2025
2026                                 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2027                                         Report.Error (
2028                                                 513, loc, MakeName (n) +
2029                                                 " is abstract but its container class is not");
2030                                         ok = false;
2031
2032                                 }
2033                         }
2034
2035                         if ((flags & Modifiers.PRIVATE) != 0){
2036                                 if ((flags & vao) != 0){
2037                                         Report.Error (
2038                                                 621, loc, MakeName (n) +
2039                                                 " virtual or abstract members can not be private");
2040                                         ok = false;
2041                                 }
2042                         }
2043
2044                         if ((flags & Modifiers.SEALED) != 0){
2045                                 if ((flags & Modifiers.OVERRIDE) == 0){
2046                                         Report.Error (
2047                                                 238, loc, MakeName (n) +
2048                                                 " cannot be sealed because it is not an override");
2049                                         ok = false;
2050                                 }
2051                         }
2052
2053                         return ok;
2054                 }
2055
2056                 Hashtable builder_and_args;
2057                 
2058                 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
2059                 {
2060                         if (builder_and_args == null)
2061                                 builder_and_args = new Hashtable ();
2062                         return true;
2063                 }
2064
2065                 protected override bool VerifyClsCompliance (DeclSpace ds)
2066                 {
2067                         if (!base.VerifyClsCompliance (ds))
2068                                 return false;
2069
2070                         // parent_container is null for System.Object
2071                         if (parent_container != null && !AttributeTester.IsClsCompliant (parent_container.Type)) {
2072                                 Report.Error_T (3009, Location, GetSignatureForError (),  TypeManager.CSharpName (parent_container.Type));
2073                         }
2074                         return true;
2075                 }
2076
2077
2078                 /// <summary>
2079                 ///   Performs checks for an explicit interface implementation.  First it
2080                 ///   checks whether the `interface_type' is a base inteface implementation.
2081                 ///   Then it checks whether `name' exists in the interface type.
2082                 /// </summary>
2083                 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
2084                 {
2085                         bool found = false;
2086
2087                         if (ifaces != null){
2088                                 foreach (TypeExpr t in ifaces){
2089                                         if (t.Type == interface_type){
2090                                                 found = true;
2091                                                 break;
2092                                         }
2093                                 }
2094                         }
2095                         
2096                         if (!found){
2097                                 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
2098                                 return false;
2099                         }
2100
2101                         return true;
2102                 }
2103
2104                 //
2105                 // IMemberContainer
2106                 //
2107
2108                 string IMemberContainer.Name {
2109                         get {
2110                                 return Name;
2111                         }
2112                 }
2113
2114                 Type IMemberContainer.Type {
2115                         get {
2116                                 return TypeBuilder;
2117                         }
2118                 }
2119
2120                 IMemberContainer IMemberContainer.Parent {
2121                         get {
2122                                 return parent_container;
2123                         }
2124                 }
2125
2126                 MemberCache IMemberContainer.MemberCache {
2127                         get {
2128                                 return member_cache;
2129                         }
2130                 }
2131
2132                 bool IMemberContainer.IsInterface {
2133                         get {
2134                                 return this is Interface;
2135                         }
2136                 }
2137
2138                 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2139                 {
2140                         return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
2141                 }
2142
2143                 //
2144                 // Operator pair checking
2145                 //
2146
2147                 class OperatorEntry {
2148                         public int flags;
2149                         public Type ret_type;
2150                         public Type type1, type2;
2151                         public Operator op;
2152                         public Operator.OpType ot;
2153                         
2154                         public OperatorEntry (int f, Operator o)
2155                         {
2156                                 flags = f;
2157
2158                                 ret_type = o.OperatorMethod.GetReturnType ();
2159                                 Type [] pt = o.OperatorMethod.ParameterTypes;
2160                                 type1 = pt [0];
2161                                 type2 = pt [1];
2162                                 op = o;
2163                                 ot = o.OperatorType;
2164                         }
2165
2166                         public override int GetHashCode ()
2167                         {       
2168                                 return ret_type.GetHashCode ();
2169                         }
2170
2171                         public override bool Equals (object o)
2172                         {
2173                                 OperatorEntry other = (OperatorEntry) o;
2174
2175                                 if (other.ret_type != ret_type)
2176                                         return false;
2177                                 if (other.type1 != type1)
2178                                         return false;
2179                                 if (other.type2 != type2)
2180                                         return false;
2181                                 return true;
2182                         }
2183                 }
2184                                 
2185                 //
2186                 // Checks that some operators come in pairs:
2187                 //  == and !=
2188                 // > and <
2189                 // >= and <=
2190                 // true and false
2191                 //
2192                 // They are matched based on the return type and the argument types
2193                 //
2194                 void CheckPairedOperators ()
2195                 {
2196                         Hashtable pairs = new Hashtable (null, null);
2197                         Operator true_op = null;
2198                         Operator false_op = null;
2199                         bool has_equality_or_inequality = false;
2200                         
2201                         // Register all the operators we care about.
2202                         foreach (Operator op in operators){
2203                                 int reg = 0;
2204                                 
2205                                 switch (op.OperatorType){
2206                                 case Operator.OpType.Equality:
2207                                         reg = 1;
2208                                         has_equality_or_inequality = true;
2209                                         break;
2210                                 case Operator.OpType.Inequality:
2211                                         reg = 2;
2212                                         has_equality_or_inequality = true;
2213                                         break;
2214
2215                                 case Operator.OpType.True:
2216                                         true_op = op;
2217                                         break;
2218                                 case Operator.OpType.False:
2219                                         false_op = op;
2220                                         break;
2221                                         
2222                                 case Operator.OpType.GreaterThan:
2223                                         reg = 1; break;
2224                                 case Operator.OpType.LessThan:
2225                                         reg = 2; break;
2226                                         
2227                                 case Operator.OpType.GreaterThanOrEqual:
2228                                         reg = 1; break;
2229                                 case Operator.OpType.LessThanOrEqual:
2230                                         reg = 2; break;
2231                                 }
2232                                 if (reg == 0)
2233                                         continue;
2234
2235                                 OperatorEntry oe = new OperatorEntry (reg, op);
2236
2237                                 object o = pairs [oe];
2238                                 if (o == null)
2239                                         pairs [oe] = oe;
2240                                 else {
2241                                         oe = (OperatorEntry) o;
2242                                         oe.flags |= reg;
2243                                 }
2244                         }
2245
2246                         if (true_op != null){
2247                                 if (false_op == null)
2248                                         Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2249                         } else if (false_op != null)
2250                                 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2251                         
2252                         //
2253                         // Look for the mistakes.
2254                         //
2255                         foreach (DictionaryEntry de in pairs){
2256                                 OperatorEntry oe = (OperatorEntry) de.Key;
2257
2258                                 if (oe.flags == 3)
2259                                         continue;
2260
2261                                 string s = "";
2262                                 switch (oe.ot){
2263                                 case Operator.OpType.Equality:
2264                                         s = "!=";
2265                                         break;
2266                                 case Operator.OpType.Inequality: 
2267                                         s = "==";
2268                                         break;
2269                                 case Operator.OpType.GreaterThan: 
2270                                         s = "<";
2271                                         break;
2272                                 case Operator.OpType.LessThan:
2273                                         s = ">";
2274                                         break;
2275                                 case Operator.OpType.GreaterThanOrEqual:
2276                                         s = "<=";
2277                                         break;
2278                                 case Operator.OpType.LessThanOrEqual:
2279                                         s = ">=";
2280                                         break;
2281                                 }
2282                                 Report.Error (216, oe.op.Location,
2283                                               "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2284                         }
2285
2286                         if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2287                                 MethodSignature equals_ms = new MethodSignature (
2288                                         "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2289                                 MethodSignature hash_ms = new MethodSignature (
2290                                         "GetHashCode", TypeManager.int32_type, new Type [0]);
2291
2292                                 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2293                                                                     BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2294                                                                     equals_ms);
2295                                 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2296                                                                   BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2297                                                                   hash_ms);
2298
2299                                 bool equals_ok = false;
2300                                 if ((equals_ml != null) && (equals_ml.Count == 1))
2301                                         equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2302                                 bool hash_ok = false;
2303                                 if ((hash_ml != null) && (hash_ml.Count == 1))
2304                                         hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2305
2306                                 if (!equals_ok)
2307                                         Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2308                                                         "not override Object.Equals (object o)");
2309                                 if (!hash_ok)
2310                                         Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2311                                                         "not override Object.GetHashCode ()");
2312                         }
2313                 }
2314                 
2315                 
2316         }
2317
2318         public class ClassOrStruct : TypeContainer {
2319                 bool hasExplicitLayout = false;
2320                 public ClassOrStruct (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
2321                         : base (ns, parent, name, attrs, l)
2322                 {
2323                 }
2324
2325                 protected override void VerifyMembers (EmitContext ec) 
2326                 {
2327                         if (Fields != null) {
2328                                 foreach (Field f in Fields) {
2329                                         if ((f.ModFlags & Modifiers.STATIC) != 0)
2330                                                 continue;
2331                                         if (hasExplicitLayout) {
2332                                                 if (f.OptAttributes == null 
2333                                                     || !f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2334                                                         Report.Error (625, f.Location,
2335                                                                       "Instance field of type marked with" 
2336                                                                       + " StructLayout(LayoutKind.Explicit) must have a"
2337                                                                       + " FieldOffset attribute.");
2338                                                 }
2339                                         }
2340                                         else {
2341                                                 if (f.OptAttributes != null 
2342                                                     && f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2343                                                         Report.Error (636, f.Location,
2344                                                                       "The FieldOffset attribute can only be placed on members of "
2345                                                                       + "types marked with the StructLayout(LayoutKind.Explicit)");
2346                                                 }
2347                                         }
2348                                 }
2349                         }
2350                         base.VerifyMembers (ec);
2351                 }
2352
2353                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2354                 {
2355                         if (a.Type == TypeManager.struct_layout_attribute_type
2356                             && (LayoutKind) a.GetPositionalValue (0) == LayoutKind.Explicit)
2357                                 hasExplicitLayout = true;
2358
2359                         base.ApplyAttributeBuilder (a, cb);
2360                 }
2361         }
2362
2363         public class Class : ClassOrStruct {
2364                 // <summary>
2365                 //   Modifiers allowed in a class declaration
2366                 // </summary>
2367                 public const int AllowedModifiers =
2368                         Modifiers.NEW |
2369                         Modifiers.PUBLIC |
2370                         Modifiers.PROTECTED |
2371                         Modifiers.INTERNAL |
2372                         Modifiers.PRIVATE |
2373                         Modifiers.ABSTRACT |
2374                         Modifiers.SEALED |
2375                         Modifiers.UNSAFE;
2376
2377
2378                 // Information in the case we are an attribute type
2379                 AttributeUsageAttribute attribute_usage;
2380
2381                 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2382                               Attributes attrs, Location l)
2383                         : base (ns, parent, name, attrs, l)
2384                 {
2385                         int accmods;
2386
2387                         if (parent.Parent == null)
2388                                 accmods = Modifiers.INTERNAL;
2389                         else
2390                                 accmods = Modifiers.PRIVATE;
2391
2392                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2393                         attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
2394                 }
2395
2396                 public override AttributeTargets AttributeTargets {
2397                         get {
2398                                 return AttributeTargets.Class;
2399                         }
2400                 }
2401
2402                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
2403                 {
2404                         if (a.UsageAttribute != null)
2405                                 attribute_usage = a.UsageAttribute;
2406
2407                         base.ApplyAttributeBuilder (a, cb);
2408                 }
2409
2410                 public AttributeUsageAttribute AttributeUsage {
2411                         get {
2412                                 return attribute_usage;
2413                         }
2414                 }
2415
2416                 //
2417                 // FIXME: How do we deal with the user specifying a different
2418                 // layout?
2419                 //
2420                 public override TypeAttributes TypeAttr {
2421                         get {
2422                                 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2423                         }
2424                 }
2425         }
2426
2427         public class Struct : ClassOrStruct {
2428                 // <summary>
2429                 //   Modifiers allowed in a struct declaration
2430                 // </summary>
2431                 public const int AllowedModifiers =
2432                         Modifiers.NEW       |
2433                         Modifiers.PUBLIC    |
2434                         Modifiers.PROTECTED |
2435                         Modifiers.INTERNAL  |
2436                         Modifiers.UNSAFE    |
2437                         Modifiers.PRIVATE;
2438
2439                 public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2440                         : base (ns, parent, name, attrs, l)
2441                 {
2442                         int accmods;
2443                         
2444                         if (parent.Parent == null)
2445                                 accmods = Modifiers.INTERNAL;
2446                         else
2447                                 accmods = Modifiers.PRIVATE;
2448                         
2449                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2450
2451                         this.ModFlags |= Modifiers.SEALED;
2452                 }
2453
2454                 public override AttributeTargets AttributeTargets {
2455                         get {
2456                                 return AttributeTargets.Struct;
2457                         }
2458                 }
2459
2460
2461                 //
2462                 // FIXME: Allow the user to specify a different set of attributes
2463                 // in some cases (Sealed for example is mandatory for a class,
2464                 // but what SequentialLayout can be changed
2465                 //
2466                 public override TypeAttributes TypeAttr {
2467                         get {
2468                                 return base.TypeAttr |
2469                                         TypeAttributes.SequentialLayout |
2470                                         TypeAttributes.Sealed |
2471                                         TypeAttributes.BeforeFieldInit;
2472                         }
2473                 }
2474         }
2475
2476         /// <summary>
2477         ///   Interfaces
2478         /// </summary>
2479         public class Interface : TypeContainer, IMemberContainer {
2480                 /// <summary>
2481                 ///   Modifiers allowed in a class declaration
2482                 /// </summary>
2483                 public const int AllowedModifiers =
2484                         Modifiers.NEW       |
2485                         Modifiers.PUBLIC    |
2486                         Modifiers.PROTECTED |
2487                         Modifiers.INTERNAL  |
2488                         Modifiers.UNSAFE    |
2489                         Modifiers.PRIVATE;
2490
2491                 public Interface (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2492                                   Attributes attrs, Location l)
2493                         : base (ns, parent, name, attrs, l)
2494                 {
2495                         int accmods;
2496
2497                         if (parent.Parent == null)
2498                                 accmods = Modifiers.INTERNAL;
2499                         else
2500                                 accmods = Modifiers.PRIVATE;
2501
2502                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2503                 }
2504
2505                 public override AttributeTargets AttributeTargets {
2506                         get {
2507                                 return AttributeTargets.Interface;
2508                         }
2509                 }
2510
2511                 public override TypeAttributes TypeAttr {
2512                         get {
2513                                 return base.TypeAttr |
2514                                         TypeAttributes.AutoLayout |
2515                                         TypeAttributes.Abstract |
2516                                         TypeAttributes.Interface;
2517                         }
2518                 }
2519         }
2520
2521         public abstract class MethodCore : MemberBase {
2522                 public readonly Parameters Parameters;
2523                 protected Block block;
2524                 public DeclSpace ds;
2525                 
2526                 //
2527                 // Parameters, cached for semantic analysis.
2528                 //
2529                 protected InternalParameters parameter_info;
2530                 protected Type [] parameter_types;
2531
2532                 // <summary>
2533                 //   This is set from TypeContainer.DefineMembers if this method overrides something.
2534                 // </summary>
2535                 public bool OverridesSomething;
2536
2537                 // Whether this is an operator method.
2538                 public bool IsOperator;
2539
2540                 static string[] attribute_targets = new string [] { "method", "return" };
2541
2542                 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2543                                    bool is_interface, string name, Attributes attrs,
2544                                    Parameters parameters, Location loc)
2545                         : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2546                 {
2547                         Parameters = parameters;
2548                         IsInterface = is_interface;
2549                         this.ds = ds;
2550                 }
2551                 
2552                 //
2553                 //  Returns the System.Type array for the parameters of this method
2554                 //
2555                 public Type [] ParameterTypes {
2556                         get {
2557                                 return parameter_types;
2558                         }
2559                 }
2560
2561                 public InternalParameters ParameterInfo
2562                 {
2563                         get {
2564                                 return parameter_info;
2565                         }
2566                 }
2567                 
2568                 public Block Block {
2569                         get {
2570                                 return block;
2571                         }
2572
2573                         set {
2574                                 block = value;
2575                         }
2576                 }
2577
2578                 protected virtual bool DoDefineParameters ()
2579                 {
2580                         // Check if arguments were correct
2581                         parameter_types = Parameters.GetParameterInfo (ds);
2582                         if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2583                                 return false;
2584
2585                         parameter_info = new InternalParameters (ds, Parameters);
2586
2587                         Parameter array_param = Parameters.ArrayParameter;
2588                         if ((array_param != null) &&
2589                             (!array_param.ParameterType.IsArray ||
2590                              (array_param.ParameterType.GetArrayRank () != 1))) {
2591                                 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2592                                 return false;
2593                         }
2594
2595                         return true;
2596                 }
2597
2598                 protected override string[] ValidAttributeTargets {
2599                         get {
2600                                 return attribute_targets;
2601                         }
2602                 }
2603
2604                 protected override bool VerifyClsCompliance (DeclSpace ds)
2605                 {
2606                         if (!base.VerifyClsCompliance (ds)) {
2607                                 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
2608                                         Report.Error_T (3011, Location, GetSignatureForError ());
2609                                 }
2610                                 return false;
2611                         }
2612
2613                         AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
2614
2615                         if (!AttributeTester.IsClsCompliant (MemberType)) {
2616                                 Report.Error_T (3002, Location, GetSignatureForError ());
2617                         }
2618
2619                         return true;
2620                 }
2621
2622                 protected bool IsDuplicateImplementation (TypeContainer tc, MethodCore method)
2623                 {
2624                         if ((method == this) || (method.Name != Name))
2625                                 return false;
2626
2627                         Type[] param_types = method.ParameterTypes;
2628                         if (param_types == null)
2629                                 return false;
2630
2631                         if (param_types.Length != ParameterTypes.Length)
2632                                 return false;
2633
2634                         for (int i = 0; i < param_types.Length; i++)
2635                                 if (param_types [i] != ParameterTypes [i])
2636                                         return false;
2637
2638                         //
2639                         // Try to report 663: method only differs on out/ref
2640                         //
2641                         ParameterData info = ParameterInfo;
2642                         ParameterData other_info = method.ParameterInfo;
2643                         for (int i = 0; i < info.Count; i++){
2644                                 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
2645                                         Report.Error (663, Location, "Overload method only differs in parameter modifier");
2646                                         return false;
2647                                 }
2648                         }
2649
2650                         Report.Error (111, Location, "Class `{0}' already defines a " +
2651                                       "member called `{1}' with the same parameter types",
2652                                       tc.Name, Name);
2653                         return true;
2654                 }
2655
2656                 public CallingConventions GetCallingConvention (bool is_class)
2657                 {
2658                         CallingConventions cc = 0;
2659                         
2660                         cc = Parameters.GetCallingConvention ();
2661
2662                         if (is_class)
2663                                 if ((ModFlags & Modifiers.STATIC) == 0)
2664                                         cc |= CallingConventions.HasThis;
2665
2666                         // FIXME: How is `ExplicitThis' used in C#?
2667                         
2668                         return cc;
2669                 }
2670         }
2671
2672         public class Method : MethodCore, IIteratorContainer, IMethodData {
2673                 public MethodBuilder MethodBuilder;
2674                 public MethodData MethodData;
2675                 ReturnParameter return_attributes;
2676
2677                 /// <summary>
2678                 ///   Modifiers allowed in a class declaration
2679                 /// </summary>
2680                 const int AllowedModifiers =
2681                         Modifiers.NEW |
2682                         Modifiers.PUBLIC |
2683                         Modifiers.PROTECTED |
2684                         Modifiers.INTERNAL |
2685                         Modifiers.PRIVATE |
2686                         Modifiers.STATIC |
2687                         Modifiers.VIRTUAL |
2688                         Modifiers.SEALED |
2689                         Modifiers.OVERRIDE |
2690                         Modifiers.ABSTRACT |
2691                         Modifiers.UNSAFE |
2692                         Modifiers.METHOD_YIELDS | 
2693                         Modifiers.EXTERN;
2694
2695                 const int AllowedInterfaceModifiers =
2696                         Modifiers.NEW | Modifiers.UNSAFE;
2697
2698                 //
2699                 // return_type can be "null" for VOID values.
2700                 //
2701                 public Method (DeclSpace ds, Expression return_type, int mod, bool is_iface,
2702                                string name, Parameters parameters, Attributes attrs, Location l)
2703                         : base (ds, return_type, mod,
2704                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
2705                                 is_iface, name, attrs, parameters, l)
2706                 {
2707                 }
2708
2709                 public override AttributeTargets AttributeTargets {
2710                         get {
2711                                 return AttributeTargets.Method | AttributeTargets.ReturnValue;
2712                         }
2713                 }
2714                 
2715                 //
2716                 // Returns the `System.Type' for the ReturnType of this
2717                 // function.  Provides a nice cache.  (used between semantic analysis
2718                 // and actual code generation
2719                 //
2720                 public Type GetReturnType ()
2721                 {
2722                         return MemberType;
2723                 }
2724
2725                 public override string GetSignatureForError()
2726                 {
2727                         return TypeManager.CSharpSignature (MethodBuilder);
2728                 }
2729
2730                 void DuplicateEntryPoint (MethodInfo b, Location location)
2731                 {
2732                         Report.Error (
2733                                 17, location,
2734                                 "Program `" + CodeGen.FileName +
2735                                 "'  has more than one entry point defined: `" +
2736                                 TypeManager.CSharpSignature(b) + "'");
2737                 }
2738
2739                 void Report28 (MethodInfo b)
2740                 {
2741                         Report.Warning (
2742                                 28, Location,
2743                                 "`" + TypeManager.CSharpSignature(b) +
2744                                 "' has the wrong signature to be an entry point");
2745                 }
2746
2747                 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2748                 {
2749                         if (b.ReturnType != TypeManager.void_type &&
2750                             b.ReturnType != TypeManager.int32_type)
2751                                 return false;
2752
2753                         if (pinfo.Count == 0)
2754                                 return true;
2755
2756                         if (pinfo.Count > 1)
2757                                 return false;
2758
2759                         Type t = pinfo.ParameterType(0);
2760                         if (t.IsArray &&
2761                             (t.GetArrayRank() == 1) &&
2762                             (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2763                             (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2764                                 return true;
2765                         else
2766                                 return false;
2767                 }
2768
2769                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2770                 {
2771                         if (a.Target == "return") {
2772                                 if (return_attributes == null)
2773                                         return_attributes = new ReturnParameter (MethodBuilder, Location);
2774
2775                                 return_attributes.ApplyAttributeBuilder (a, cb);
2776                                 return;
2777                         }
2778
2779                         if (a.Type == TypeManager.methodimpl_attr_type && a.IsInternalCall) {
2780                                 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
2781                         }
2782
2783                         if (a.Type == TypeManager.dllimport_type)
2784                                 return;
2785
2786                         MethodBuilder.SetCustomAttribute (cb);
2787                 }
2788
2789                 //
2790                 // Checks our base implementation if any
2791                 //
2792                 protected override bool CheckBase (TypeContainer container)
2793                 {
2794                         base.CheckBase (container);
2795                         
2796                         // Check whether arguments were correct.
2797                         if (!DoDefineParameters ())
2798                                 return false;
2799
2800                         MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2801                         if (IsOperator) {
2802                                 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2803                         } else {
2804                                 //
2805                                 // Check in our class for dups
2806                                 //
2807                                 ArrayList ar = container.Methods;
2808                                 if (ar != null) {
2809                                         int arLen = ar.Count;
2810                                         
2811                                         for (int i = 0; i < arLen; i++) {
2812                                                 Method m = (Method) ar [i];
2813                                                 if (IsDuplicateImplementation (container, m))
2814                                                         return false;
2815                                         }
2816                                 }
2817                         }
2818                         
2819
2820                         //
2821                         // Verify if the parent has a type with the same name, and then
2822                         // check whether we have to create a new slot for it or not.
2823                         //
2824                         Type ptype = container.TypeBuilder.BaseType;
2825
2826                         // ptype is only null for System.Object while compiling corlib.
2827                         if (ptype != null) {
2828                                 
2829                                 //
2830                                 // Explicit implementations do not have `parent' methods, however,
2831                                 // the member cache stores them there. Without this check, we get
2832                                 // an incorrect warning in corlib.
2833                                 //
2834                                 if (! IsExplicitImpl) {
2835                                         parent_method = (MethodInfo)((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
2836                                                 container.TypeBuilder, Name, ParameterTypes, false);
2837                                 }
2838                                 
2839                                 if (parent_method != null) {
2840                                         string name = parent_method.DeclaringType.Name + "." +
2841                                                 parent_method.Name;
2842
2843                                         if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2844                                                 return false;
2845
2846                                         if ((ModFlags & Modifiers.NEW) == 0) {
2847                                                 Type parent_ret = TypeManager.TypeToCoreType (
2848                                                         parent_method.ReturnType);
2849
2850                                                 if (parent_ret != MemberType) {
2851                                                         Report.Error (
2852                                                                 508, Location, container.MakeName (Name) + ": cannot " +
2853                                                                 "change return type when overriding " +
2854                                                                 "inherited member " + name);
2855                                                         return false;
2856                                                 }
2857                                         }
2858                                 } else {
2859                                         if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2860                                                 WarningNotHiding (container);
2861
2862                                         if ((ModFlags & Modifiers.OVERRIDE) != 0){
2863                                                 Report.Error (115, Location,
2864                                                               container.MakeName (Name) +
2865                                                               " no suitable methods found to override");
2866                                         }
2867                                 }
2868                         } else if ((ModFlags & Modifiers.NEW) != 0)
2869                                 WarningNotHiding (container);
2870
2871                         return true;
2872                 }
2873
2874                 //
2875                 // Creates the type
2876                 //
2877                 public override bool Define (TypeContainer container)
2878                 {
2879                         if (!DoDefine (container))
2880                                 return false;
2881
2882                         if (!CheckBase (container))
2883                                 return false;
2884
2885                         MethodData = new MethodData (this, ParameterInfo, ModFlags, flags, true, this);
2886
2887                         if (!MethodData.Define (container))
2888                                 return false;
2889
2890                         //
2891                         // Setup iterator if we are one
2892                         //
2893                         if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2894                                 IteratorHandler ih = new  IteratorHandler (
2895                                             Name, container, MemberType,
2896                                             ParameterTypes, ParameterInfo,
2897                                             ModFlags, Location);
2898
2899                                 Block new_block = ih.Setup (block);
2900                                 if (new_block == null)
2901                                         return false;
2902                                 block = new_block;
2903                         }
2904
2905                         MethodBuilder = MethodData.MethodBuilder;
2906                         
2907                         //
2908                         // This is used to track the Entry Point,
2909                         //
2910                         if (Name == "Main" &&
2911                             ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint && 
2912                             (RootContext.MainClass == null ||
2913                              RootContext.MainClass == container.TypeBuilder.FullName)){
2914                                 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2915                                         if (RootContext.EntryPoint == null) {
2916                                                 RootContext.EntryPoint = MethodBuilder;
2917                                                 RootContext.EntryPointLocation = Location;
2918                                         } else {
2919                                                 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2920                                                 DuplicateEntryPoint (MethodBuilder, Location);
2921                                         }
2922                                 } else                                  
2923                                         Report28(MethodBuilder);
2924                         }
2925
2926                         return true;
2927                 }
2928
2929                 //
2930                 // Emits the code
2931                 // 
2932                 public override void Emit (TypeContainer container)
2933                 {
2934                         MethodData.Emit (container, this);
2935                         base.Emit (container);
2936                         Block = null;
2937                         MethodData = null;
2938                 }
2939
2940                 void IIteratorContainer.SetYields ()
2941                 {
2942                         ModFlags |= Modifiers.METHOD_YIELDS;
2943                 }
2944         
2945                 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
2946                 {
2947                         return IsIdentifierAndParamClsCompliant (ds, Name, MethodBuilder, parameter_types);
2948                 }
2949
2950                 #region IMethodData Members
2951
2952                 public CallingConventions CallingConventions {
2953                         get {
2954                                 CallingConventions cc = Parameters.GetCallingConvention ();
2955
2956                                 if (!IsInterface)
2957                                         if ((ModFlags & Modifiers.STATIC) == 0)
2958                                                 cc |= CallingConventions.HasThis;
2959
2960                                 // FIXME: How is `ExplicitThis' used in C#?
2961                         
2962                                 return cc;
2963                         }
2964                 }
2965
2966                 public Type ReturnType {
2967                         get {
2968                                 return MemberType;
2969                         }
2970                 }
2971
2972                 public string MethodName {
2973                         get {
2974                                 return ShortName;
2975                         }
2976                 }
2977
2978                 public new Location Location {
2979                         get {
2980                                 return base.Location;
2981                         }
2982                 }
2983
2984                 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
2985                 {
2986                         return new EmitContext (tc, ds, Location, ig, ReturnType, ModFlags, false);
2987                 }
2988
2989                 #endregion
2990         }
2991
2992         public abstract class ConstructorInitializer {
2993                 ArrayList argument_list;
2994                 ConstructorInfo parent_constructor;
2995                 Parameters parameters;
2996                 Location loc;
2997                 
2998                 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2999                                                Location loc)
3000                 {
3001                         this.argument_list = argument_list;
3002                         this.parameters = parameters;
3003                         this.loc = loc;
3004                 }
3005
3006                 public ArrayList Arguments {
3007                         get {
3008                                 return argument_list;
3009                         }
3010                 }
3011
3012                 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
3013                 {
3014                         Expression parent_constructor_group;
3015                         Type t;
3016
3017                         ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
3018
3019                         if (argument_list != null){
3020                                 foreach (Argument a in argument_list){
3021                                         if (!a.Resolve (ec, loc))
3022                                                 return false;
3023                                 }
3024                         }
3025                         ec.CurrentBlock = null;
3026
3027                         if (this is ConstructorBaseInitializer) {
3028                                 if (ec.ContainerType.BaseType == null)
3029                                         return true;
3030
3031                                 t = ec.ContainerType.BaseType;
3032                                 if (ec.ContainerType.IsValueType) {
3033                                         Report.Error (522, loc,
3034                                                 "structs cannot call base class constructors");
3035                                         return false;
3036                                 }
3037                         } else
3038                                 t = ec.ContainerType;
3039
3040                         parent_constructor_group = Expression.MemberLookup (
3041                                 ec, t, ".ctor", MemberTypes.Constructor,
3042                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3043                                 loc);
3044                         
3045                         if (parent_constructor_group == null){
3046                                 parent_constructor_group = Expression.MemberLookup (
3047                                         ec, t, ".ctor", MemberTypes.Constructor,
3048                                         BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3049                                         loc);
3050
3051                                 if (parent_constructor_group != null)
3052                                         Report.Error (
3053                                                 112, loc, "`{0}.{1}' is inaccessible due to " +
3054                                                 "its protection level", t.FullName, t.Name);
3055                                 else
3056                                         Report.Error (
3057                                                 1501, loc, "Can not find a constructor for " +
3058                                                 "this argument list");
3059                                 return false;
3060                         }
3061                         
3062                         parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
3063                                 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
3064                         
3065                         if (parent_constructor == null){
3066                                 Report.Error (1501, loc,
3067                                        "Can not find a constructor for this argument list");
3068                                 return false;
3069                         }
3070
3071                         if (parent_constructor == caller_builder){
3072                                 Report.Error (515, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
3073                                 return false;
3074                         }
3075                         
3076                         return true;
3077                 }
3078
3079                 public void Emit (EmitContext ec)
3080                 {
3081                         if (parent_constructor != null){
3082                                 ec.Mark (loc, false);
3083                                 if (ec.IsStatic)
3084                                         Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
3085                                 else
3086                                         Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
3087                         }
3088                 }
3089         }
3090
3091         public class ConstructorBaseInitializer : ConstructorInitializer {
3092                 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
3093                         base (argument_list, pars, l)
3094                 {
3095                 }
3096         }
3097
3098         public class ConstructorThisInitializer : ConstructorInitializer {
3099                 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
3100                         base (argument_list, pars, l)
3101                 {
3102                 }
3103         }
3104         
3105         public class Constructor : MethodCore {
3106                 public ConstructorBuilder ConstructorBuilder;
3107                 public ConstructorInitializer Initializer;
3108
3109                 // <summary>
3110                 //   Modifiers allowed for a constructor.
3111                 // </summary>
3112                 public const int AllowedModifiers =
3113                         Modifiers.PUBLIC |
3114                         Modifiers.PROTECTED |
3115                         Modifiers.INTERNAL |
3116                         Modifiers.STATIC |
3117                         Modifiers.UNSAFE |
3118                         Modifiers.EXTERN |              
3119                         Modifiers.PRIVATE;
3120
3121                 bool has_compliant_args = false;
3122                 //
3123                 // The spec claims that static is not permitted, but
3124                 // my very own code has static constructors.
3125                 //
3126                 public Constructor (DeclSpace ds, string name, int mod, Parameters args,
3127                                     ConstructorInitializer init, Location l)
3128                         : base (ds, null, mod, AllowedModifiers, false, name, null, args, l)
3129                 {
3130                         Initializer = init;
3131                 }
3132
3133                 public override string GetSignatureForError()
3134                 {
3135                         return TypeManager.CSharpSignature (ConstructorBuilder);
3136                 }
3137
3138                 public bool HasCompliantArgs {
3139                         get {
3140                                 return has_compliant_args;
3141                         }
3142                 }
3143
3144                 public override AttributeTargets AttributeTargets {
3145                         get {
3146                                 return AttributeTargets.Constructor;
3147                         }
3148                 }
3149
3150
3151                 //
3152                 // Returns true if this is a default constructor
3153                 //
3154                 public bool IsDefault ()
3155                 {
3156                         if ((ModFlags & Modifiers.STATIC) != 0)
3157                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3158                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty);
3159                         
3160                         else
3161                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3162                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
3163                                         (Initializer is ConstructorBaseInitializer) &&
3164                                         (Initializer.Arguments == null);
3165                 }
3166
3167                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3168                 {
3169                         ConstructorBuilder.SetCustomAttribute (cb);
3170                 }
3171                 
3172                 protected override bool CheckBase (TypeContainer container)
3173                 {
3174                         base.CheckBase (container);
3175                         
3176                         // Check whether arguments were correct.
3177                         if (!DoDefineParameters ())
3178                                 return false;
3179                         
3180                         if ((ModFlags & Modifiers.STATIC) != 0)
3181                                 return true;
3182                         
3183                         if (container is Struct && ParameterTypes.Length == 0) {
3184                                 Report.Error (568, Location, 
3185                                         "Structs can not contain explicit parameterless " +
3186                                         "constructors");
3187                                 return false;
3188                         }
3189                                 
3190                         //
3191                         // Check in our class for dups
3192                         //
3193                         ArrayList ar = container.InstanceConstructors;
3194                         if (ar != null) {
3195                                 int arLen = ar.Count;
3196                                         
3197                                 for (int i = 0; i < arLen; i++) {
3198                                         Constructor m = (Constructor) ar [i];
3199                                         if (IsDuplicateImplementation (container, m))
3200                                                 return false;
3201                                 }
3202                         }
3203                         
3204                         return true;
3205                 }
3206                 
3207                 //
3208                 // Creates the ConstructorBuilder
3209                 //
3210                 public override bool Define (TypeContainer container)
3211                 {
3212                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
3213                                                MethodAttributes.SpecialName);
3214                         
3215                         if ((ModFlags & Modifiers.STATIC) != 0) {
3216                                 ca |= MethodAttributes.Static | MethodAttributes.Private;
3217                         } else {
3218                                 ca |= MethodAttributes.HideBySig;
3219
3220                                 if ((ModFlags & Modifiers.PUBLIC) != 0)
3221                                         ca |= MethodAttributes.Public;
3222                                 else if ((ModFlags & Modifiers.PROTECTED) != 0){
3223                                         if ((ModFlags & Modifiers.INTERNAL) != 0)
3224                                                 ca |= MethodAttributes.FamORAssem;
3225                                         else 
3226                                                 ca |= MethodAttributes.Family;
3227                                 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
3228                                         ca |= MethodAttributes.Assembly;
3229                                 else if (IsDefault ())
3230                                         ca |= MethodAttributes.Public;
3231                                 else
3232                                         ca |= MethodAttributes.Private;
3233                         }
3234                         
3235                         // Check if arguments were correct.
3236                         if (!CheckBase (container))
3237                                 return false;
3238
3239                         ConstructorBuilder = container.TypeBuilder.DefineConstructor (
3240                                 ca, GetCallingConvention (container is Class), ParameterTypes);
3241
3242                         if ((ModFlags & Modifiers.UNSAFE) != 0)
3243                                 ConstructorBuilder.InitLocals = false;
3244                         
3245                         //
3246                         // HACK because System.Reflection.Emit is lame
3247                         //
3248                         TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
3249
3250                         return true;
3251                 }
3252
3253                 //
3254                 // Emits the code
3255                 //
3256                 public override void Emit (TypeContainer container)
3257                 {
3258                         ILGenerator ig = ConstructorBuilder.GetILGenerator ();
3259                         EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
3260
3261                         //
3262                         // extern methods have no bodies
3263                         //
3264                         if ((ModFlags & Modifiers.EXTERN) != 0) {
3265                                 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
3266                                         Report.Error (
3267                                                 179, Location, "External constructor `" +
3268                                                 TypeManager.CSharpSignature (ConstructorBuilder) +
3269                                                 "' can not have a body");
3270                                         return;
3271                                 }
3272                         } else if (block == null) {
3273                                 Report.Error (
3274                                         501, Location, "Constructor `" +
3275                                         TypeManager.CSharpSignature (ConstructorBuilder) +
3276                                         "' must declare a body since it is not marked extern");
3277                                 return;
3278                         }
3279
3280                         if ((ModFlags & Modifiers.STATIC) == 0){
3281                                 if (container is Class && Initializer == null)
3282                                         Initializer = new ConstructorBaseInitializer (
3283                                                 null, Parameters.EmptyReadOnlyParameters, Location);
3284
3285
3286                                 //
3287                                 // Spec mandates that Initializers will not have
3288                                 // `this' access
3289                                 //
3290                                 ec.IsStatic = true;
3291                                 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
3292                                         return;
3293                                 ec.IsStatic = false;
3294                         }
3295
3296                         Parameters.LabelParameters (ec, ConstructorBuilder, Location);
3297                         
3298                         SymbolWriter sw = CodeGen.SymbolWriter;
3299                         bool generate_debugging = false;
3300
3301                         if ((sw != null) && (block != null) &&
3302                                 !Location.IsNull (Location) &&
3303                                 !Location.IsNull (block.EndLocation) &&
3304                                 (Location.SymbolDocument != null)) {
3305                                 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
3306
3307                                 generate_debugging = true;
3308                         }
3309
3310                         //
3311                         // Classes can have base initializers and instance field initializers.
3312                         //
3313                         if (container is Class){
3314                                 if ((ModFlags & Modifiers.STATIC) == 0){
3315
3316                                         //
3317                                         // If we use a "this (...)" constructor initializer, then
3318                                         // do not emit field initializers, they are initialized in the other constructor
3319                                         //
3320                                         if (!(Initializer != null && Initializer is ConstructorThisInitializer))
3321                                                 container.EmitFieldInitializers (ec);
3322                                 }
3323                         }
3324                         if (Initializer != null)
3325                                 Initializer.Emit (ec);
3326                         
3327                         if ((ModFlags & Modifiers.STATIC) != 0)
3328                                 container.EmitFieldInitializers (ec);
3329
3330                         if (OptAttributes != null) 
3331                                 OptAttributes.Emit (ec, this);
3332
3333                         // If this is a non-static `struct' constructor and doesn't have any
3334                         // initializer, it must initialize all of the struct's fields.
3335                         if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
3336                                 Block.AddThisVariable (container, Location);
3337
3338                         ec.EmitTopBlock (block, ParameterInfo, Location);
3339
3340                         if (generate_debugging)
3341                                 sw.CloseMethod ();
3342
3343                         base.Emit (container);
3344
3345                         block = null;
3346                 }
3347
3348                 // For constructors is needed to test only parameters
3349                 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3350                 {
3351                         if (parameter_types == null || parameter_types.Length == 0)
3352                                 return true;
3353
3354                         TypeContainer tc = ds as TypeContainer;
3355
3356                         for (int i = 0; i < tc.InstanceConstructors.Count; i++) {
3357                                 Constructor c = (Constructor) tc.InstanceConstructors [i];
3358                                                 
3359                                 if (c == this || c.ParameterTypes.Length == 0)
3360                                         continue;
3361
3362                                 if (!c.IsClsCompliaceRequired (ds))
3363                                         continue;
3364                                 
3365                                 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, c.ParameterTypes)) {
3366                                         Report.Error_T (3006, Location, GetSignatureForError ());
3367                                         return false;
3368                                 }
3369                         }
3370
3371                         if (tc.TypeBuilder.BaseType == null)
3372                                 return true;
3373
3374                         DeclSpace temp_ds = TypeManager.LookupDeclSpace (tc.TypeBuilder.BaseType);
3375                         if (temp_ds != null)
3376                                 return IsIdentifierClsCompliant (temp_ds);
3377
3378                         MemberInfo[] ml = tc.TypeBuilder.BaseType.FindMembers (MemberTypes.Constructor, BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance, null, null);
3379                         // Skip parameter-less ctor
3380                         if (ml.Length < 2)
3381                                 return true;
3382
3383                         foreach (ConstructorInfo ci in ml) {
3384                                 object[] cls_attribute = ci.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
3385                                 if (cls_attribute.Length == 1 && (!((CLSCompliantAttribute)cls_attribute[0]).IsCompliant))
3386                                         continue;
3387
3388                                 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, TypeManager.GetArgumentTypes (ci))) {
3389                                         Report.Error_T (3006, Location, GetSignatureForError ());
3390                                         return false;
3391                                 }
3392                         }
3393                         
3394                         return true;
3395                 }
3396
3397                 protected override bool VerifyClsCompliance (DeclSpace ds)
3398                 {
3399                         if (!base.VerifyClsCompliance (ds) || !IsExposedFromAssembly (ds)) {
3400                                 return false;
3401                         }
3402                         
3403                         if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
3404                                 foreach (Type param in parameter_types) {
3405                                         if (param.IsArray) {
3406                                                 return false;
3407                                         }
3408                                 }
3409                         }
3410                         has_compliant_args = true;
3411                         return true;
3412                 }
3413
3414         }
3415
3416         /// <summary>
3417         /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
3418         /// </summary>
3419         public interface IMethodData
3420         {
3421                 CallingConventions CallingConventions { get; }
3422                 Location Location { get; }
3423                 string MethodName { get; }
3424                 Type[] ParameterTypes { get; }
3425                 Type ReturnType { get; }
3426
3427                 Attributes OptAttributes { get; }
3428                 Block Block { get; }
3429
3430                 EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
3431         }
3432
3433         //
3434         // Encapsulates most of the Method's state
3435         //
3436         public class MethodData {
3437
3438                 readonly IMethodData method;
3439
3440                 //
3441                 // The return type of this method
3442                 //
3443                 public readonly InternalParameters ParameterInfo;
3444
3445                 //
3446                 // Are we implementing an interface ?
3447                 //
3448                 public bool IsImplementing = false;
3449
3450                 //
3451                 // Protected data.
3452                 //
3453                 protected MemberBase member;
3454                 protected int modifiers;
3455                 protected MethodAttributes flags;
3456                 protected bool is_method;
3457
3458                 //
3459                 // It can either hold a string with the condition, or an arraylist of conditions.
3460                 object conditionals;
3461
3462                 MethodBuilder builder = null;
3463                 public MethodBuilder MethodBuilder {
3464                         get {
3465                                 return builder;
3466                         }
3467                 }
3468
3469                 public MethodData (MemberBase member, InternalParameters parameters,
3470                                    int modifiers, MethodAttributes flags, bool is_method, IMethodData method)
3471                 {
3472                         this.member = member;
3473                         this.ParameterInfo = parameters;
3474                         this.modifiers = modifiers;
3475                         this.flags = flags;
3476                         this.is_method = is_method;
3477                         this.conditionals = null;
3478
3479                         this.method = method;
3480                 }
3481
3482                 //
3483                 // Attributes.
3484                 //
3485                 Attribute dllimport_attribute = null;
3486                 string obsolete = null;
3487                 bool obsolete_error = false;
3488
3489                 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method,
3490                                                      EmitContext ec)
3491                 {
3492                         if ((opt_attrs == null) || (opt_attrs.Attrs == null))
3493                                 return true;
3494
3495                         foreach (Attribute a in opt_attrs.Attrs) {
3496                                 Type attr_type = a.ResolveType (ec, true);
3497                                 if (attr_type == TypeManager.conditional_attribute_type) {
3498                                         if (!ApplyConditionalAttribute (a))
3499                                                 return false;
3500                                 } else if (attr_type == TypeManager.obsolete_attribute_type) {
3501                                         if (!ApplyObsoleteAttribute (a))
3502                                                 return false;
3503                                 } else if (attr_type == TypeManager.dllimport_type) {
3504                                         if (!is_method) {
3505                                                 Attribute.Error_AttributeNotValidForElement (a, method.Location);
3506                                                 return false;
3507                                         }
3508                                         if (!ApplyDllImportAttribute (a))
3509                                                 return false;
3510                                 }
3511                         }
3512
3513                         return true;
3514                 }
3515
3516                 //
3517                 // Applies the `DllImport' attribute to the method.
3518                 //
3519                 protected virtual bool ApplyDllImportAttribute (Attribute a)
3520                 {
3521                         const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3522                         if ((modifiers & extern_static) != extern_static) {
3523                                 Report.Error (601, method.Location,
3524                                               "The DllImport attribute must be specified on a method " +
3525                                               "marked `static' and `extern'.");
3526                                 return false;
3527                         }
3528
3529                         flags |= MethodAttributes.PinvokeImpl;
3530                         dllimport_attribute = a;
3531                         return true;
3532                 }
3533
3534                 //
3535                 // Applies the `Obsolete' attribute to the method.
3536                 //
3537                 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3538                 {
3539                         if (obsolete != null) {
3540                                 Report.Error (579, method.Location, "Duplicate `Obsolete' attribute");
3541                                 return false;
3542                         }
3543
3544                         obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3545                         return obsolete != null;
3546                 }
3547
3548                 //
3549                 // Applies the `Conditional' attribute to the method.
3550                 //
3551                 protected virtual bool ApplyConditionalAttribute (Attribute a)
3552                 {
3553                         // The Conditional attribute is only valid on methods.
3554                         if (!is_method) {
3555                                 Attribute.Error_AttributeNotValidForElement (a, method.Location);
3556                                 return false;
3557                         }
3558
3559                         string condition = a.Conditional_GetConditionName ();
3560
3561                         if (condition == null)
3562                                 return false;
3563
3564                         if (method.ReturnType != TypeManager.void_type) {
3565                                 Report.Error (578, method.Location,
3566                                               "Conditional not valid on `" + member.Name + "' " +
3567                                               "because its return type is not void");
3568                                 return false;
3569                         }
3570
3571                         if ((modifiers & Modifiers.OVERRIDE) != 0) {
3572                                 Report.Error (243, method.Location,
3573                                               "Conditional not valid on `" + member.Name + "' " +
3574                                               "because it is an override method");
3575                                 return false;
3576                         }
3577
3578                         if (member.IsExplicitImpl) {
3579                                 Report.Error (577, method.Location,
3580                                               "Conditional not valid on `" + member.Name + "' " +
3581                                               "because it is an explicit interface implementation");
3582                                 return false;
3583                         }
3584
3585                         if (IsImplementing) {
3586                                 Report.Error (623, method.Location,
3587                                               "Conditional not valid on `" + member.Name + "' " +
3588                                               "because it is an interface method");
3589                                 return false;
3590                         }
3591
3592                         //
3593                         // The likelyhood that the conditional will be more than 1 is very slim
3594                         //
3595                         if (conditionals == null)
3596                                 conditionals = condition;
3597                         else if (conditionals is string){
3598                                 string s = (string) conditionals;
3599                                 conditionals = new ArrayList ();
3600                                 ((ArrayList)conditionals).Add (s);
3601                         } else
3602                                 ((ArrayList)conditionals).Add (condition);
3603
3604                         return true;
3605                 }
3606
3607                 //
3608                 // Checks whether this method should be ignored due to its Conditional attributes.
3609                 //
3610                 bool ShouldIgnore (Location loc)
3611                 {
3612                         // When we're overriding a virtual method, we implicitly inherit the
3613                         // Conditional attributes from our parent.
3614                         if (member.ParentMethod != null) {
3615                                 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3616                                         member.ParentMethod, loc);
3617
3618                                 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3619                                         return true;
3620                         }
3621
3622                         if (conditionals != null){
3623                                 if (conditionals is string){
3624                                         if (RootContext.AllDefines [conditionals] == null)
3625                                                 return true;
3626                                 } else {
3627                                         foreach (string condition in (ArrayList) conditionals)
3628                                         if (RootContext.AllDefines [condition] == null)
3629                                                 return true;
3630                                 }
3631                         }
3632                         return false;
3633                 }
3634
3635                 //
3636                 // Returns the TypeManager.MethodFlags for this method.
3637                 // This emits an error 619 / warning 618 if the method is obsolete.
3638                 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3639                 //
3640                 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3641                 {
3642                         TypeManager.MethodFlags flags = 0;
3643
3644                         if (obsolete != null) {
3645                                 if (obsolete_error) {
3646                                         Report.Error (619, loc, "Method `" + member.Name +
3647                                                       "' is obsolete: `" + obsolete + "'");
3648                                         return TypeManager.MethodFlags.IsObsoleteError;
3649                                 } else
3650                                         Report.Warning (618, loc, "Method `" + member.Name +
3651                                                         "' is obsolete: `" + obsolete + "'");
3652
3653                                 flags |= TypeManager.MethodFlags.IsObsolete;
3654                         }
3655
3656                         if (ShouldIgnore (loc))
3657                                 flags |= TypeManager.MethodFlags.ShouldIgnore;
3658
3659                         return flags;
3660                 }
3661
3662                 public bool Define (TypeContainer container)
3663                 {
3664                         MethodInfo implementing = null;
3665                         string prefix;
3666
3667                         EmitContext ec = method.CreateEmitContext (container, null);
3668                                 
3669                         if (method.OptAttributes != null)
3670                                 if (!ApplyAttributes (method.OptAttributes, is_method, ec))
3671                                         return false;
3672
3673                         if (member.IsExplicitImpl)
3674                                 prefix = member.InterfaceType.FullName + ".";
3675                         else
3676                                 prefix = "";
3677
3678                         string name = method.MethodName;
3679                         string method_name = prefix + name;
3680                         Type[] ParameterTypes = method.ParameterTypes;
3681
3682                         if (container.Pending != null){
3683                                 if (member is Indexer)
3684                                         implementing = container.Pending.IsInterfaceIndexer (
3685                                                 member.InterfaceType, method.ReturnType, ParameterTypes);
3686                                 else
3687                                         implementing = container.Pending.IsInterfaceMethod (
3688                                                 member.InterfaceType, name, method.ReturnType, ParameterTypes);
3689
3690                                 if (member.InterfaceType != null && implementing == null){
3691                                         Report.Error (539, method.Location, "'{0}' in explicit interface declaration is not an interface", method_name);
3692                                         return false;
3693                                 }
3694                         }
3695
3696                         //
3697                         // For implicit implementations, make sure we are public, for
3698                         // explicit implementations, make sure we are private.
3699                         //
3700                         if (implementing != null){
3701                                 //
3702                                 // Setting null inside this block will trigger a more
3703                                 // verbose error reporting for missing interface implementations
3704                                 //
3705                                 // The "candidate" function has been flagged already
3706                                 // but it wont get cleared
3707                                 //
3708                                 if (member.IsExplicitImpl){
3709                                         if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3710                                                 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
3711                                                 implementing = null;
3712                                         }
3713                                 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3714                                         if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3715                                                 //
3716                                                 // If this is an interface method implementation,
3717                                                 // check for public accessibility
3718                                                 //
3719                                                 implementing = null;
3720                                         } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3721                                                 // We may never be private.
3722                                                 implementing = null;
3723                                         } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3724                                                 //
3725                                                 // We may be protected if we're overriding something.
3726                                                 //
3727                                                 implementing = null;
3728                                         }
3729                                 } 
3730                                         
3731                                 //
3732                                 // Static is not allowed
3733                                 //
3734                                 if ((modifiers & Modifiers.STATIC) != 0){
3735                                         implementing = null;
3736                                         Modifiers.Error_InvalidModifier (method.Location, "static");
3737                                 }
3738                         }
3739                         
3740                         //
3741                         // If implementing is still valid, set flags
3742                         //
3743                         if (implementing != null){
3744                                 //
3745                                 // When implementing interface methods, set NewSlot
3746                                 // unless, we are overwriting a method.
3747                                 //
3748                                 if (implementing.DeclaringType.IsInterface){
3749                                         if ((modifiers & Modifiers.OVERRIDE) == 0)
3750                                                 flags |= MethodAttributes.NewSlot;
3751                                 }
3752                                 flags |=
3753                                         MethodAttributes.Virtual |
3754                                         MethodAttributes.HideBySig;
3755
3756                                 // Set Final unless we're virtual, abstract or already overriding a method.
3757                                 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3758                                         flags |= MethodAttributes.Final;
3759
3760                                 // Get the method name from the explicit interface.
3761                                 if (member.InterfaceType != null) {
3762                                         name = implementing.Name;
3763                                         method_name = prefix + name;
3764                                 }
3765
3766                                 IsImplementing = true;
3767                         }
3768
3769                         //
3770                         // Create the MethodBuilder for the method
3771                         //
3772                         if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3773                                 if ((modifiers & Modifiers.STATIC) == 0) {
3774                                         Report.Error (601, method.Location,
3775                                                       "The DllImport attribute must be specified on " +
3776                                                       "a method marked 'static' and 'extern'.");
3777                                         return false;
3778                                 }
3779                                 
3780                                 builder = dllimport_attribute.DefinePInvokeMethod (
3781                                         ec, container.TypeBuilder, method_name, flags,
3782                                         method.ReturnType, ParameterTypes);
3783                         } else
3784                                 builder = container.TypeBuilder.DefineMethod (
3785                                         method_name, flags, method.CallingConventions,
3786                                         method.ReturnType, ParameterTypes);
3787
3788                         if (builder == null)
3789                                 return false;
3790
3791                         if ((modifiers & Modifiers.UNSAFE) != 0)
3792                                 builder.InitLocals = false;
3793
3794                         if (IsImplementing){
3795                                 //
3796                                 // clear the pending implemntation flag
3797                                 //
3798                                 if (member is Indexer) {
3799                                         container.Pending.ImplementIndexer (
3800                                                 member.InterfaceType, builder, method.ReturnType,
3801                                                 ParameterTypes, true);
3802                                 } else
3803                                         container.Pending.ImplementMethod (
3804                                                 member.InterfaceType, name, method.ReturnType,
3805                                                 ParameterTypes, member.IsExplicitImpl);
3806
3807                                 if (member.IsExplicitImpl)
3808                                         container.TypeBuilder.DefineMethodOverride (
3809                                                 builder, implementing);
3810
3811                         }
3812
3813                         if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3814                                 Report.Error (111, method.Location,
3815                                               "Class `" + container.Name +
3816                                               "' already contains a definition with the " +
3817                                               "same return value and parameter types as the " +
3818                                               "'get' method of property `" + member.Name + "'");
3819                                 return false;
3820                         }
3821
3822                         TypeManager.AddMethod (builder, this);
3823
3824                         return true;
3825                 }
3826
3827                 //
3828                 // Emits the code
3829                 // 
3830                 public void Emit (TypeContainer container, Attributable kind)
3831                 {
3832                         EmitContext ec;
3833
3834                         if ((flags & MethodAttributes.PinvokeImpl) == 0)
3835                                 ec = method.CreateEmitContext (container, builder.GetILGenerator ());
3836                         else
3837                                 ec = method.CreateEmitContext (container, null);
3838
3839                         Location loc = method.Location;
3840                         Attributes OptAttributes = method.OptAttributes;
3841
3842                         if (OptAttributes != null)
3843                                 OptAttributes.Emit (ec, kind);
3844
3845                         if (member is MethodCore)
3846                                 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
3847
3848                         SymbolWriter sw = CodeGen.SymbolWriter;
3849                         Block block = method.Block;
3850                         
3851                         //
3852                         // abstract or extern methods have no bodies
3853                         //
3854                         if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3855                                 if (block == null) {
3856                                         if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0) &&
3857                                             !Location.IsNull (loc) &&
3858                                             (method.Location.SymbolDocument != null)) {
3859                                                 sw.OpenMethod (container, MethodBuilder, loc, loc);
3860                                                 sw.CloseMethod ();
3861                                         }
3862
3863                                         return;
3864                                 }
3865
3866                                 //
3867                                 // abstract or extern methods have no bodies.
3868                                 //
3869                                 if ((modifiers & Modifiers.ABSTRACT) != 0)
3870                                         Report.Error (
3871                                                 500, method.Location, "Abstract method `" +
3872                                                 TypeManager.CSharpSignature (builder) +
3873                                                 "' can not have a body");
3874
3875                                 if ((modifiers & Modifiers.EXTERN) != 0)
3876                                         Report.Error (
3877                                                 179, method.Location, "External method `" +
3878                                                 TypeManager.CSharpSignature (builder) +
3879                                                 "' can not have a body");
3880
3881                                 return;
3882                         }
3883
3884                         //
3885                         // Methods must have a body unless they're extern or abstract
3886                         //
3887                         if (block == null) {
3888                                 Report.Error (
3889                                         501, method.Location, "Method `" +
3890                                         TypeManager.CSharpSignature (builder) +
3891                                         "' must declare a body since it is not marked " +
3892                                         "abstract or extern");
3893                                 return;
3894                         }
3895
3896                         //
3897                         // Handle destructors specially
3898                         //
3899                         // FIXME: This code generates buggy code
3900                         //
3901                         if ((sw != null) && !Location.IsNull (loc) &&
3902                             !Location.IsNull (block.EndLocation) &&
3903                             (loc.SymbolDocument != null)) {
3904                                 sw.OpenMethod (container, MethodBuilder, loc, block.EndLocation);
3905
3906                                 if (member is Destructor)
3907                                         EmitDestructor (ec, block);
3908                                 else
3909                                         ec.EmitTopBlock (block, ParameterInfo, loc);
3910
3911                                 sw.CloseMethod ();
3912                         } else {
3913                                 if (member is Destructor)
3914                                         EmitDestructor (ec, block);
3915                                 else
3916                                         ec.EmitTopBlock (block, ParameterInfo, loc);
3917                         }
3918                 }
3919
3920                 void EmitDestructor (EmitContext ec, Block block)
3921                 {
3922                         ILGenerator ig = ec.ig;
3923                         
3924                         Label finish = ig.DefineLabel ();
3925
3926                         block.SetDestructor ();
3927                         
3928                         ig.BeginExceptionBlock ();
3929                         ec.ReturnLabel = finish;
3930                         ec.HasReturnLabel = true;
3931                         ec.EmitTopBlock (block, null, method.Location);
3932                         
3933                         // ig.MarkLabel (finish);
3934                         ig.BeginFinallyBlock ();
3935                         
3936                         if (ec.ContainerType.BaseType != null) {
3937                                 Expression member_lookup = Expression.MemberLookup (
3938                                         ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3939                                         "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
3940
3941                                 if (member_lookup != null){
3942                                         MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3943                                 
3944                                         ig.Emit (OpCodes.Ldarg_0);
3945                                         ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3946                                 }
3947                         }
3948                         
3949                         ig.EndExceptionBlock ();
3950                         //ig.MarkLabel (ec.ReturnLabel);
3951                         ig.Emit (OpCodes.Ret);
3952                 }
3953         }
3954
3955         public class Destructor : Method {
3956
3957                 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
3958                                    Parameters parameters, Attributes attrs, Location l)
3959                         : base (ds, return_type, mod, false, name, parameters, attrs, l)
3960                 { }
3961
3962         }
3963         
3964         abstract public class MemberBase : MemberCore {
3965                 public Expression Type;
3966
3967                 public MethodAttributes flags;
3968                         
3969                 protected readonly int explicit_mod_flags;
3970
3971                 //
3972                 // The "short" name of this property / indexer / event.  This is the
3973                 // name without the explicit interface.
3974                 //
3975                 public string ShortName;
3976
3977                 //
3978                 // The type of this property / indexer / event
3979                 //
3980                 public Type MemberType;
3981
3982                 //
3983                 // If true, this is an explicit interface implementation
3984                 //
3985                 public bool IsExplicitImpl = false;
3986
3987                 //
3988                 // The name of the interface we are explicitly implementing
3989                 //
3990                 public string ExplicitInterfaceName = null;
3991
3992                 //
3993                 // Whether this is an interface member.
3994                 //
3995                 public bool IsInterface;
3996
3997                 //
3998                 // If true, the interface type we are explicitly implementing
3999                 //
4000                 public Type InterfaceType = null;
4001
4002                 //
4003                 // The method we're overriding if this is an override method.
4004                 //
4005                 protected MethodInfo parent_method = null;
4006                 public MethodInfo ParentMethod {
4007                         get {
4008                                 return parent_method;
4009                         }
4010                 }
4011
4012                 //
4013                 // The constructor is only exposed to our children
4014                 //
4015                 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod, string name,
4016                                       Attributes attrs, Location loc)
4017                         : base (name, attrs, loc)
4018                 {
4019                         explicit_mod_flags = mod;
4020                         Type = type;
4021                         ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
4022                 }
4023
4024                 protected virtual bool CheckBase (TypeContainer container)
4025                 {
4026                         if ((container is Struct) || (RootContext.WarningLevel > 3)){
4027                                 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
4028                                         if (container is Struct){
4029                                                 Report.Error (666, Location, "Protected member in struct declaration");
4030                                                 return false;
4031                                         } else
4032                                                 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
4033                                 }
4034                         }
4035                         return true;
4036                 }
4037
4038                 protected void WarningNotHiding (TypeContainer parent)
4039                 {
4040                         Report.Warning (
4041                                 109, Location,
4042                                 "The member " + parent.MakeName (Name) + " does not hide an " +
4043                                 "inherited member.  The keyword new is not required");
4044                                                            
4045                 }
4046
4047                 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
4048                                                         string name)
4049                 {
4050                         //
4051                         // FIXME: report the old/new permissions?
4052                         //
4053                         Report.Error (
4054                                 507, Location, parent.MakeName (Name) +
4055                                 ": can't change the access modifiers when overriding inherited " +
4056                                 "member `" + name + "'");
4057                 }
4058                 
4059                 //
4060                 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
4061                 // that have been defined.
4062                 //
4063                 // `name' is the user visible name for reporting errors (this is used to
4064                 // provide the right name regarding method names and properties)
4065                 //
4066                 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
4067                                                        MethodInfo mb, string name)
4068                 {
4069                         bool ok = true;
4070                         
4071                         if ((ModFlags & Modifiers.OVERRIDE) != 0){
4072                                 if (!(mb.IsAbstract || mb.IsVirtual)){
4073                                         Report.Error (
4074                                                 506, Location, parent.MakeName (Name) +
4075                                                 ": cannot override inherited member `" +
4076                                                 name + "' because it is not " +
4077                                                 "virtual, abstract or override");
4078                                         ok = false;
4079                                 }
4080                                 
4081                                 // Now we check that the overriden method is not final
4082                                 
4083                                 if (mb.IsFinal) {
4084                                         // This happens when implementing interface methods.
4085                                         if (mb.IsHideBySig && mb.IsVirtual) {
4086                                                 Report.Error (
4087                                                         506, Location, parent.MakeName (Name) +
4088                                                         ": cannot override inherited member `" +
4089                                                         name + "' because it is not " +
4090                                                         "virtual, abstract or override");
4091                                         } else
4092                                                 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
4093                                                               "override inherited member `" + name +
4094                                                               "' because it is sealed.");
4095                                         ok = false;
4096                                 }
4097                                 //
4098                                 // Check that the permissions are not being changed
4099                                 //
4100                                 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
4101                                 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
4102
4103                                 //
4104                                 // special case for "protected internal"
4105                                 //
4106
4107                                 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4108                                         //
4109                                         // when overriding protected internal, the method can be declared
4110                                         // protected internal only within the same assembly
4111                                         //
4112
4113                                         if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4114                                                 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
4115                                                         //
4116                                                         // assemblies differ - report an error
4117                                                         //
4118                                                         
4119                                                         Error_CannotChangeAccessModifiers (parent, mb, name);
4120                                                     ok = false;
4121                                                 } else if (thisp != parentp) {
4122                                                         //
4123                                                         // same assembly, but other attributes differ - report an error
4124                                                         //
4125                                                         
4126                                                         Error_CannotChangeAccessModifiers (parent, mb, name);
4127                                                         ok = false;
4128                                                 };
4129                                         } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
4130                                                 //
4131                                                 // if it's not "protected internal", it must be "protected"
4132                                                 //
4133
4134                                                 Error_CannotChangeAccessModifiers (parent, mb, name);
4135                                                 ok = false;
4136                                         } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
4137                                                 //
4138                                                 // protected within the same assembly - an error
4139                                                 //
4140                                                 Error_CannotChangeAccessModifiers (parent, mb, name);
4141                                                 ok = false;
4142                                         } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) != 
4143                                                    (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
4144                                                 //
4145                                                 // protected ok, but other attributes differ - report an error
4146                                                 //
4147                                                 Error_CannotChangeAccessModifiers (parent, mb, name);
4148                                                 ok = false;
4149                                         }
4150                                 } else {
4151                                         if (thisp != parentp){
4152                                                 Error_CannotChangeAccessModifiers (parent, mb, name);
4153                                                 ok = false;
4154                                         }
4155                                 }
4156                         }
4157
4158                         if (mb.IsVirtual || mb.IsAbstract){
4159                                 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4160                                         if (Name != "Finalize"){
4161                                                 Report.Warning (
4162                                                         114, 2, Location, parent.MakeName (Name) + 
4163                                                         " hides inherited member `" + name +
4164                                                         "'.  To make the current member override that " +
4165                                                         "implementation, add the override keyword, " +
4166                                                         "otherwise use the new keyword");
4167                                                 ModFlags |= Modifiers.NEW;
4168                                         }
4169                                 }
4170                         } else {
4171                                 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4172                                         if (Name != "Finalize"){
4173                                                 Report.Warning (
4174                                                         108, 1, Location, "The keyword new is required on " +
4175                                                         parent.MakeName (Name) + " because it hides " +
4176                                                         "inherited member `" + name + "'");
4177                                                 ModFlags |= Modifiers.NEW;
4178                                         }
4179                                 }
4180                         }
4181
4182                         return ok;
4183                 }
4184
4185                 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
4186                 {
4187                         bool error = false;
4188
4189                         foreach (Type partype in parameters){
4190                                 if (partype == TypeManager.void_type) {
4191                                         Report.Error (
4192                                                 1547, Location, "Keyword 'void' cannot " +
4193                                                 "be used in this context");
4194                                         return false;
4195                                 }
4196
4197                                 if (partype.IsPointer){
4198                                         if (!UnsafeOK (ds))
4199                                                 error = true;
4200                                         if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
4201                                                 error = true;
4202                                 }
4203
4204                                 if (ds.AsAccessible (partype, ModFlags))
4205                                         continue;
4206
4207                                 if (this is Indexer)
4208                                         Report.Error (55, Location,
4209                                                       "Inconsistent accessibility: parameter type `" +
4210                                                       TypeManager.CSharpName (partype) + "' is less " +
4211                                                       "accessible than indexer `" + Name + "'");
4212                                 else if ((this is Method) && ((Method) this).IsOperator)
4213                                         Report.Error (57, Location,
4214                                                       "Inconsistent accessibility: parameter type `" +
4215                                                       TypeManager.CSharpName (partype) + "' is less " +
4216                                                       "accessible than operator `" + Name + "'");
4217                                 else
4218                                         Report.Error (51, Location,
4219                                                       "Inconsistent accessibility: parameter type `" +
4220                                                       TypeManager.CSharpName (partype) + "' is less " +
4221                                                       "accessible than method `" + Name + "'");
4222                                 error = true;
4223                         }
4224
4225                         return !error;
4226                 }
4227
4228                 protected virtual bool DoDefine (TypeContainer container)
4229                 {
4230                         if (Name == null)
4231                                 Name = "this";
4232
4233                         if (IsInterface) {
4234                                 ModFlags = Modifiers.PUBLIC |
4235                                         Modifiers.ABSTRACT |
4236                                         Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE);
4237
4238                                 flags = MethodAttributes.Public |
4239                                         MethodAttributes.Abstract |
4240                                         MethodAttributes.HideBySig |
4241                                         MethodAttributes.NewSlot |
4242                                         MethodAttributes.Virtual;
4243                         } else {
4244                                 if (!container.MethodModifiersValid (ModFlags, Name, Location))
4245                                         return false;
4246
4247                                 flags = Modifiers.MethodAttr (ModFlags);
4248                         }
4249
4250                         // Lookup Type, verify validity
4251                         MemberType = container.ResolveType (Type, false, Location);
4252                         if (MemberType == null)
4253                                 return false;
4254
4255                         if ((container.ModFlags & Modifiers.SEALED) != 0){
4256                                 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
4257                                         Report.Error (549, Location, "Virtual method can not be contained in sealed class");
4258                                         return false;
4259                                 }
4260                         }
4261                         
4262                         // verify accessibility
4263                         if (!container.AsAccessible (MemberType, ModFlags)) {
4264                                 if (this is Property)
4265                                         Report.Error (53, Location,
4266                                                       "Inconsistent accessibility: property type `" +
4267                                                       TypeManager.CSharpName (MemberType) + "' is less " +
4268                                                       "accessible than property `" + Name + "'");
4269                                 else if (this is Indexer)
4270                                         Report.Error (54, Location,
4271                                                       "Inconsistent accessibility: indexer return type `" +
4272                                                       TypeManager.CSharpName (MemberType) + "' is less " +
4273                                                       "accessible than indexer `" + Name + "'");
4274                                 else if (this is Method) {
4275                                         if (((Method) this).IsOperator)
4276                                                 Report.Error (56, Location,
4277                                                               "Inconsistent accessibility: return type `" +
4278                                                               TypeManager.CSharpName (MemberType) + "' is less " +
4279                                                               "accessible than operator `" + Name + "'");
4280                                         else
4281                                                 Report.Error (50, Location,
4282                                                               "Inconsistent accessibility: return type `" +
4283                                                               TypeManager.CSharpName (MemberType) + "' is less " +
4284                                                               "accessible than method `" + Name + "'");
4285                                 } else
4286                                         Report.Error (52, Location,
4287                                                       "Inconsistent accessibility: field type `" +
4288                                                       TypeManager.CSharpName (MemberType) + "' is less " +
4289                                                       "accessible than field `" + Name + "'");
4290                                 return false;
4291                         }
4292
4293                         if (MemberType.IsPointer && !UnsafeOK (container))
4294                                 return false;
4295                         
4296                         //
4297                         // Check for explicit interface implementation
4298                         //
4299                         if ((ExplicitInterfaceName == null) && (Name.IndexOf ('.') != -1)){
4300                                 int pos = Name.LastIndexOf ('.');
4301
4302                                 ExplicitInterfaceName = Name.Substring (0, pos);
4303                                 ShortName = Name.Substring (pos + 1);
4304                         } else
4305                                 ShortName = Name;
4306
4307                         if (ExplicitInterfaceName != null) {
4308                                 InterfaceType  = RootContext.LookupType (
4309                                         container, ExplicitInterfaceName, false, Location);
4310                                 if (InterfaceType == null)
4311                                         return false;
4312
4313                                 if (InterfaceType.IsClass) {
4314                                         Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
4315                                         return false;
4316                                 }
4317
4318                                 // Compute the full name that we need to export.
4319                                 Name = InterfaceType.FullName + "." + ShortName;
4320                                 
4321                                 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
4322                                         return false;
4323                                 
4324                                 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4325                                 
4326                                 IsExplicitImpl = true;
4327                         } else
4328                                 IsExplicitImpl = false;
4329
4330                         return true;
4331                 }
4332
4333                 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4334                 {
4335                         return IsIdentifierAndParamClsCompliant (ds, Name, null, null);
4336                 }
4337
4338                 protected override bool VerifyClsCompliance(DeclSpace ds)
4339                 {
4340                         if (base.VerifyClsCompliance (ds)) {
4341                                 return true;
4342                         }
4343
4344                         if (IsInterface && HasClsCompliantAttribute && ds.IsClsCompliaceRequired (ds)) {
4345                                 Report.Error_T (3010, Location, GetSignatureForError ());
4346                         }
4347                         return false;
4348                 }
4349
4350
4351         }
4352
4353         //
4354         // Fields and Events both generate FieldBuilders, we use this to share 
4355         // their common bits.  This is also used to flag usage of the field
4356         //
4357         abstract public class FieldBase : MemberBase {
4358                 public FieldBuilder  FieldBuilder;
4359                 public Status status;
4360
4361                 [Flags]
4362                 public enum Status : byte { ASSIGNED = 1, USED = 2 }
4363
4364                 static string[] attribute_targets = new string [] { "field" };
4365
4366                 //
4367                 // The constructor is only exposed to our children
4368                 //
4369                 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
4370                                      object init, Attributes attrs, Location loc)
4371                         : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
4372                 {
4373                         this.init = init;
4374                 }
4375
4376                 public override AttributeTargets AttributeTargets {
4377                         get {
4378                                 return AttributeTargets.Field;
4379                         }
4380                 }
4381
4382                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4383                 {
4384                         if (a.Type == TypeManager.marshal_as_attr_type) {
4385                                 UnmanagedMarshal marshal = a.GetMarshal ();
4386                                 if (marshal != null) {
4387                                         FieldBuilder.SetMarshal (marshal);
4388                                         return;
4389                                 }
4390                                 Report.Warning_T (-24, a.Location);
4391                                 return;
4392                         }
4393
4394                         
4395                         FieldBuilder.SetCustomAttribute (cb);
4396                 }
4397
4398                 //
4399                 // Whether this field has an initializer.
4400                 //
4401                 public bool HasInitializer {
4402                         get {
4403                                 return init != null;
4404                         }
4405                 }
4406
4407                 protected readonly Object init;
4408                 // Private.
4409                 Expression init_expr;
4410                 bool init_expr_initialized = false;
4411
4412                 //
4413                 // Resolves and returns the field initializer.
4414                 //
4415                 public Expression GetInitializerExpression (EmitContext ec)
4416                 {
4417                         if (init_expr_initialized)
4418                                 return init_expr;
4419
4420                         Expression e;
4421                         if (init is Expression)
4422                                 e = (Expression) init;
4423                         else
4424                                 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
4425
4426                         ec.IsFieldInitializer = true;
4427                         e = e.DoResolve (ec);
4428                         ec.IsFieldInitializer = false;
4429
4430                         init_expr = e;
4431                         init_expr_initialized = true;
4432
4433                         return init_expr;
4434                 }
4435
4436                 protected override bool DoDefine (TypeContainer container)
4437                 {
4438                         if (!base.DoDefine (container))
4439                                 return false;
4440
4441                         if (MemberType == TypeManager.void_type) {
4442                                 Report.Error (1547, Location,
4443                                               "Keyword 'void' cannot be used in this context");
4444                                 return false;
4445                         }
4446
4447                         return true;
4448                 }
4449
4450                 public override string GetSignatureForError ()
4451                 {
4452                         return TypeManager.GetFullNameSignature (FieldBuilder);
4453                 }
4454
4455                 protected override string[] ValidAttributeTargets {
4456                         get {
4457                                 return attribute_targets;
4458                         }
4459                 }
4460
4461                 protected override bool VerifyClsCompliance (DeclSpace ds)
4462                 {
4463                         if (!base.VerifyClsCompliance (ds))
4464                                 return false;
4465
4466                         if (FieldBuilder == null) {
4467                                 return true;
4468                         }
4469
4470                         if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
4471                                 Report.Error_T (3003, Location, GetSignatureForError ());
4472                         }
4473                         return true;
4474                 }
4475
4476
4477                 public void SetAssigned ()
4478                 {
4479                         status |= Status.ASSIGNED;
4480                 }
4481         }
4482
4483         //
4484         // The Field class is used to represents class/struct fields during parsing.
4485         //
4486         public class Field : FieldBase {
4487                 // <summary>
4488                 //   Modifiers allowed in a class declaration
4489                 // </summary>
4490                 const int AllowedModifiers =
4491                         Modifiers.NEW |
4492                         Modifiers.PUBLIC |
4493                         Modifiers.PROTECTED |
4494                         Modifiers.INTERNAL |
4495                         Modifiers.PRIVATE |
4496                         Modifiers.STATIC |
4497                         Modifiers.VOLATILE |
4498                         Modifiers.UNSAFE |
4499                         Modifiers.READONLY;
4500
4501                 public Field (Expression type, int mod, string name, Object expr_or_array_init,
4502                               Attributes attrs, Location loc)
4503                         : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
4504                 {
4505                 }
4506
4507                 public override bool Define (TypeContainer container)
4508                 {
4509                         Type t = container.ResolveType (Type, false, Location);
4510                         
4511                         if (t == null)
4512                                 return false;
4513
4514                         CheckBase (container);
4515                         
4516                         if (!container.AsAccessible (t, ModFlags)) {
4517                                 Report.Error (52, Location,
4518                                               "Inconsistent accessibility: field type `" +
4519                                               TypeManager.CSharpName (t) + "' is less " +
4520                                               "accessible than field `" + Name + "'");
4521                                 return false;
4522                         }
4523
4524                         if (t.IsPointer && !UnsafeOK (container))
4525                                 return false;
4526                         
4527                         if (RootContext.WarningLevel > 1){
4528                                 Type ptype = container.TypeBuilder.BaseType;
4529
4530                                 // ptype is only null for System.Object while compiling corlib.
4531                                 if (ptype != null){
4532                                         TypeContainer.FindMembers (
4533                                                 ptype, MemberTypes.Method,
4534                                                 BindingFlags.Public |
4535                                                 BindingFlags.Static | BindingFlags.Instance,
4536                                                 System.Type.FilterName, Name);
4537                                 }
4538                         }
4539
4540                         if ((ModFlags & Modifiers.VOLATILE) != 0){
4541                                 if (!t.IsClass){
4542                                         Type vt = t;
4543                                         
4544                                         if (TypeManager.IsEnumType (vt))
4545                                                 vt = TypeManager.EnumToUnderlying (t);
4546
4547                                         if (!((vt == TypeManager.bool_type) ||
4548                                               (vt == TypeManager.sbyte_type) ||
4549                                               (vt == TypeManager.byte_type) ||
4550                                               (vt == TypeManager.short_type) ||
4551                                               (vt == TypeManager.ushort_type) ||
4552                                               (vt == TypeManager.int32_type) ||
4553                                               (vt == TypeManager.uint32_type) ||    
4554                                               (vt == TypeManager.char_type) ||
4555                                               (vt == TypeManager.float_type) ||
4556                                               (!vt.IsValueType))){
4557                                                 Report.Error (
4558                                                         677, Location, container.MakeName (Name) +
4559                                                         " A volatile field can not be of type `" +
4560                                                         TypeManager.CSharpName (vt) + "'");
4561                                                 return false;
4562                                         }
4563                                 }
4564
4565                                 if ((ModFlags & Modifiers.READONLY) != 0){
4566                                         Report.Error (
4567                                                       678, Location,
4568                                                       "A field can not be both volatile and readonly");
4569                                         return false;
4570                                 }
4571                         }
4572
4573                         FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4574
4575                         if (container is Struct && 
4576                             ((fa & FieldAttributes.Static) == 0) &&
4577                             t == container.TypeBuilder &&
4578                             !TypeManager.IsBuiltinType (t)){
4579                                 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name + 
4580                                               "' causes a cycle in the structure layout");
4581                                 return false;
4582                         }
4583
4584                         try {
4585                                 FieldBuilder = container.TypeBuilder.DefineField (
4586                                         Name, t, Modifiers.FieldAttr (ModFlags));
4587
4588                                 TypeManager.RegisterFieldBase (FieldBuilder, this);
4589                         }
4590                         catch (ArgumentException) {
4591                                 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
4592                                 return false;
4593                         }
4594
4595                         return true;
4596                 }
4597
4598                 public override void Emit (TypeContainer tc)
4599                 {
4600                         if (OptAttributes != null) {
4601                                 EmitContext ec = new EmitContext (tc, Location, null, FieldBuilder.FieldType, ModFlags);
4602                                 OptAttributes.Emit (ec, this);
4603                         }
4604
4605                         base.Emit (tc);
4606                 }
4607         }
4608
4609         //
4610         // `set' and `get' accessors are represented with an Accessor.
4611         // 
4612         public class Accessor {
4613                 //
4614                 // Null if the accessor is empty, or a Block if not
4615                 //
4616                 public Block Block;
4617                 public Attributes Attributes;
4618                 
4619                 public Accessor (Block b, Attributes attrs)
4620                 {
4621                         Block = b;
4622                         Attributes = attrs;
4623                 }
4624         }
4625
4626         //
4627         // Properties and Indexers both generate PropertyBuilders, we use this to share 
4628         // their common bits.
4629         //
4630         abstract public class PropertyBase : MethodCore {
4631
4632                 public class GetMethod: PropertyMethod
4633                 {
4634                         static string[] attribute_targets = new string [] { "method", "return" };
4635
4636                         public GetMethod (MethodCore method, Accessor accessor):
4637                                 base (method, accessor)
4638                         {
4639                         }
4640
4641                         public override MethodBuilder Define(TypeContainer container)
4642                         {
4643                                 method_data = new MethodData (method, method.ParameterInfo, method.ModFlags, method.flags, false, this);
4644
4645                                 if (!method_data.Define (container))
4646                                         return null;
4647
4648                                 return method_data.MethodBuilder;
4649                         }
4650
4651                         public override string MethodName {
4652                                 get {
4653                                         return "get_" + method.ShortName;
4654                                 }
4655                         }
4656
4657                         public override Type ReturnType {
4658                                 get {
4659                                         return method.MemberType;
4660                                 }
4661                         }
4662
4663                         protected override string[] ValidAttributeTargets {
4664                                 get {
4665                                         return attribute_targets;
4666                                 }
4667                         }
4668                 }
4669
4670                 public class SetMethod: PropertyMethod {
4671
4672                         static string[] attribute_targets = new string [] { "method", "param", "return" };
4673                         ImplicitParameter param_attr;
4674
4675                         public SetMethod (MethodCore method, Accessor accessor):
4676                                 base (method, accessor)
4677                         {
4678                         }
4679
4680                         public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4681                         {
4682                                 if (a.Target == "param") {
4683                                         if (param_attr == null)
4684                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder);
4685
4686                                         param_attr.ApplyAttributeBuilder (a, cb);
4687                                         return;
4688                                 }
4689
4690                                 base.ApplyAttributeBuilder (a, cb);
4691                         }
4692
4693                         protected virtual InternalParameters GetParameterInfo (TypeContainer container)
4694                         {
4695                                 Parameter [] parms = new Parameter [1];
4696                                 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null);
4697                                 return new InternalParameters (
4698                                         container, new Parameters (parms, null, method.Location));
4699                         }
4700
4701                         public override MethodBuilder Define(TypeContainer container)
4702                         {
4703                                 method_data = new MethodData (method, GetParameterInfo (container), method.ModFlags, method.flags, false, this);
4704
4705                                 if (!method_data.Define (container))
4706                                         return null;
4707
4708                                 return method_data.MethodBuilder;
4709                         }
4710
4711                         public override string MethodName {
4712                                 get {
4713                                         return "set_" + method.ShortName;
4714                                 }
4715                         }
4716
4717                         public override Type[] ParameterTypes {
4718                                 get {
4719                                         return new Type[] { method.MemberType };
4720                                 }
4721                         }
4722
4723                         public override Type ReturnType {
4724                                 get {
4725                                         return TypeManager.void_type;
4726                                 }
4727                         }
4728
4729                         protected override string[] ValidAttributeTargets {
4730                                 get {
4731                                         return attribute_targets;
4732                                 }
4733                         }
4734                 }
4735
4736
4737                 static string[] attribute_targets = new string [] { "property" };
4738
4739                 public abstract class PropertyMethod: Attributable, IMethodData 
4740                 {
4741                         protected readonly MethodCore method;
4742                         protected MethodData method_data;
4743                         Block block;
4744
4745                         ReturnParameter return_attributes;
4746
4747                         public PropertyMethod (MethodCore method, Accessor accessor):
4748                                 base (accessor.Attributes)
4749                         {
4750                                 this.method = method;
4751                                 this.block = accessor.Block;
4752                         }
4753
4754                         public override AttributeTargets AttributeTargets {
4755                                 get {
4756                                         return AttributeTargets.Method | AttributeTargets.ReturnValue;
4757                                 }
4758                         }
4759
4760
4761                         public override bool IsClsCompliaceRequired(DeclSpace ds)
4762                         {
4763                                 return method.IsClsCompliaceRequired (ds);
4764                         }
4765
4766                         public InternalParameters ParameterInfo 
4767                         {
4768                                 get {
4769                                         return method_data.ParameterInfo;
4770                                 }
4771                         }
4772
4773                         #region IMethodData Members
4774
4775                         public Block Block {
4776                                 get {
4777                                         return block;
4778                                 }
4779                         }
4780
4781                         public CallingConventions CallingConventions {
4782                                 get {
4783                                         return CallingConventions.Standard;
4784                                 }
4785                         }
4786
4787                         public abstract MethodBuilder Define (TypeContainer container);
4788
4789                         public void Emit (TypeContainer container)
4790                         {
4791                                 method_data.Emit (container, this);
4792                                 block = null;
4793                         }
4794
4795                         public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4796                         {
4797                                 if (a.Target == "return") {
4798                                         if (return_attributes == null)
4799                                                 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
4800
4801                                         return_attributes.ApplyAttributeBuilder (a, cb);
4802                                         return;
4803                                 }
4804
4805                                 method_data.MethodBuilder.SetCustomAttribute (cb);
4806                         }
4807
4808                         public virtual Type[] ParameterTypes {
4809                                 get {
4810                                         return TypeManager.NoTypes;
4811                                 }
4812                         }
4813
4814                         public abstract Type ReturnType { get; }
4815
4816                         public Location Location {
4817                                 get {
4818                                         return method.Location;
4819                                 }
4820                         }
4821
4822                         public abstract string MethodName { get; }
4823
4824                         public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
4825                         {
4826                                 return new EmitContext (tc, method.ds, method.Location, ig, ReturnType, method.ModFlags, false);
4827                         }
4828
4829                         #endregion
4830                 }
4831
4832
4833                 public PropertyMethod Get, Set;
4834                 public PropertyBuilder PropertyBuilder;
4835                 public MethodBuilder GetBuilder, SetBuilder;
4836
4837                 protected EmitContext ec;
4838
4839                 public PropertyBase (DeclSpace ds, Expression type, int mod_flags,
4840                                      int allowed_mod, bool is_iface, string name,
4841                                      Parameters parameters, Attributes attrs,
4842                                      Location loc)
4843                         : base (ds, type, mod_flags, allowed_mod, is_iface, name,
4844                                 attrs, parameters, loc)
4845                 {
4846                 }
4847
4848                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4849                 {
4850                         PropertyBuilder.SetCustomAttribute (cb);
4851                 }
4852
4853                 public override AttributeTargets AttributeTargets {
4854                         get {
4855                                 return AttributeTargets.Property;
4856                         }
4857                 }
4858
4859                 protected override bool DoDefine (TypeContainer container)
4860                 {
4861                         if (!base.DoDefine (container))
4862                                 return false;
4863
4864                         ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4865
4866                         return true;
4867                 }
4868
4869                 public override string GetSignatureForError()
4870                 {
4871                         return TypeManager.CSharpSignature (PropertyBuilder, false);
4872                 }
4873
4874                 protected virtual string RealMethodName {
4875                         get {
4876                                 return Name;
4877                         }
4878                 }
4879
4880                 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4881                 {
4882                         if (!IsIdentifierAndParamClsCompliant (ds, RealMethodName, null, null))
4883                                 return false;
4884
4885                         if (Get != null && !IsIdentifierAndParamClsCompliant (ds, "get_" + RealMethodName, null, null))
4886                                 return false;
4887
4888                         if (Set != null && !IsIdentifierAndParamClsCompliant (ds, "set_" + RealMethodName, null, null))
4889                                 return false;
4890
4891                         return true;
4892                 }
4893
4894
4895                 //
4896                 // Checks our base implementation if any
4897                 //
4898                 protected override bool CheckBase (TypeContainer container)
4899                 {
4900                         base.CheckBase (container);
4901                         
4902                         // Check whether arguments were correct.
4903                         if (!DoDefineParameters ())
4904                                 return false;
4905
4906                         if (IsExplicitImpl)
4907                                 return true;
4908
4909                         //
4910                         // Check in our class for dups
4911                         //
4912                         ArrayList ar = container.Properties;
4913                         if (ar != null) {
4914                                 int arLen = ar.Count;
4915                                         
4916                                 for (int i = 0; i < arLen; i++) {
4917                                         Property m = (Property) ar [i];
4918                                         if (IsDuplicateImplementation (container, m))
4919                                                 return false;
4920                                 }
4921                         }
4922
4923                         if (IsInterface)
4924                                 return true;
4925
4926                         string report_name;
4927                         MethodSignature ms, base_ms;
4928                         if (this is Indexer) {
4929                                 string name, base_name;
4930
4931                                 report_name = "this";
4932                                 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
4933                                 ms = new MethodSignature (name, null, ParameterTypes);
4934                                 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
4935                                 base_ms = new MethodSignature (base_name, null, ParameterTypes);
4936                         } else {
4937                                 report_name = Name;
4938                                 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
4939                         }
4940
4941                         //
4942                         // Verify if the parent has a type with the same name, and then
4943                         // check whether we have to create a new slot for it or not.
4944                         //
4945                         Type ptype = container.TypeBuilder.BaseType;
4946
4947                         // ptype is only null for System.Object while compiling corlib.
4948                         if (ptype == null) {
4949                                 if ((ModFlags & Modifiers.NEW) != 0)
4950                                         WarningNotHiding (container);
4951
4952                                 return true;
4953                         }
4954
4955                         MemberInfo parent_member = null;
4956                         
4957                         //
4958                         // Explicit implementations do not have `parent' methods, however,
4959                         // the member cache stores them there. Without this check, we get
4960                         // an incorrect warning in corlib.
4961                         //
4962                         if (! IsExplicitImpl) {
4963                                 parent_member = ((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
4964                                         container.TypeBuilder, Name, ParameterTypes, true);
4965                         }
4966
4967                         if (parent_member is PropertyInfo) {
4968                                 PropertyInfo parent_property = (PropertyInfo)parent_member;
4969
4970                                 string name = parent_property.DeclaringType.Name + "." +
4971                                         parent_property.Name;
4972
4973                                 MethodInfo get, set, parent_method;
4974                                 get = parent_property.GetGetMethod (true);
4975                                 set = parent_property.GetSetMethod (true);
4976
4977                                 if (get != null)
4978                                         parent_method = get;
4979                                 else if (set != null)
4980                                         parent_method = set;
4981                                 else
4982                                         throw new Exception ("Internal error!");
4983
4984                                 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
4985                                         return false;
4986
4987                                 if ((ModFlags & Modifiers.NEW) == 0) {
4988                                         Type parent_type = TypeManager.TypeToCoreType (
4989                                                 parent_property.PropertyType);
4990
4991                                         if (parent_type != MemberType) {
4992                                                 Report.Error (
4993                                                         508, Location, container.MakeName (Name) + ": cannot " +
4994                                                         "change return type when overriding " +
4995                                                         "inherited member " + name);
4996                                                 return false;
4997                                         }
4998                                 }
4999                         } else if (parent_member == null){
5000                                 if ((ModFlags & Modifiers.NEW) != 0)
5001                                         WarningNotHiding (container);
5002
5003                                 if ((ModFlags & Modifiers.OVERRIDE) != 0){
5004                                         if (this is Indexer)
5005                                                 Report.Error (115, Location,
5006                                                               container.MakeName (Name) +
5007                                                               " no suitable indexers found to override");
5008                                         else
5009                                                 Report.Error (115, Location,
5010                                                               container.MakeName (Name) +
5011                                                               " no suitable properties found to override");
5012                                         return false;
5013                                 }
5014                         }
5015                         return true;
5016                 }
5017
5018                 public override void Emit (TypeContainer tc)
5019                 {
5020                         //
5021                         // The PropertyBuilder can be null for explicit implementations, in that
5022                         // case, we do not actually emit the ".property", so there is nowhere to
5023                         // put the attribute
5024                         //
5025                         if (PropertyBuilder != null && OptAttributes != null)
5026                                 OptAttributes.Emit (ec, this);
5027
5028                         if (Get != null)
5029                                 Get.Emit (tc);
5030
5031                         if (Set != null)
5032                                 Set.Emit (tc);
5033
5034                         base.Emit (tc);
5035                 }
5036
5037                 protected override string[] ValidAttributeTargets {
5038                         get {
5039                                 return attribute_targets;
5040                         }
5041                 }
5042         }
5043                         
5044         public class Property : PropertyBase, IIteratorContainer {
5045                 const int AllowedModifiers =
5046                         Modifiers.NEW |
5047                         Modifiers.PUBLIC |
5048                         Modifiers.PROTECTED |
5049                         Modifiers.INTERNAL |
5050                         Modifiers.PRIVATE |
5051                         Modifiers.STATIC |
5052                         Modifiers.SEALED |
5053                         Modifiers.OVERRIDE |
5054                         Modifiers.ABSTRACT |
5055                         Modifiers.UNSAFE |
5056                         Modifiers.EXTERN |
5057                         Modifiers.METHOD_YIELDS |
5058                         Modifiers.VIRTUAL;
5059
5060                 const int AllowedInterfaceModifiers =
5061                         Modifiers.NEW;
5062
5063                 public Property (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
5064                                  string name, Attributes attrs, Accessor get_block,
5065                                  Accessor set_block, Location loc)
5066                         : base (ds, type, mod_flags,
5067                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5068                                 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
5069                                 loc)
5070                 {
5071                         if (get_block != null)
5072                                 Get = new GetMethod (this, get_block);
5073
5074                         if (set_block != null)
5075                                 Set = new SetMethod (this, set_block);
5076                 }
5077
5078                 public override bool Define (TypeContainer container)
5079                 {
5080                         if (!DoDefine (container))
5081                                 return false;
5082
5083                         if (!CheckBase (container))
5084                                 return false;
5085
5086                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5087
5088                         if (Get != null) {
5089
5090                                 GetBuilder = Get.Define (container);
5091                                 if (GetBuilder == null)
5092                                         return false;
5093
5094                                 //
5095                                 // Setup iterator if we are one
5096                                 //
5097                                 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
5098                                         IteratorHandler ih = new  IteratorHandler (
5099                                                                                    "get", container, MemberType,
5100                                                                                    TypeManager.NoTypes, Get.ParameterInfo, ModFlags, Location);
5101                                         
5102                                         Block new_block = ih.Setup (block);
5103                                         if (new_block == null)
5104                                                 return false;
5105                                         block = new_block;
5106                                 }
5107                         }
5108
5109                         if (Set != null) {
5110                                 SetBuilder = Set.Define (container);
5111                                 if (SetBuilder == null)
5112                                         return false;
5113
5114                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
5115                         }
5116
5117                         // FIXME - PropertyAttributes.HasDefault ?
5118                         
5119                         PropertyAttributes prop_attr = PropertyAttributes.None;
5120                         if (!IsInterface)
5121                                 prop_attr |= PropertyAttributes.RTSpecialName |
5122                                         PropertyAttributes.SpecialName;
5123
5124                         if (!IsExplicitImpl){
5125                                 PropertyBuilder = container.TypeBuilder.DefineProperty (
5126                                         Name, prop_attr, MemberType, null);
5127                                 
5128                                 if (Get != null)
5129                                         PropertyBuilder.SetGetMethod (GetBuilder);
5130                                 
5131                                 if (Set != null)
5132                                         PropertyBuilder.SetSetMethod (SetBuilder);
5133
5134                                 //
5135                                 // HACK for the reasons exposed above
5136                                 //
5137                                 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
5138                                         Report.Error (
5139                                                 111, Location,
5140                                                 "Class `" + container.Name +
5141                                                 "' already contains a definition for the property `" +
5142                                                 Name + "'");
5143                                         return false;
5144                                 }
5145                         }
5146                         return true;
5147                 }
5148
5149                 public void SetYields ()
5150                 {
5151                         ModFlags |= Modifiers.METHOD_YIELDS;
5152                 }
5153         }
5154
5155         /// </summary>
5156         ///  Gigantic workaround  for lameness in SRE follows :
5157         ///  This class derives from EventInfo and attempts to basically
5158         ///  wrap around the EventBuilder so that FindMembers can quickly
5159         ///  return this in it search for members
5160         /// </summary>
5161         public class MyEventBuilder : EventInfo {
5162                 
5163                 //
5164                 // We use this to "point" to our Builder which is
5165                 // not really a MemberInfo
5166                 //
5167                 EventBuilder MyBuilder;
5168                 
5169                 //
5170                 // We "catch" and wrap these methods
5171                 //
5172                 MethodInfo raise, remove, add;
5173
5174                 EventAttributes attributes;
5175                 Type declaring_type, reflected_type, event_type;
5176                 string name;
5177
5178                 Event my_event;
5179
5180                 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
5181                 {
5182                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
5183
5184                         // And now store the values in our own fields.
5185                         
5186                         declaring_type = type_builder;
5187
5188                         reflected_type = type_builder;
5189                         
5190                         attributes = event_attr;
5191                         this.name = name;
5192                         my_event = ev;
5193                         this.event_type = event_type;
5194                 }
5195                 
5196                 //
5197                 // Methods that you have to override.  Note that you only need 
5198                 // to "implement" the variants that take the argument (those are
5199                 // the "abstract" methods, the others (GetAddMethod()) are 
5200                 // regular.
5201                 //
5202                 public override MethodInfo GetAddMethod (bool nonPublic)
5203                 {
5204                         return add;
5205                 }
5206                 
5207                 public override MethodInfo GetRemoveMethod (bool nonPublic)
5208                 {
5209                         return remove;
5210                 }
5211                 
5212                 public override MethodInfo GetRaiseMethod (bool nonPublic)
5213                 {
5214                         return raise;
5215                 }
5216                 
5217                 //
5218                 // These methods make "MyEventInfo" look like a Builder
5219                 //
5220                 public void SetRaiseMethod (MethodBuilder raiseMethod)
5221                 {
5222                         raise = raiseMethod;
5223                         MyBuilder.SetRaiseMethod (raiseMethod);
5224                 }
5225
5226                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
5227                 {
5228                         remove = removeMethod;
5229                         MyBuilder.SetRemoveOnMethod (removeMethod);
5230                 }
5231
5232                 public void SetAddOnMethod (MethodBuilder addMethod)
5233                 {
5234                         add = addMethod;
5235                         MyBuilder.SetAddOnMethod (addMethod);
5236                 }
5237
5238                 public void SetCustomAttribute (CustomAttributeBuilder cb)
5239                 {
5240                         MyBuilder.SetCustomAttribute (cb);
5241                 }
5242                 
5243                 public override object [] GetCustomAttributes (bool inherit)
5244                 {
5245                         // FIXME : There's nothing which can be seemingly done here because
5246                         // we have no way of getting at the custom attribute objects of the
5247                         // EventBuilder !
5248                         return null;
5249                 }
5250
5251                 public override object [] GetCustomAttributes (Type t, bool inherit)
5252                 {
5253                         // FIXME : Same here !
5254                         return null;
5255                 }
5256
5257                 public override bool IsDefined (Type t, bool b)
5258                 {
5259                         return true;
5260                 }
5261
5262                 public override EventAttributes Attributes {
5263                         get {
5264                                 return attributes;
5265                         }
5266                 }
5267
5268                 public override string Name {
5269                         get {
5270                                 return name;
5271                         }
5272                 }
5273
5274                 public override Type DeclaringType {
5275                         get {
5276                                 return declaring_type;
5277                         }
5278                 }
5279
5280                 public override Type ReflectedType {
5281                         get {
5282                                 return reflected_type;
5283                         }
5284                 }
5285
5286                 public Type EventType {
5287                         get {
5288                                 return event_type;
5289                         }
5290                 }
5291                 
5292                 public void SetUsed ()
5293                 {
5294                         if (my_event != null)
5295                                 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
5296                 }
5297         }
5298         
5299         /// <summary>
5300         /// For case when event is declared like property (with add and remove accessors).
5301         /// </summary>
5302         public class EventProperty: Event {
5303
5304                 static string[] attribute_targets = new string [] { "event", "property" };
5305
5306                 public EventProperty (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
5307                         Object init, Attributes attrs, Accessor add, Accessor remove, Location loc)
5308                         : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
5309                 {
5310                         Add = new AddDelegateMethod (this, add);
5311                         Remove = new RemoveDelegateMethod (this, remove);
5312                 }
5313
5314                 protected override string[] ValidAttributeTargets {
5315                         get {
5316                                 return attribute_targets;
5317                         }
5318                 }
5319         }
5320
5321         /// <summary>
5322         /// Event is declared like field.
5323         /// </summary>
5324         public class EventField: Event {
5325
5326                 static string[] attribute_targets = new string [] { "method", "field", "event" };
5327
5328                 public EventField (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
5329                         Object init, Attributes attrs, Location loc)
5330                         : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
5331                 {
5332                         Add = new AddDelegateMethod (this);
5333                         Remove = new RemoveDelegateMethod (this);
5334                 }
5335
5336                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5337                 {
5338                         if (a.Target == "field") {
5339                                 FieldBuilder.SetCustomAttribute (cb);
5340                                 return;
5341                         }
5342
5343                         if (a.Target == "method") {
5344                                 AddBuilder.SetCustomAttribute (cb);
5345                                 RemoveBuilder.SetCustomAttribute (cb);
5346                                 return;
5347                         }
5348
5349                         base.ApplyAttributeBuilder (a, cb);
5350                 }
5351
5352                 protected override string[] ValidAttributeTargets {
5353                         get {
5354                                 return attribute_targets;
5355                         }
5356                 }
5357         }
5358
5359         public abstract class Event : FieldBase {
5360
5361                 protected sealed class AddDelegateMethod: DelegateMethod
5362                 {
5363                         public AddDelegateMethod (Event method):
5364                                 base (method)
5365                         {
5366                         }
5367
5368                         public AddDelegateMethod (Event method, Accessor accessor):
5369                                 base (method, accessor)
5370                         {
5371                         }
5372
5373                         public override string MethodName {
5374                                 get {
5375                                         return "add_" + method.ShortName;
5376                                 }
5377                         }
5378
5379                         protected override MethodInfo DelegateMethodInfo {
5380                                 get {
5381                                         return TypeManager.delegate_combine_delegate_delegate;
5382                                 }
5383                         }
5384
5385                 }
5386
5387                 protected sealed class RemoveDelegateMethod: DelegateMethod
5388                 {
5389                         public RemoveDelegateMethod (Event method):
5390                                 base (method)
5391                         {
5392                         }
5393
5394                         public RemoveDelegateMethod (Event method, Accessor accessor):
5395                                 base (method, accessor)
5396                         {
5397                         }
5398
5399                         public override string MethodName {
5400                                 get {
5401                                         return "remove_" + method.ShortName;
5402                                 }
5403                         }
5404
5405                         protected override MethodInfo DelegateMethodInfo {
5406                                 get {
5407                                         return TypeManager.delegate_remove_delegate_delegate;
5408                                 }
5409                         }
5410
5411                 }
5412
5413                 public abstract class DelegateMethod: Attributable, IMethodData
5414                 {
5415                         protected readonly Event method;
5416                         protected MethodData method_data;
5417                         Block block;
5418                         ReturnParameter return_attributes;
5419                         ImplicitParameter param_attr;
5420
5421                         static string[] attribute_targets = new string [] { "method", "param", "return" };
5422
5423                         public DelegateMethod (Event method):
5424                                 base (null)
5425                         {
5426                                 this.method = method;
5427                         }
5428
5429                         public DelegateMethod (Event method, Accessor accessor):
5430                                 base (accessor.Attributes)
5431                         {
5432                                 this.method = method;
5433                                 this.block = accessor.Block;
5434                         }
5435
5436                         public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5437                         {
5438                                 if (a.Target == "return") {
5439                                         if (return_attributes == null)
5440                                                 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5441
5442                                         return_attributes.ApplyAttributeBuilder (a, cb);
5443                                         return;
5444                                 }
5445
5446                                 if (a.Target == "param") {
5447                                         if (param_attr == null)
5448                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5449
5450                                         param_attr.ApplyAttributeBuilder (a, cb);
5451                                         return;
5452                                 }
5453
5454                                 method_data.MethodBuilder.SetCustomAttribute (cb);
5455                         }
5456
5457                         public override AttributeTargets AttributeTargets {
5458                                 get {
5459                                         return AttributeTargets.Method;
5460                                 }
5461                         }
5462
5463                         public override bool IsClsCompliaceRequired(DeclSpace ds)
5464                         {
5465                                 return method.IsClsCompliaceRequired (ds);
5466                         }
5467
5468                         public MethodBuilder Define (TypeContainer container, InternalParameters ip)
5469                         {
5470                                 method_data = new MethodData (method, ip, method.ModFlags,
5471                                         method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, false, this);
5472
5473                                 if (!method_data.Define (container))
5474                                         return null;
5475
5476                                 MethodBuilder mb = method_data.MethodBuilder;
5477                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
5478                                 return mb;
5479                         }
5480
5481                         #region IMethodData Members
5482
5483                         public Block Block {
5484                                 get {
5485                                         return block;
5486                                 }
5487                         }
5488
5489                         public CallingConventions CallingConventions {
5490                                 get {
5491                                         return CallingConventions.Standard;
5492                                 }
5493                         }
5494
5495                         public void Emit (TypeContainer tc)
5496                         {
5497                                 if (block != null) {
5498                                         method_data.Emit (tc, this);
5499                                         block = null;
5500                                         return;
5501                                 }
5502
5503                                 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
5504                                 EmitContext ec = CreateEmitContext (tc, ig);
5505                                 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
5506
5507                                 if ((method.ModFlags & Modifiers.STATIC) != 0) {
5508                                         ig.Emit (OpCodes.Ldsfld, field_info);
5509                                         ig.Emit (OpCodes.Ldarg_0);
5510                                         ig.Emit (OpCodes.Call, DelegateMethodInfo);
5511                                         ig.Emit (OpCodes.Castclass, method.MemberType);
5512                                         ig.Emit (OpCodes.Stsfld, field_info);
5513                                 } else {
5514                                         ig.Emit (OpCodes.Ldarg_0);
5515                                         ig.Emit (OpCodes.Ldarg_0);
5516                                         ig.Emit (OpCodes.Ldfld, field_info);
5517                                         ig.Emit (OpCodes.Ldarg_1);
5518                                         ig.Emit (OpCodes.Call, DelegateMethodInfo);
5519                                         ig.Emit (OpCodes.Castclass, method.MemberType);
5520                                         ig.Emit (OpCodes.Stfld, field_info);
5521                                 }
5522                                 ig.Emit (OpCodes.Ret);
5523                         }
5524
5525                         protected abstract MethodInfo DelegateMethodInfo { get; }
5526
5527                         public Type[] ParameterTypes {
5528                                 get {
5529                                         return new Type[] { method.MemberType };
5530                                 }
5531                         }
5532
5533                         public Type ReturnType {
5534                                 get {
5535                                         return TypeManager.void_type;
5536                                 }
5537                         }
5538
5539                         public Location Location {
5540                                 get {
5541                                         return method.Location;
5542                                 }
5543                         }
5544
5545                         public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
5546                         {
5547                                 return new EmitContext (tc, method.ds, Location, ig, ReturnType, method.ModFlags, false);
5548                         }
5549
5550                         public abstract string MethodName { get; }
5551
5552                         #endregion
5553
5554                         protected override string[] ValidAttributeTargets {
5555                                 get {
5556                                         return attribute_targets;
5557                                 }
5558                         }
5559                 }
5560
5561
5562                 const int AllowedModifiers =
5563                         Modifiers.NEW |
5564                         Modifiers.PUBLIC |
5565                         Modifiers.PROTECTED |
5566                         Modifiers.INTERNAL |
5567                         Modifiers.PRIVATE |
5568                         Modifiers.STATIC |
5569                         Modifiers.VIRTUAL |
5570                         Modifiers.SEALED |
5571                         Modifiers.OVERRIDE |
5572                         Modifiers.UNSAFE |
5573                         Modifiers.ABSTRACT;
5574
5575                 const int AllowedInterfaceModifiers =
5576                         Modifiers.NEW;
5577
5578                 protected DelegateMethod Add, Remove;
5579                 public MyEventBuilder     EventBuilder;
5580                 public MethodBuilder AddBuilder, RemoveBuilder;
5581                 public DeclSpace ds;
5582
5583                 public Event (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
5584                                 Object init, Attributes attrs, Location loc)
5585                         : base (type, mod_flags, is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5586                                 name, init, attrs, loc)
5587                 {
5588                         IsInterface = is_iface;
5589                         this.ds = ds;
5590                 }
5591
5592                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5593                 {
5594                         EventBuilder.SetCustomAttribute (cb);
5595                 }
5596
5597                 public override AttributeTargets AttributeTargets {
5598                         get {
5599                                 return AttributeTargets.Event;
5600                         }
5601                 }
5602
5603                 public override bool Define (TypeContainer container)
5604                 {
5605                         EventAttributes e_attr;
5606                         if (IsInterface)
5607                                 e_attr = EventAttributes.None;
5608                         else
5609                                 e_attr = EventAttributes.RTSpecialName |
5610                                         EventAttributes.SpecialName;
5611
5612                         if (!DoDefine (container))
5613                                 return false;
5614
5615                         if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
5616                                 Report.Error (74, Location, "'" + container.Name + "." + Name +
5617                                               "': abstract event can not have an initializer");
5618                                 return false;
5619                         }
5620                         
5621                         if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
5622                                 Report.Error (66, Location, "'" + container.Name + "." + Name +
5623                                               "' : event must be of a delegate type");
5624                                 return false;
5625                         }
5626
5627                         Parameter [] parms = new Parameter [1];
5628                         parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
5629                         InternalParameters ip = new InternalParameters (
5630                                 container, new Parameters (parms, null, Location)); 
5631
5632                         if (!CheckBase (container))
5633                                 return false;
5634
5635                         //
5636                         // Now define the accessors
5637                         //
5638
5639                         AddBuilder = Add.Define (container, ip);
5640                         if (AddBuilder == null)
5641                                 return false;
5642
5643                         RemoveBuilder = Remove.Define (container, ip);
5644                         if (RemoveBuilder == null)
5645                                 return false;
5646
5647                         if (!IsExplicitImpl){
5648                                 EventBuilder = new MyEventBuilder (this,
5649                                         container.TypeBuilder, Name, e_attr, MemberType);
5650                                         
5651                                 if (Add.Block == null && Remove.Block == null &&
5652                                     !IsInterface) {
5653                                         FieldBuilder = container.TypeBuilder.DefineField (
5654                                                 Name, MemberType,
5655                                                 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
5656                                         TypeManager.RegisterPrivateFieldOfEvent (
5657                                                 (EventInfo) EventBuilder, FieldBuilder);
5658                                         TypeManager.RegisterFieldBase (FieldBuilder, this);
5659                                 }
5660                         
5661                                 EventBuilder.SetAddOnMethod (AddBuilder);
5662                                 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
5663
5664                                 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
5665                                         Report.Error (111, Location,
5666                                                       "Class `" + container.Name +
5667                                                       "' already contains a definition for the event `" +
5668                                                       Name + "'");
5669                                         return false;
5670                                 }
5671                         }
5672                         
5673                         return true;
5674                 }
5675
5676                 public override void Emit (TypeContainer tc)
5677                 {
5678                         if (OptAttributes != null) {
5679                                 EmitContext ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
5680                                 OptAttributes.Emit (ec, this);
5681                         }
5682
5683                         if (!IsInterface) {
5684                                 Add.Emit (tc);
5685                                 Remove.Emit (tc);
5686                         }
5687
5688                         base.Emit (tc);
5689                 }
5690         }
5691
5692         //
5693         // FIXME: This does not handle:
5694         //
5695         //   int INTERFACENAME [ args ]
5696         //   Does not 
5697         //
5698         // Only:
5699         // 
5700         // int this [ args ]
5701  
5702         public class Indexer : PropertyBase {
5703
5704                 class GetIndexerMethod: GetMethod
5705                 {
5706                         public GetIndexerMethod (MethodCore method, Accessor accessor):
5707                                 base (method, accessor)
5708                         {
5709                         }
5710
5711                         public override Type[] ParameterTypes {
5712                                 get {
5713                                         return method.ParameterTypes;
5714                                 }
5715                         }
5716                 }
5717
5718                 class SetIndexerMethod: SetMethod
5719                 {
5720                         readonly Parameters parameters;
5721
5722                         public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
5723                                 base (method, accessor)
5724                         {
5725                                 this.parameters = parameters;
5726                         }
5727
5728                         public override Type[] ParameterTypes {
5729                                 get {
5730                                         int top = method.ParameterTypes.Length;
5731                                         Type [] set_pars = new Type [top + 1];
5732                                         method.ParameterTypes.CopyTo (set_pars, 0);
5733                                         set_pars [top] = method.MemberType;
5734                                         return set_pars;
5735                                 }
5736                         }
5737
5738                         protected override InternalParameters GetParameterInfo (TypeContainer container)
5739                         {
5740                                 Parameter [] fixed_parms = parameters.FixedParameters;
5741
5742                                 if (fixed_parms == null){
5743                                         throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
5744                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5745                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5746                                         //
5747                                         // Here is the problem: the `value' parameter has
5748                                         // to come *after* the array parameter in the declaration
5749                                         // like this:
5750                                         // X (object [] x, Type value)
5751                                         // .param [0]
5752                                         //
5753                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5754                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5755                                         
5756                                 }
5757                                 
5758                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
5759
5760                                 fixed_parms.CopyTo (tmp, 0);
5761                                 tmp [fixed_parms.Length] = new Parameter (
5762                                         method.Type, "value", Parameter.Modifier.NONE, null);
5763
5764                                 Parameters set_formal_params = new Parameters (tmp, null, method.Location);
5765                                 
5766                                 return new InternalParameters (container, set_formal_params);
5767                         }
5768
5769                 }
5770
5771
5772                 const int AllowedModifiers =
5773                         Modifiers.NEW |
5774                         Modifiers.PUBLIC |
5775                         Modifiers.PROTECTED |
5776                         Modifiers.INTERNAL |
5777                         Modifiers.PRIVATE |
5778                         Modifiers.VIRTUAL |
5779                         Modifiers.SEALED |
5780                         Modifiers.OVERRIDE |
5781                         Modifiers.UNSAFE |
5782                         Modifiers.EXTERN |
5783                         Modifiers.ABSTRACT;
5784
5785                 const int AllowedInterfaceModifiers =
5786                         Modifiers.NEW;
5787
5788                 public string IndexerName;
5789                 public string InterfaceIndexerName;
5790
5791                 //
5792                 // Are we implementing an interface ?
5793                 //
5794                 public Indexer (DeclSpace ds, Expression type, string int_type, int mod_flags,
5795                                 bool is_iface, Parameters parameters, Attributes attrs,
5796                                 Accessor get_block, Accessor set_block, Location loc)
5797                         : base (ds, type, mod_flags,
5798                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5799                                 is_iface, "", parameters, attrs, loc)
5800                 {
5801                         ExplicitInterfaceName = int_type;
5802
5803                         if (get_block != null)
5804                                 Get = new GetIndexerMethod (this, get_block);
5805
5806                         if (set_block != null)
5807                                 Set = new SetIndexerMethod (this, parameters, set_block);
5808                 }
5809                        
5810                 public override bool Define (TypeContainer container)
5811                 {
5812                         PropertyAttributes prop_attr =
5813                                 PropertyAttributes.RTSpecialName |
5814                                 PropertyAttributes.SpecialName;
5815                         
5816                         if (!DoDefine (container))
5817                                 return false;
5818
5819                         if (OptAttributes != null)
5820                                 IndexerName = OptAttributes.ScanForIndexerName (ec);
5821
5822                         if (IndexerName == null)
5823                                 IndexerName = "Item";
5824                         else {
5825                                 if (! Tokenizer.IsValidIdentifier (IndexerName)) {
5826                                         Report.Error (633, Location, "The IndexerName specified is an invalid identifier");
5827                                         return false;
5828                                 }
5829                                 
5830                                 if (IsExplicitImpl) {
5831                                         Report.Error (592, Location,
5832                                                       "Attribute 'IndexerName' is not valid on explicit implementations.");
5833                                         return false;
5834                                 }
5835                         }
5836
5837                         ShortName = IndexerName;
5838                         if (IsExplicitImpl) {
5839                                 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
5840                                 Name = InterfaceType.FullName + "." + IndexerName;
5841                         } else {
5842                                 InterfaceIndexerName = IndexerName;
5843                                 Name = ShortName;
5844                         }
5845
5846                         if (!CheckNameCollision (container))
5847                                 return false;
5848
5849                         if (!CheckBase (container))
5850                                 return false;
5851
5852                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5853                         if (Get != null){
5854                                 GetBuilder = Get.Define (container);
5855                                 if (GetBuilder == null)
5856                                         return false;
5857                         }
5858                         
5859                         if (Set != null){
5860                                 SetBuilder = Set.Define (container);
5861                                 if (SetBuilder == null)
5862                                         return false;
5863                         }
5864
5865                         //
5866                         // Now name the parameters
5867                         //
5868                         Parameter [] p = Parameters.FixedParameters;
5869                         if (p != null) {
5870                                 int i;
5871                                 
5872                                 for (i = 0; i < p.Length; ++i) {
5873                                         if (Get != null)
5874                                                 GetBuilder.DefineParameter (
5875                                                         i + 1, p [i].Attributes, p [i].Name);
5876
5877                                         if (Set != null)
5878                                                 SetBuilder.DefineParameter (
5879                                                         i + 1, p [i].Attributes, p [i].Name);
5880                                 }
5881
5882                                 if (Set != null)
5883                                         SetBuilder.DefineParameter (
5884                                                 i + 1, ParameterAttributes.None, "value");
5885                                         
5886                                 if (i != ParameterTypes.Length) {
5887                                         Parameter array_param = Parameters.ArrayParameter;
5888
5889                                         SetBuilder.DefineParameter (
5890                                                 i + 1, array_param.Attributes, array_param.Name);
5891                                 }
5892                         }
5893
5894                         //
5895                         // Define the PropertyBuilder if one of the following conditions are met:
5896                         // a) we're not implementing an interface indexer.
5897                         // b) the indexer has a different IndexerName and this is no
5898                         //    explicit interface implementation.
5899                         //
5900                         if (!IsExplicitImpl) {
5901                                 PropertyBuilder = container.TypeBuilder.DefineProperty (
5902                                         IndexerName, prop_attr, MemberType, ParameterTypes);
5903
5904                                 if (Get != null)
5905                                         PropertyBuilder.SetGetMethod (GetBuilder);
5906
5907                                 if (Set != null)
5908                                         PropertyBuilder.SetSetMethod (SetBuilder);
5909                                 
5910                                 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
5911                                                              ParameterTypes);
5912                         }
5913
5914                         return true;
5915                 }
5916
5917                 bool CheckNameCollision (TypeContainer container) {
5918                         switch (VerifyName (container)){
5919                                 case DeclSpace.AdditionResult.NameExists:
5920                                         Report.Error (102, Location, "The container '{0}' already contains a definition for '{1}'", container.GetSignatureForError (), Name);
5921                                         return false;
5922
5923                                 case DeclSpace.AdditionResult.Success:
5924                                         return true;
5925                         }
5926                         throw new NotImplementedException ();
5927                 }
5928
5929                 DeclSpace.AdditionResult VerifyName (TypeContainer container) {
5930                         if (!AddIndexer (container, container.Name + "." + Name))
5931                                 return DeclSpace.AdditionResult.NameExists;
5932
5933                         if (Get != null) {
5934                                 if (!AddIndexer (container, container.Name + ".get_" + Name))
5935                                         return DeclSpace.AdditionResult.NameExists;
5936                         }
5937
5938                         if (Set != null) {
5939                                 if (!AddIndexer (container, container.Name + ".set_" + Name))
5940                                         return DeclSpace.AdditionResult.NameExists;
5941                         }
5942                         return DeclSpace.AdditionResult.Success;
5943                 }
5944
5945                 bool AddIndexer (TypeContainer container, string fullname)
5946                 {
5947                         object value = container.GetDefinition (fullname);
5948
5949                         if (value != null) {
5950                                 return value.GetType () != GetType () ? false : true;
5951                         }
5952
5953                         container.DefineName (fullname, this);
5954                         return true;
5955                 }
5956
5957                 public override string GetSignatureForError ()
5958                 {
5959                         return TypeManager.CSharpSignature (PropertyBuilder, true);
5960                 }
5961
5962                 protected override string RealMethodName {
5963                         get {
5964                                 return IndexerName;
5965                         }
5966                 }
5967         }
5968
5969         public class Operator : MemberBase, IIteratorContainer {
5970
5971                 const int AllowedModifiers =
5972                         Modifiers.PUBLIC |
5973                         Modifiers.UNSAFE |
5974                         Modifiers.EXTERN |
5975                         Modifiers.STATIC;
5976
5977                 const int RequiredModifiers =
5978                         Modifiers.PUBLIC |
5979                         Modifiers.STATIC;
5980
5981                 public enum OpType : byte {
5982
5983                         // Unary operators
5984                         LogicalNot,
5985                         OnesComplement,
5986                         Increment,
5987                         Decrement,
5988                         True,
5989                         False,
5990
5991                         // Unary and Binary operators
5992                         Addition,
5993                         Subtraction,
5994
5995                         UnaryPlus,
5996                         UnaryNegation,
5997                         
5998                         // Binary operators
5999                         Multiply,
6000                         Division,
6001                         Modulus,
6002                         BitwiseAnd,
6003                         BitwiseOr,
6004                         ExclusiveOr,
6005                         LeftShift,
6006                         RightShift,
6007                         Equality,
6008                         Inequality,
6009                         GreaterThan,
6010                         LessThan,
6011                         GreaterThanOrEqual,
6012                         LessThanOrEqual,
6013
6014                         // Implicit and Explicit
6015                         Implicit,
6016                         Explicit
6017                 };
6018
6019                 public readonly OpType OperatorType;
6020                 public readonly Expression ReturnType;
6021                 public readonly Expression FirstArgType, SecondArgType;
6022                 public readonly string FirstArgName, SecondArgName;
6023                 public Block           Block;
6024                 public MethodBuilder   OperatorMethodBuilder;
6025                 
6026                 public string MethodName;
6027                 public Method OperatorMethod;
6028
6029                 static string[] attribute_targets = new string [] { "param" };
6030
6031                 public Operator (OpType type, Expression ret_type, int mod_flags,
6032                                  Expression arg1type, string arg1name,
6033                                  Expression arg2type, string arg2name,
6034                                  Block block, Attributes attrs, Location loc)
6035                         : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
6036                 {
6037                         OperatorType = type;
6038                         Name = "op_" + OperatorType;
6039                         ReturnType = ret_type;
6040                         FirstArgType = arg1type;
6041                         FirstArgName = arg1name;
6042                         SecondArgType = arg2type;
6043                         SecondArgName = arg2name;
6044                         Block = block;
6045                 }
6046
6047                 string Prototype (TypeContainer container)
6048                 {
6049                         return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
6050                                 SecondArgType + ")";
6051                 }
6052
6053                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) 
6054                 {
6055                         OperatorMethod.ApplyAttributeBuilder (a, cb);
6056                 }
6057
6058                 public override AttributeTargets AttributeTargets {
6059                         get {
6060                                 return AttributeTargets.Method; 
6061                         }
6062                 }
6063                 
6064                 public override bool Define (TypeContainer container)
6065                 {
6066                         int length = 1;
6067                         MethodName = "op_" + OperatorType;
6068                         
6069                         if (SecondArgType != null)
6070                                 length = 2;
6071                         
6072                         Parameter [] param_list = new Parameter [length];
6073
6074                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
6075                                 Report.Error (
6076                                         558, Location, 
6077                                         "User defined operators `" +
6078                                         Prototype (container) +
6079                                         "' must be declared static and public");
6080                                 return false;
6081                         }
6082
6083                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
6084                                                        Parameter.Modifier.NONE, null);
6085                         if (SecondArgType != null)
6086                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
6087                                                                Parameter.Modifier.NONE, null);
6088                         
6089                         OperatorMethod = new Method (
6090                                 container, ReturnType, ModFlags, false, MethodName,
6091                                 new Parameters (param_list, null, Location),
6092                                 OptAttributes, Location);
6093
6094                         OperatorMethod.Block = Block;
6095                         OperatorMethod.IsOperator = true;                       
6096                         OperatorMethod.Define (container);
6097
6098                         if (OperatorMethod.MethodBuilder == null)
6099                                 return false;
6100                         
6101                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
6102
6103                         Type [] param_types = OperatorMethod.ParameterTypes;
6104                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
6105                         Type return_type = OperatorMethod.GetReturnType ();
6106                         Type first_arg_type = param_types [0];
6107
6108                         // Rules for conversion operators
6109                         
6110                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
6111                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
6112                                         Report.Error (
6113                                                 555, Location,
6114                                                 "User-defined conversion cannot take an object of the " +
6115                                                 "enclosing type and convert to an object of the enclosing" +
6116                                                 " type");
6117                                         return false;
6118                                 }
6119                                 
6120                                 if (first_arg_type != declaring_type && return_type != declaring_type){
6121                                         Report.Error (
6122                                                 556, Location, 
6123                                                 "User-defined conversion must convert to or from the " +
6124                                                 "enclosing type");
6125                                         return false;
6126                                 }
6127                                 
6128                                 if (first_arg_type == TypeManager.object_type ||
6129                                     return_type == TypeManager.object_type){
6130                                         Report.Error (
6131                                                 -8, Location,
6132                                                 "User-defined conversion cannot convert to or from " +
6133                                                 "object type");
6134                                         return false;
6135                                 }
6136
6137                                 if (first_arg_type.IsInterface || return_type.IsInterface){
6138                                         Report.Error (
6139                                                 552, Location,
6140                                                 "User-defined conversion cannot convert to or from an " +
6141                                                 "interface type");
6142                                         return false;
6143                                 }
6144                                 
6145                                 if (first_arg_type.IsSubclassOf (return_type) ||
6146                                     return_type.IsSubclassOf (first_arg_type)){
6147                                         Report.Error (
6148                                                 -10, Location,
6149                                                 "User-defined conversion cannot convert between types " +
6150                                                 "that derive from each other");
6151                                         return false;
6152                                 }
6153                         } else if (SecondArgType == null) {
6154                                 // Checks for Unary operators
6155                                 
6156                                 if (first_arg_type != declaring_type){
6157                                         Report.Error (
6158                                                 562, Location,
6159                                                 "The parameter of a unary operator must be the " +
6160                                                 "containing type");
6161                                         return false;
6162                                 }
6163                                 
6164                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
6165                                         if (return_type != declaring_type){
6166                                                 Report.Error (
6167                                                         559, Location,
6168                                                         "The parameter and return type for ++ and -- " +
6169                                                         "must be the containing type");
6170                                                 return false;
6171                                         }
6172                                         
6173                                 }
6174                                 
6175                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
6176                                         if (return_type != TypeManager.bool_type){
6177                                                 Report.Error (
6178                                                         215, Location,
6179                                                         "The return type of operator True or False " +
6180                                                         "must be bool");
6181                                                 return false;
6182                                         }
6183                                 }
6184                                 
6185                         } else {
6186                                 // Checks for Binary operators
6187                                 
6188                                 if (first_arg_type != declaring_type &&
6189                                     param_types [1] != declaring_type){
6190                                         Report.Error (
6191                                                 563, Location,
6192                                                 "One of the parameters of a binary operator must " +
6193                                                 "be the containing type");
6194                                         return false;
6195                                 }
6196                         }
6197
6198                         return true;
6199                 }
6200                 
6201                 public override void Emit (TypeContainer container)
6202                 {
6203                         //
6204                         // abstract or extern methods have no bodies
6205                         //
6206                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
6207                                 return;
6208                         
6209                         OperatorMethod.Emit (container);
6210                         Block = null;
6211                 }
6212
6213                 public static string GetName (OpType ot)
6214                 {
6215                         switch (ot){
6216                         case OpType.LogicalNot:
6217                                 return "!";
6218                         case OpType.OnesComplement:
6219                                 return "~";
6220                         case OpType.Increment:
6221                                 return "++";
6222                         case OpType.Decrement:
6223                                 return "--";
6224                         case OpType.True:
6225                                 return "true";
6226                         case OpType.False:
6227                                 return "false";
6228                         case OpType.Addition:
6229                                 return "+";
6230                         case OpType.Subtraction:
6231                                 return "-";
6232                         case OpType.UnaryPlus:
6233                                 return "+";
6234                         case OpType.UnaryNegation:
6235                                 return "-";
6236                         case OpType.Multiply:
6237                                 return "*";
6238                         case OpType.Division:
6239                                 return "/";
6240                         case OpType.Modulus:
6241                                 return "%";
6242                         case OpType.BitwiseAnd:
6243                                 return "&";
6244                         case OpType.BitwiseOr:
6245                                 return "|";
6246                         case OpType.ExclusiveOr:
6247                                 return "^";
6248                         case OpType.LeftShift:
6249                                 return "<<";
6250                         case OpType.RightShift:
6251                                 return ">>";
6252                         case OpType.Equality:
6253                                 return "==";
6254                         case OpType.Inequality:
6255                                 return "!=";
6256                         case OpType.GreaterThan:
6257                                 return ">";
6258                         case OpType.LessThan:
6259                                 return "<";
6260                         case OpType.GreaterThanOrEqual:
6261                                 return ">=";
6262                         case OpType.LessThanOrEqual:
6263                                 return "<=";
6264                         case OpType.Implicit:
6265                                 return "implicit";
6266                         case OpType.Explicit:
6267                                 return "explicit";
6268                         default: return "";
6269                         }
6270                 }
6271                 
6272                 public override string ToString ()
6273                 {
6274                         Type return_type = OperatorMethod.GetReturnType();
6275                         Type [] param_types = OperatorMethod.ParameterTypes;
6276                         
6277                         if (SecondArgType == null)
6278                                 return String.Format (
6279                                         "{0} operator {1}({2})",
6280                                         TypeManager.CSharpName (return_type),
6281                                         GetName (OperatorType),
6282                                         param_types [0]);
6283                         else
6284                                 return String.Format (
6285                                         "{0} operator {1}({2}, {3})",
6286                                         TypeManager.CSharpName (return_type),
6287                                         GetName (OperatorType),
6288                                         param_types [0], param_types [1]);
6289                 }
6290
6291                 protected override string[] ValidAttributeTargets {
6292                         get {
6293                                 return attribute_targets;
6294                         }
6295                 }
6296
6297                 public void SetYields ()
6298                 {
6299                         ModFlags |= Modifiers.METHOD_YIELDS;
6300                 }
6301         }
6302
6303         //
6304         // This is used to compare method signatures
6305         //
6306         struct MethodSignature {
6307                 public string Name;
6308                 public Type RetType;
6309                 public Type [] Parameters;
6310                 
6311                 /// <summary>
6312                 ///    This delegate is used to extract methods which have the
6313                 ///    same signature as the argument
6314                 /// </summary>
6315                 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
6316                 
6317                 public MethodSignature (string name, Type ret_type, Type [] parameters)
6318                 {
6319                         Name = name;
6320                         RetType = ret_type;
6321
6322                         if (parameters == null)
6323                                 Parameters = TypeManager.NoTypes;
6324                         else
6325                                 Parameters = parameters;
6326                 }
6327
6328                 public override string ToString ()
6329                 {
6330                         string pars = "";
6331                         if (Parameters.Length != 0){
6332                                 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
6333                                 for (int i = 0; i < Parameters.Length; i++){
6334                                         sb.Append (Parameters [i]);
6335                                         if (i+1 < Parameters.Length)
6336                                                 sb.Append (", ");
6337                                 }
6338                                 pars = sb.ToString ();
6339                         }
6340
6341                         return String.Format ("{0} {1} ({2})", RetType, Name, pars);
6342                 }
6343                 
6344                 public override int GetHashCode ()
6345                 {
6346                         return Name.GetHashCode ();
6347                 }
6348
6349                 public override bool Equals (Object o)
6350                 {
6351                         MethodSignature other = (MethodSignature) o;
6352
6353                         if (other.Name != Name)
6354                                 return false;
6355
6356                         if (other.RetType != RetType)
6357                                 return false;
6358                         
6359                         if (Parameters == null){
6360                                 if (other.Parameters == null)
6361                                         return true;
6362                                 return false;
6363                         }
6364
6365                         if (other.Parameters == null)
6366                                 return false;
6367                         
6368                         int c = Parameters.Length;
6369                         if (other.Parameters.Length != c)
6370                                 return false;
6371
6372                         for (int i = 0; i < c; i++)
6373                                 if (other.Parameters [i] != Parameters [i])
6374                                         return false;
6375
6376                         return true;
6377                 }
6378
6379                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
6380                 {
6381                         MethodSignature sig = (MethodSignature) filter_criteria;
6382
6383                         if (m.Name != sig.Name)
6384                                 return false;
6385
6386                         Type ReturnType;
6387                         MethodInfo mi = m as MethodInfo;
6388                         PropertyInfo pi = m as PropertyInfo;
6389
6390                         if (mi != null)
6391                                 ReturnType = mi.ReturnType;
6392                         else if (pi != null)
6393                                 ReturnType = pi.PropertyType;
6394                         else
6395                                 return false;
6396                         
6397                         //
6398                         // we use sig.RetType == null to mean `do not check the
6399                         // method return value.  
6400                         //
6401                         if (sig.RetType != null)
6402                                 if (ReturnType != sig.RetType)
6403                                         return false;
6404
6405                         Type [] args;
6406                         if (mi != null)
6407                                 args = TypeManager.GetArgumentTypes (mi);
6408                         else
6409                                 args = TypeManager.GetArgumentTypes (pi);
6410                         Type [] sigp = sig.Parameters;
6411
6412                         if (args.Length != sigp.Length)
6413                                 return false;
6414
6415                         for (int i = args.Length; i > 0; ){
6416                                 i--;
6417                                 if (args [i] != sigp [i])
6418                                         return false;
6419                         }
6420                         return true;
6421                 }
6422         }
6423 }