2004-06-03 Marek Safar <marek.safar@seznam.cz>
[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 //          Marek Safar (marek.safar@seznam.cz)
7 //
8 // Licensed under the terms of the GNU GPL
9 //
10 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 //
12 //
13 //  2002-10-11  Miguel de Icaza  <miguel@ximian.com>
14 //
15 //      * class.cs: Following the comment from 2002-09-26 to AddMethod, I
16 //      have fixed a remaining problem: not every AddXXXX was adding a
17 //      fully qualified name.  
18 //
19 //      Now everyone registers a fully qualified name in the DeclSpace as
20 //      being defined instead of the partial name.  
21 //
22 //      Downsides: we are slower than we need to be due to the excess
23 //      copies and the names being registered this way.  
24 //
25 //      The reason for this is that we currently depend (on the corlib
26 //      bootstrap for instance) that types are fully qualified, because
27 //      we dump all the types in the namespace, and we should really have
28 //      types inserted into the proper namespace, so we can only store the
29 //      basenames in the defined_names array.
30 //
31 //
32 #define CACHE
33 using System;
34 using System.Collections;
35 using System.Reflection;
36 using System.Reflection.Emit;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.InteropServices;
39
40 namespace Mono.CSharp {
41
42         /// <summary>
43         ///   This is the base class for structs and classes.  
44         /// </summary>
45         public class TypeContainer : DeclSpace, IMemberContainer {
46                 // Holds a list of classes and structures
47                 ArrayList types;
48
49                 // Holds the list of properties
50                 ArrayList properties;
51
52                 // Holds the list of enumerations
53                 ArrayList enums;
54
55                 // Holds the list of delegates
56                 ArrayList delegates;
57                 
58                 // Holds the list of constructors
59                 ArrayList instance_constructors;
60
61                 // Holds the list of fields
62                 ArrayList fields;
63
64                 // Holds a list of fields that have initializers
65                 ArrayList initialized_fields;
66
67                 // Holds a list of static fields that have initializers
68                 ArrayList initialized_static_fields;
69
70                 // Holds the list of constants
71                 ArrayList constants;
72
73                 // Holds the list of
74                 ArrayList interfaces;
75
76                 // Holds order in which interfaces must be closed
77                 ArrayList interface_order;
78                 
79                 // Holds the methods.
80                 ArrayList methods;
81
82                 // Holds the events
83                 ArrayList events;
84
85                 // Holds the indexers
86                 ArrayList indexers;
87
88                 // Holds the operators
89                 ArrayList operators;
90
91                 // The emit context for toplevel objects.
92                 EmitContext ec;
93                 
94                 //
95                 // Pointers to the default constructor and the default static constructor
96                 //
97                 Constructor default_constructor;
98                 Constructor default_static_constructor;
99
100                 //
101                 // Whether we have seen a static constructor for this class or not
102                 //
103                 public bool UserDefinedStaticConstructor = false;
104
105                 //
106                 // Whether we have at least one non-static field
107                 //
108                 bool have_nonstatic_fields = false;
109                 
110                 //
111                 // This one is computed after we can distinguish interfaces
112                 // from classes from the arraylist `type_bases' 
113                 //
114                 string     base_class_name;
115                 public Type base_classs_type;
116
117                 ArrayList type_bases;
118
119                 bool members_defined;
120                 bool members_defined_ok;
121
122                 // The interfaces we implement.
123                 TypeExpr [] ifaces;
124                 Type[] base_inteface_types;
125
126                 // The parent member container and our member cache
127                 IMemberContainer parent_container;
128                 MemberCache member_cache;
129                 
130                 //
131                 // The indexer name for this class
132                 //
133                 public string IndexerName;
134
135                 public TypeContainer ():
136                         this (null, null, "", null, new Location (-1)) {
137                 }
138
139                 public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
140                         : base (ns, parent, name, attrs, l)
141                 {
142                         types = new ArrayList ();
143
144                         base_class_name = null;
145                 }
146
147                 public AdditionResult AddConstant (Const constant)
148                 {
149                         AdditionResult res;
150                         string basename = constant.Name;
151                         string fullname = Name + "." + basename;
152
153                         if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
154                                 return res;
155                         
156                         if (constants == null)
157                                 constants = new ArrayList ();
158
159                         constants.Add (constant);
160                         DefineName (fullname, constant);
161
162                         return AdditionResult.Success;
163                 }
164
165                 public AdditionResult AddEnum (Mono.CSharp.Enum e)
166                 {
167                         AdditionResult res;
168
169                         if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
170                                 return res;
171
172                         if (enums == null)
173                                 enums = new ArrayList ();
174
175                         enums.Add (e);
176                         DefineName (e.Name, e);
177
178                         return AdditionResult.Success;
179                 }
180                 
181                 public AdditionResult AddClass (Class c)
182                 {
183                         AdditionResult res;
184                         string name = c.Basename;
185                         
186                         if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
187                                 return res;
188
189                         DefineName (c.Name, c);
190                         types.Add (c);
191
192                         return AdditionResult.Success;
193                 }
194
195                 public AdditionResult AddStruct (Struct s)
196                 {
197                         AdditionResult res;
198                         string name = s.Basename;
199                         
200                         if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
201                                 return res;
202
203                         DefineName (s.Name, s);
204                         types.Add (s);
205
206                         return AdditionResult.Success;
207                 }
208
209                 public AdditionResult AddDelegate (Delegate d)
210                 {
211                         AdditionResult res;
212                         string name = d.Basename;
213                         
214                         if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
215                                 return res;
216
217                         if (delegates == null)
218                                 delegates = new ArrayList ();
219                         
220                         DefineName (d.Name, d);
221                         delegates.Add (d);
222
223                         return AdditionResult.Success;
224                 }
225
226                 public AdditionResult AddMethod (Method method)
227                 {
228                         string basename = method.Name;
229                         string fullname = Name + "." + basename;
230
231                         Object value = defined_names [fullname];
232
233                         if (value != null && (!(value is Method)))
234                                 return AdditionResult.NameExists;
235
236                         if (basename == Basename)
237                                 return AdditionResult.EnclosingClash;
238
239                         if (methods == null)
240                                 methods = new ArrayList ();
241
242                         if (method.Name.IndexOf ('.') != -1)
243                                 methods.Insert (0, method);
244                         else 
245                                 methods.Add (method);
246                         
247                         if (value == null)
248                                 DefineName (fullname, method);
249
250                         return AdditionResult.Success;
251                 }
252
253                 public AdditionResult AddConstructor (Constructor c)
254                 {
255                         if (c.Name != Basename) 
256                                 return AdditionResult.NotAConstructor;
257
258                         bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
259                         
260                         if (is_static){
261                                 UserDefinedStaticConstructor = true;
262                                 if (default_static_constructor != null)
263                                         return AdditionResult.MethodExists;
264
265                                 default_static_constructor = c;
266                         } else {
267                                 if (c.IsDefault ()){
268                                         if (default_constructor != null)
269                                                 return AdditionResult.MethodExists;
270                                         default_constructor = c;
271                                 }
272                                 
273                                 if (instance_constructors == null)
274                                         instance_constructors = new ArrayList ();
275                                 
276                                 instance_constructors.Add (c);
277                         }
278                         
279                         return AdditionResult.Success;
280                 }
281                 
282                 public AdditionResult AddInterface (Interface iface)
283                 {
284                         AdditionResult res;
285                         string name = iface.Basename;
286                         
287                         if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
288                                 return res;
289                         
290                         if (interfaces == null)
291                                 interfaces = new ArrayList ();
292                         interfaces.Add (iface);
293                         DefineName (iface.Name, iface);
294                         
295                         return AdditionResult.Success;
296                 }
297
298                 public AdditionResult AddField (Field field)
299                 {
300                         AdditionResult res;
301                         string basename = field.Name;
302                         string fullname = Name + "." + basename;
303
304                         if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
305                                 return res;
306                         
307                         if (fields == null)
308                                 fields = new ArrayList ();
309                         
310                         fields.Add (field);
311                         
312                         if (field.HasInitializer){
313                                 if ((field.ModFlags & Modifiers.STATIC) != 0){
314                                         if (initialized_static_fields == null)
315                                                 initialized_static_fields = new ArrayList ();
316
317                                         initialized_static_fields.Add (field);
318
319                                 } else {
320                                         if (initialized_fields == null)
321                                                 initialized_fields = new ArrayList ();
322                                 
323                                         initialized_fields.Add (field);
324                                 }
325                         }
326
327                         if ((field.ModFlags & Modifiers.STATIC) == 0)
328                                 have_nonstatic_fields = true;
329
330                         DefineName (fullname, field);
331                         return AdditionResult.Success;
332                 }
333
334                 public AdditionResult AddProperty (Property prop)
335                 {
336                         AdditionResult res;
337
338                         if ((res = AddProperty (prop, prop.Name)) != AdditionResult.Success)
339                                 return res;
340
341                         if (prop.Get != null) {
342                                 if ((res = AddProperty (prop, "get_" + prop.Name)) != AdditionResult.Success)
343                                         return res;
344                         }
345
346                         if (prop.Set != null) {
347                                 if ((res = AddProperty (prop, "set_" + prop.Name)) != AdditionResult.Success)
348                                 return res;
349                         }
350
351                         if (properties == null)
352                                 properties = new ArrayList ();
353
354                         if (prop.Name.IndexOf ('.') != -1)
355                                 properties.Insert (0, prop);
356                         else
357                                 properties.Add (prop);
358
359                         return AdditionResult.Success;
360                 }
361
362                 AdditionResult AddProperty (Property prop, string basename)
363                 {
364                         AdditionResult res;
365                         string fullname = Name + "." + basename;
366
367                         if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
368                                 return res;
369
370                         DefineName (fullname, prop);
371
372                         return AdditionResult.Success;
373                 }
374
375                 public AdditionResult AddEvent (Event e)
376                 {
377                         AdditionResult res;
378                         string basename = e.Name;
379                         string fullname = Name + "." + basename;
380
381                         if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
382                                 return res;
383
384                         if (events == null)
385                                 events = new ArrayList ();
386                         
387                         events.Add (e);
388                         DefineName (fullname, e);
389
390                         return AdditionResult.Success;
391                 }
392
393                 public void AddIndexer (Indexer i)
394                 {
395                         if (indexers == null)
396                                 indexers = new ArrayList ();
397
398                         if (i.ExplicitInterfaceName != null)
399                                 indexers.Insert (0, i);
400                         else
401                                 indexers.Add (i);
402                 }
403
404                 public AdditionResult AddOperator (Operator op)
405                 {
406                         if (operators == null)
407                                 operators = new ArrayList ();
408
409                         operators.Add (op);
410
411                         string basename = op.Name;
412                         string fullname = Name + "." + basename;
413                         if (!defined_names.Contains (fullname))
414                         {
415                                 DefineName (fullname, op);
416                         }
417                         return AdditionResult.Success;
418                 }
419
420                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
421                 {
422                         if (a.Type == TypeManager.default_member_type) {
423                                 if (Indexers != null) {
424                                         Report.Error (646, a.Location,
425                                                       "Cannot specify the DefaultMember attribute on" +
426                                                       " a type containing an indexer");
427                                         return;
428                                 }
429                         }
430                         
431                         base.ApplyAttributeBuilder (a, cb);
432                 } 
433
434                 public override AttributeTargets AttributeTargets {
435                         get {
436                                 throw new NotSupportedException ();
437                         }
438                 }
439
440                 public void RegisterOrder (Interface iface)
441                 {
442                         if (interface_order == null)
443                                 interface_order = new ArrayList ();
444
445                         interface_order.Add (iface);
446                 }
447                 
448                 public ArrayList Types {
449                         get {
450                                 return types;
451                         }
452                 }
453
454                 public ArrayList Methods {
455                         get {
456                                 return methods;
457                         }
458                 }
459
460                 public ArrayList Constants {
461                         get {
462                                 return constants;
463                         }
464                 }
465
466                 public ArrayList Interfaces {
467                         get {
468                                 return interfaces;
469                         }
470                 }
471                 
472                 public string Base {
473                         get {
474                                 return base_class_name;
475                         }
476                 }
477                 
478                 public ArrayList Bases {
479                         get {
480                                 return type_bases;
481                         }
482
483                         set {
484                                 type_bases = value;
485                         }
486                 }
487
488                 public ArrayList Fields {
489                         get {
490                                 return fields;
491                         }
492
493                         set {
494                                 fields = value;
495                         }
496                 }
497
498                 public ArrayList InstanceConstructors {
499                         get {
500                                 return instance_constructors;
501                         }
502                 }
503
504                 public ArrayList Properties {
505                         get {
506                                 return properties;
507                         }
508                 }
509
510                 public ArrayList Events {
511                         get {
512                                 return events;
513                         }
514                 }
515                 
516                 public ArrayList Enums {
517                         get {
518                                 return enums;
519                         }
520                 }
521
522                 public ArrayList Indexers {
523                         get {
524                                 return indexers;
525                         }
526                 }
527
528                 public ArrayList Operators {
529                         get {
530                                 return operators;
531                         }
532                 }
533
534                 public ArrayList Delegates {
535                         get {
536                                 return delegates;
537                         }
538                 }
539
540                 public virtual TypeAttributes TypeAttr {
541                         get {
542                                 return Modifiers.TypeAttr (ModFlags, this);
543                         }
544                 }
545
546                 //
547                 // Emits the instance field initializers
548                 //
549                 public bool EmitFieldInitializers (EmitContext ec)
550                 {
551                         ArrayList fields;
552                         Expression instance_expr;
553                         
554                         if (ec.IsStatic){
555                                 fields = initialized_static_fields;
556                                 instance_expr = null;
557                         } else {
558                                 fields = initialized_fields;
559                                 instance_expr = new This (Location.Null).Resolve (ec);
560                         }
561
562                         if (fields == null)
563                                 return true;
564
565                         foreach (Field f in fields){
566                                 Expression e = f.GetInitializerExpression (ec);
567                                 if (e == null)
568                                         return false;
569
570                                 Location l = f.Location;
571                                 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
572                                 fe.InstanceExpression = instance_expr;
573                                 ExpressionStatement a = new Assign (fe, e, l);
574
575                                 a = a.ResolveStatement (ec);
576                                 if (a == null)
577                                         return false;
578
579                                 a.EmitStatement (ec);
580                         }
581
582                         return true;
583                 }
584                 
585                 //
586                 // Defines the default constructors
587                 //
588                 void DefineDefaultConstructor (bool is_static)
589                 {
590                         Constructor c;
591
592                         // The default constructor is public
593                         // If the class is abstract, the default constructor is protected
594                         // The default static constructor is private
595
596                         int mods = Modifiers.PUBLIC;
597                         if (is_static)
598                                 mods = Modifiers.STATIC | Modifiers.PRIVATE;
599                         else if ((ModFlags & Modifiers.ABSTRACT) != 0)
600                                 mods = Modifiers.PROTECTED;
601
602                         c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
603                                              new ConstructorBaseInitializer (
604                                                      null, Parameters.EmptyReadOnlyParameters,
605                                                      Location),
606                                              Location);
607                         
608                         AddConstructor (c);
609                         
610                         c.Block = new ToplevelBlock (null, Location);
611                         
612                 }
613
614                 public void ReportStructInitializedInstanceError ()
615                 {
616                         string n = TypeBuilder.FullName;
617                         
618                         foreach (Field f in initialized_fields){
619                                 Report.Error (
620                                         573, Location,
621                                         "`" + n + "." + f.Name + "': can not have " +
622                                         "instance field initializers in structs");
623                         }
624                 }
625
626                 /// <remarks>
627                 ///  The pending methods that need to be implemented (interfaces or abstract methods)
628                 /// </remarks>
629                 public PendingImplementation Pending;
630
631                 /// <summary>
632                 ///   This function computes the Base class and also the
633                 ///   list of interfaces that the class or struct @c implements.
634                 ///   
635                 ///   The return value is an array (might be null) of
636                 ///   interfaces implemented (as Types).
637                 ///   
638                 ///   The @parent argument is set to the parent object or null
639                 ///   if this is `System.Object'. 
640                 /// </summary>
641                 TypeExpr [] GetClassBases (bool is_class, bool is_iface,
642                                            out TypeExpr parent, out bool error)
643                 {
644                         ArrayList bases = Bases;
645                         int count;
646                         int start, j, i;
647
648                         error = false;
649
650                         if (is_class || is_iface)
651                                 parent = null;
652                         else
653                                 parent = TypeManager.system_valuetype_expr;
654
655                         if (bases == null){
656                                 if (is_class){
657                                         if (RootContext.StdLib)
658                                                 parent = TypeManager.system_object_expr;
659                                         else if (Name != "System.Object")
660                                                 parent = TypeManager.system_object_expr;
661                                 } else {
662                                         //
663                                         // If we are compiling our runtime,
664                                         // and we are defining ValueType, then our
665                                         // parent is `System.Object'.
666                                         //
667                                         if (!RootContext.StdLib && Name == "System.ValueType")
668                                                 parent = TypeManager.system_object_expr;
669                                 }
670
671                                 return null;
672                         }
673
674                         //
675                         // Bases should be null if there are no bases at all
676                         //
677                         count = bases.Count;
678
679                         if (is_class){
680                                 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
681
682                                 if (name == null){
683                                         error = true;
684                                         return null;
685                                 }
686
687                                 if (name.IsClass){
688                                         parent = name;
689                                         start = 1;
690                                 } else {
691                                         parent = TypeManager.system_object_expr;
692                                         start = 0;
693                                 }
694                                 if (name.IsSealed){
695                                         string detail = "";
696                                         
697                                         if (name.IsValueType)
698                                                 detail = " (a class can not inherit from a struct/enum)";
699                                         
700                                         Report.Error (509, "class `"+ Name +
701                                                       "': Cannot inherit from sealed class `"+
702                                                       name.Name + "'" + detail);
703                                         error = true;
704                                         return null;
705                                 }
706
707                                 if (!parent.CanInheritFrom ()){
708                                         Report.Error (644, Location,
709                                                       "`{0}' cannot inherit from special class `{1}'",
710                                                       Name, parent.Name);
711                                         error = true;
712                                         return null;
713                                 }
714
715                                 if (!parent.AsAccessible (this, ModFlags))
716                                         Report.Error (60, Location,
717                                                       "Inconsistent accessibility: base class `" +
718                                                       name.Name + "' is less accessible than class `" +
719                                                       Name + "'");
720
721                         } else {
722                                 start = 0;
723                         }
724
725                         if (parent != null)
726                                 base_class_name = parent.Name;
727
728                         TypeExpr [] ifaces = new TypeExpr [count-start];
729                         
730                         for (i = start, j = 0; i < count; i++, j++){
731                                 Expression name = (Expression) bases [i];
732                                 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
733                                 if (resolved == null)
734                                         return null;
735                                 
736                                 bases [i] = resolved;
737
738                                 if (is_class == false && !resolved.IsInterface){
739                                         Report.Error (527, "In Struct `" + Name + "', type `"+
740                                                       name +"' is not an interface");
741                                         error = true;
742                                         return null;
743                                 }
744                                 
745                                 if (resolved.IsClass) {
746                                         if (parent != null){
747                                                 Report.Error (527, "In Class `" + Name + "', type `"+
748                                                               name+"' is not an interface");
749                                                 error = true;
750                                                 return null;
751                                         }
752                                 }
753
754                                 for (int x = 0; x < j; x++) {
755                                         if (resolved.Equals (ifaces [x])) {
756                                                 Report.Error (528, "`" + name + "' is already listed in interface list");
757                                                 error = true;
758                                                 return null;
759                                         }
760                                 }
761
762                                 if (is_iface &&
763                                     !resolved.AsAccessible (Parent, ModFlags))
764                                         Report.Error (61, Location,
765                                                       "Inconsistent accessibility: base interface `" +
766                                                       name + "' is less accessible than interface `" +
767                                                       Name + "'");
768
769                                 ifaces [j] = resolved;
770                         }
771
772                         return TypeManager.ExpandInterfaces (ifaces);
773                 }
774
775                 bool error = false;
776                 
777                 //
778                 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
779                 //
780                 public override TypeBuilder DefineType ()
781                 {
782                         TypeExpr parent;
783                         bool is_class, is_iface;
784
785                         if (TypeBuilder != null)
786                                 return TypeBuilder;
787
788                         if (error)
789                                 return null;
790                         
791                         if (InTransit) {
792                                 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
793                                 error = true;
794                                 return null;
795                         }
796                         
797                         InTransit = true;
798
799                         if (this is Interface) {
800                                 is_iface = true;
801                                 is_class = false;
802                         } else {
803                                 is_iface = false;
804                                 if (this is Class)
805                                         is_class = true;
806                                 else
807                                         is_class = false;
808                         }
809
810                         ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
811
812                         ifaces = GetClassBases (is_class, is_iface, out parent, out error); 
813
814                         if (error)
815                                 return null;
816
817                         if (!is_class && TypeManager.value_type == null)
818                                 throw new Exception ();
819
820                         TypeAttributes type_attributes = TypeAttr;
821
822                         if (parent != null)
823                                 base_classs_type = parent.ResolveType (ec);
824
825                         if (IsTopLevel){
826                                 if (TypeManager.NamespaceClash (Name, Location)) {
827                                         error = true;
828                                         return null;
829                                 }
830                                 
831                                 ModuleBuilder builder = CodeGen.Module.Builder;
832                                 TypeBuilder = builder.DefineType (
833                                         Name, type_attributes, base_classs_type, null);
834                                 
835                         } else {
836                                 TypeBuilder builder = Parent.DefineType ();
837                                 if (builder == null)
838                                         return null;
839                                 
840                                 TypeBuilder = builder.DefineNestedType (
841                                         Basename, type_attributes, base_classs_type, 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                 protected override void VerifyObsoleteAttribute()
2105                 {
2106                         CheckUsageOfObsoleteAttribute (base_classs_type);
2107
2108                         if (ifaces == null)
2109                                 return;
2110
2111                         foreach (TypeExpr expr in ifaces) {
2112                                 CheckUsageOfObsoleteAttribute (expr.Type);
2113                         }
2114                 }
2115
2116
2117                 //
2118                 // IMemberContainer
2119                 //
2120
2121                 string IMemberContainer.Name {
2122                         get {
2123                                 return Name;
2124                         }
2125                 }
2126
2127                 Type IMemberContainer.Type {
2128                         get {
2129                                 return TypeBuilder;
2130                         }
2131                 }
2132
2133                 IMemberContainer IMemberContainer.Parent {
2134                         get {
2135                                 return parent_container;
2136                         }
2137                 }
2138
2139                 MemberCache IMemberContainer.MemberCache {
2140                         get {
2141                                 return member_cache;
2142                         }
2143                 }
2144
2145                 bool IMemberContainer.IsInterface {
2146                         get {
2147                                 return this is Interface;
2148                         }
2149                 }
2150
2151                 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2152                 {
2153                         return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
2154                 }
2155
2156                 //
2157                 // Operator pair checking
2158                 //
2159
2160                 class OperatorEntry {
2161                         public int flags;
2162                         public Type ret_type;
2163                         public Type type1, type2;
2164                         public Operator op;
2165                         public Operator.OpType ot;
2166                         
2167                         public OperatorEntry (int f, Operator o)
2168                         {
2169                                 flags = f;
2170
2171                                 ret_type = o.OperatorMethod.GetReturnType ();
2172                                 Type [] pt = o.OperatorMethod.ParameterTypes;
2173                                 type1 = pt [0];
2174                                 type2 = pt [1];
2175                                 op = o;
2176                                 ot = o.OperatorType;
2177                         }
2178
2179                         public override int GetHashCode ()
2180                         {       
2181                                 return ret_type.GetHashCode ();
2182                         }
2183
2184                         public override bool Equals (object o)
2185                         {
2186                                 OperatorEntry other = (OperatorEntry) o;
2187
2188                                 if (other.ret_type != ret_type)
2189                                         return false;
2190                                 if (other.type1 != type1)
2191                                         return false;
2192                                 if (other.type2 != type2)
2193                                         return false;
2194                                 return true;
2195                         }
2196                 }
2197                                 
2198                 //
2199                 // Checks that some operators come in pairs:
2200                 //  == and !=
2201                 // > and <
2202                 // >= and <=
2203                 // true and false
2204                 //
2205                 // They are matched based on the return type and the argument types
2206                 //
2207                 void CheckPairedOperators ()
2208                 {
2209                         Hashtable pairs = new Hashtable (null, null);
2210                         Operator true_op = null;
2211                         Operator false_op = null;
2212                         bool has_equality_or_inequality = false;
2213                         
2214                         // Register all the operators we care about.
2215                         foreach (Operator op in operators){
2216                                 int reg = 0;
2217                                 
2218                                 switch (op.OperatorType){
2219                                 case Operator.OpType.Equality:
2220                                         reg = 1;
2221                                         has_equality_or_inequality = true;
2222                                         break;
2223                                 case Operator.OpType.Inequality:
2224                                         reg = 2;
2225                                         has_equality_or_inequality = true;
2226                                         break;
2227
2228                                 case Operator.OpType.True:
2229                                         true_op = op;
2230                                         break;
2231                                 case Operator.OpType.False:
2232                                         false_op = op;
2233                                         break;
2234                                         
2235                                 case Operator.OpType.GreaterThan:
2236                                         reg = 1; break;
2237                                 case Operator.OpType.LessThan:
2238                                         reg = 2; break;
2239                                         
2240                                 case Operator.OpType.GreaterThanOrEqual:
2241                                         reg = 1; break;
2242                                 case Operator.OpType.LessThanOrEqual:
2243                                         reg = 2; break;
2244                                 }
2245                                 if (reg == 0)
2246                                         continue;
2247
2248                                 OperatorEntry oe = new OperatorEntry (reg, op);
2249
2250                                 object o = pairs [oe];
2251                                 if (o == null)
2252                                         pairs [oe] = oe;
2253                                 else {
2254                                         oe = (OperatorEntry) o;
2255                                         oe.flags |= reg;
2256                                 }
2257                         }
2258
2259                         if (true_op != null){
2260                                 if (false_op == null)
2261                                         Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2262                         } else if (false_op != null)
2263                                 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2264                         
2265                         //
2266                         // Look for the mistakes.
2267                         //
2268                         foreach (DictionaryEntry de in pairs){
2269                                 OperatorEntry oe = (OperatorEntry) de.Key;
2270
2271                                 if (oe.flags == 3)
2272                                         continue;
2273
2274                                 string s = "";
2275                                 switch (oe.ot){
2276                                 case Operator.OpType.Equality:
2277                                         s = "!=";
2278                                         break;
2279                                 case Operator.OpType.Inequality: 
2280                                         s = "==";
2281                                         break;
2282                                 case Operator.OpType.GreaterThan: 
2283                                         s = "<";
2284                                         break;
2285                                 case Operator.OpType.LessThan:
2286                                         s = ">";
2287                                         break;
2288                                 case Operator.OpType.GreaterThanOrEqual:
2289                                         s = "<=";
2290                                         break;
2291                                 case Operator.OpType.LessThanOrEqual:
2292                                         s = ">=";
2293                                         break;
2294                                 }
2295                                 Report.Error (216, oe.op.Location,
2296                                               "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2297                         }
2298
2299                         if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2300                                 MethodSignature equals_ms = new MethodSignature (
2301                                         "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2302                                 MethodSignature hash_ms = new MethodSignature (
2303                                         "GetHashCode", TypeManager.int32_type, new Type [0]);
2304
2305                                 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2306                                                                     BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2307                                                                     equals_ms);
2308                                 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2309                                                                   BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2310                                                                   hash_ms);
2311
2312                                 bool equals_ok = false;
2313                                 if ((equals_ml != null) && (equals_ml.Count == 1))
2314                                         equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2315                                 bool hash_ok = false;
2316                                 if ((hash_ml != null) && (hash_ml.Count == 1))
2317                                         hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2318
2319                                 if (!equals_ok)
2320                                         Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2321                                                         "not override Object.Equals (object o)");
2322                                 if (!hash_ok)
2323                                         Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2324                                                         "not override Object.GetHashCode ()");
2325                         }
2326                 }
2327                 
2328                 
2329         }
2330
2331         public class ClassOrStruct : TypeContainer {
2332                 bool hasExplicitLayout = false;
2333                 public ClassOrStruct (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
2334                         : base (ns, parent, name, attrs, l)
2335                 {
2336                 }
2337
2338                 protected override void VerifyMembers (EmitContext ec) 
2339                 {
2340                         if (Fields != null) {
2341                                 foreach (Field f in Fields) {
2342                                         if ((f.ModFlags & Modifiers.STATIC) != 0)
2343                                                 continue;
2344                                         if (hasExplicitLayout) {
2345                                                 if (f.OptAttributes == null 
2346                                                     || !f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2347                                                         Report.Error (625, f.Location,
2348                                                                       "Instance field of type marked with" 
2349                                                                       + " StructLayout(LayoutKind.Explicit) must have a"
2350                                                                       + " FieldOffset attribute.");
2351                                                 }
2352                                         }
2353                                         else {
2354                                                 if (f.OptAttributes != null 
2355                                                     && f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2356                                                         Report.Error (636, f.Location,
2357                                                                       "The FieldOffset attribute can only be placed on members of "
2358                                                                       + "types marked with the StructLayout(LayoutKind.Explicit)");
2359                                                 }
2360                                         }
2361                                 }
2362                         }
2363                         base.VerifyMembers (ec);
2364                 }
2365
2366                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2367                 {
2368                         if (a.Type == TypeManager.struct_layout_attribute_type
2369                             && (LayoutKind) a.GetPositionalValue (0) == LayoutKind.Explicit)
2370                                 hasExplicitLayout = true;
2371
2372                         base.ApplyAttributeBuilder (a, cb);
2373                 }
2374         }
2375
2376         public class Class : ClassOrStruct {
2377                 // <summary>
2378                 //   Modifiers allowed in a class declaration
2379                 // </summary>
2380                 public const int AllowedModifiers =
2381                         Modifiers.NEW |
2382                         Modifiers.PUBLIC |
2383                         Modifiers.PROTECTED |
2384                         Modifiers.INTERNAL |
2385                         Modifiers.PRIVATE |
2386                         Modifiers.ABSTRACT |
2387                         Modifiers.SEALED |
2388                         Modifiers.UNSAFE;
2389
2390
2391                 // Information in the case we are an attribute type
2392                 AttributeUsageAttribute attribute_usage;
2393
2394                 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2395                               Attributes attrs, Location l)
2396                         : base (ns, parent, name, attrs, l)
2397                 {
2398                         int accmods;
2399
2400                         if (parent.Parent == null)
2401                                 accmods = Modifiers.INTERNAL;
2402                         else
2403                                 accmods = Modifiers.PRIVATE;
2404
2405                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2406                         attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
2407                 }
2408
2409                 public override AttributeTargets AttributeTargets {
2410                         get {
2411                                 return AttributeTargets.Class;
2412                         }
2413                 }
2414
2415                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
2416                 {
2417                         if (a.UsageAttribute != null)
2418                                 attribute_usage = a.UsageAttribute;
2419
2420                         base.ApplyAttributeBuilder (a, cb);
2421                 }
2422
2423                 public AttributeUsageAttribute AttributeUsage {
2424                         get {
2425                                 return attribute_usage;
2426                         }
2427                 }
2428
2429                 //
2430                 // FIXME: How do we deal with the user specifying a different
2431                 // layout?
2432                 //
2433                 public override TypeAttributes TypeAttr {
2434                         get {
2435                                 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2436                         }
2437                 }
2438         }
2439
2440         public class Struct : ClassOrStruct {
2441                 // <summary>
2442                 //   Modifiers allowed in a struct declaration
2443                 // </summary>
2444                 public const int AllowedModifiers =
2445                         Modifiers.NEW       |
2446                         Modifiers.PUBLIC    |
2447                         Modifiers.PROTECTED |
2448                         Modifiers.INTERNAL  |
2449                         Modifiers.UNSAFE    |
2450                         Modifiers.PRIVATE;
2451
2452                 public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2453                         : base (ns, parent, name, attrs, l)
2454                 {
2455                         int accmods;
2456                         
2457                         if (parent.Parent == null)
2458                                 accmods = Modifiers.INTERNAL;
2459                         else
2460                                 accmods = Modifiers.PRIVATE;
2461                         
2462                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2463
2464                         this.ModFlags |= Modifiers.SEALED;
2465                 }
2466
2467                 public override AttributeTargets AttributeTargets {
2468                         get {
2469                                 return AttributeTargets.Struct;
2470                         }
2471                 }
2472
2473
2474                 //
2475                 // FIXME: Allow the user to specify a different set of attributes
2476                 // in some cases (Sealed for example is mandatory for a class,
2477                 // but what SequentialLayout can be changed
2478                 //
2479                 public override TypeAttributes TypeAttr {
2480                         get {
2481                                 return base.TypeAttr |
2482                                         TypeAttributes.SequentialLayout |
2483                                         TypeAttributes.Sealed |
2484                                         TypeAttributes.BeforeFieldInit;
2485                         }
2486                 }
2487         }
2488
2489         /// <summary>
2490         ///   Interfaces
2491         /// </summary>
2492         public class Interface : TypeContainer, IMemberContainer {
2493                 /// <summary>
2494                 ///   Modifiers allowed in a class declaration
2495                 /// </summary>
2496                 public const int AllowedModifiers =
2497                         Modifiers.NEW       |
2498                         Modifiers.PUBLIC    |
2499                         Modifiers.PROTECTED |
2500                         Modifiers.INTERNAL  |
2501                         Modifiers.UNSAFE    |
2502                         Modifiers.PRIVATE;
2503
2504                 public Interface (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2505                                   Attributes attrs, Location l)
2506                         : base (ns, parent, name, attrs, l)
2507                 {
2508                         int accmods;
2509
2510                         if (parent.Parent == null)
2511                                 accmods = Modifiers.INTERNAL;
2512                         else
2513                                 accmods = Modifiers.PRIVATE;
2514
2515                         this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2516                 }
2517
2518                 public override AttributeTargets AttributeTargets {
2519                         get {
2520                                 return AttributeTargets.Interface;
2521                         }
2522                 }
2523
2524                 public override TypeAttributes TypeAttr {
2525                         get {
2526                                 return base.TypeAttr |
2527                                         TypeAttributes.AutoLayout |
2528                                         TypeAttributes.Abstract |
2529                                         TypeAttributes.Interface;
2530                         }
2531                 }
2532         }
2533
2534         public abstract class MethodCore : MemberBase {
2535                 public readonly Parameters Parameters;
2536                 protected Block block;
2537                 public DeclSpace ds;
2538                 
2539                 //
2540                 // Parameters, cached for semantic analysis.
2541                 //
2542                 protected InternalParameters parameter_info;
2543                 protected Type [] parameter_types;
2544
2545                 // <summary>
2546                 //   This is set from TypeContainer.DefineMembers if this method overrides something.
2547                 // </summary>
2548                 public bool OverridesSomething;
2549
2550                 // Whether this is an operator method.
2551                 public bool IsOperator;
2552
2553                 static string[] attribute_targets = new string [] { "method", "return" };
2554
2555                 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2556                                    bool is_interface, string name, Attributes attrs,
2557                                    Parameters parameters, Location loc)
2558                         : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2559                 {
2560                         Parameters = parameters;
2561                         IsInterface = is_interface;
2562                         this.ds = ds;
2563                 }
2564                 
2565                 //
2566                 //  Returns the System.Type array for the parameters of this method
2567                 //
2568                 public Type [] ParameterTypes {
2569                         get {
2570                                 return parameter_types;
2571                         }
2572                 }
2573
2574                 public InternalParameters ParameterInfo
2575                 {
2576                         get {
2577                                 return parameter_info;
2578                         }
2579                 }
2580                 
2581                 public Block Block {
2582                         get {
2583                                 return block;
2584                         }
2585
2586                         set {
2587                                 block = value;
2588                         }
2589                 }
2590
2591                 protected virtual bool DoDefineParameters ()
2592                 {
2593                         // Check if arguments were correct
2594                         parameter_types = Parameters.GetParameterInfo (ds);
2595                         if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2596                                 return false;
2597
2598                         parameter_info = new InternalParameters (ds, Parameters);
2599
2600                         Parameter array_param = Parameters.ArrayParameter;
2601                         if ((array_param != null) &&
2602                             (!array_param.ParameterType.IsArray ||
2603                              (array_param.ParameterType.GetArrayRank () != 1))) {
2604                                 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2605                                 return false;
2606                         }
2607
2608                         return true;
2609                 }
2610
2611                 protected override string[] ValidAttributeTargets {
2612                         get {
2613                                 return attribute_targets;
2614                         }
2615                 }
2616
2617                 protected override bool VerifyClsCompliance (DeclSpace ds)
2618                 {
2619                         if (!base.VerifyClsCompliance (ds)) {
2620                                 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
2621                                         Report.Error_T (3011, Location, GetSignatureForError ());
2622                                 }
2623                                 return false;
2624                         }
2625
2626                         AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
2627
2628                         if (!AttributeTester.IsClsCompliant (MemberType)) {
2629                                 Report.Error_T (3002, Location, GetSignatureForError ());
2630                         }
2631
2632                         return true;
2633                 }
2634
2635                 protected bool IsDuplicateImplementation (TypeContainer tc, MethodCore method)
2636                 {
2637                         if ((method == this) || (method.Name != Name))
2638                                 return false;
2639
2640                         Type[] param_types = method.ParameterTypes;
2641                         if (param_types == null)
2642                                 return false;
2643
2644                         if (param_types.Length != ParameterTypes.Length)
2645                                 return false;
2646
2647                         for (int i = 0; i < param_types.Length; i++)
2648                                 if (param_types [i] != ParameterTypes [i])
2649                                         return false;
2650
2651                         //
2652                         // Try to report 663: method only differs on out/ref
2653                         //
2654                         ParameterData info = ParameterInfo;
2655                         ParameterData other_info = method.ParameterInfo;
2656                         for (int i = 0; i < info.Count; i++){
2657                                 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
2658                                         Report.Error (663, Location, "Overload method only differs in parameter modifier");
2659                                         return false;
2660                                 }
2661                         }
2662
2663                         Report.Error (111, Location, "Class `{0}' already defines a " +
2664                                       "member called `{1}' with the same parameter types",
2665                                       tc.Name, Name);
2666                         return true;
2667                 }
2668
2669                 public CallingConventions GetCallingConvention (bool is_class)
2670                 {
2671                         CallingConventions cc = 0;
2672                         
2673                         cc = Parameters.GetCallingConvention ();
2674
2675                         if (is_class)
2676                                 if ((ModFlags & Modifiers.STATIC) == 0)
2677                                         cc |= CallingConventions.HasThis;
2678
2679                         // FIXME: How is `ExplicitThis' used in C#?
2680                         
2681                         return cc;
2682                 }
2683
2684                 protected override void VerifyObsoleteAttribute()
2685                 {
2686                         base.VerifyObsoleteAttribute ();
2687
2688                         if (parameter_types == null)
2689                                 return;
2690
2691                         foreach (Type type in parameter_types) {
2692                                 CheckUsageOfObsoleteAttribute (type);
2693                         }
2694                 }
2695         }
2696
2697         public class Method : MethodCore, IIteratorContainer, IMethodData {
2698                 public MethodBuilder MethodBuilder;
2699                 public MethodData MethodData;
2700                 ReturnParameter return_attributes;
2701
2702                 /// <summary>
2703                 ///   Modifiers allowed in a class declaration
2704                 /// </summary>
2705                 const int AllowedModifiers =
2706                         Modifiers.NEW |
2707                         Modifiers.PUBLIC |
2708                         Modifiers.PROTECTED |
2709                         Modifiers.INTERNAL |
2710                         Modifiers.PRIVATE |
2711                         Modifiers.STATIC |
2712                         Modifiers.VIRTUAL |
2713                         Modifiers.SEALED |
2714                         Modifiers.OVERRIDE |
2715                         Modifiers.ABSTRACT |
2716                         Modifiers.UNSAFE |
2717                         Modifiers.METHOD_YIELDS | 
2718                         Modifiers.EXTERN;
2719
2720                 const int AllowedInterfaceModifiers =
2721                         Modifiers.NEW | Modifiers.UNSAFE;
2722
2723                 //
2724                 // return_type can be "null" for VOID values.
2725                 //
2726                 public Method (DeclSpace ds, Expression return_type, int mod, bool is_iface,
2727                                string name, Parameters parameters, Attributes attrs, Location l)
2728                         : base (ds, return_type, mod,
2729                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
2730                                 is_iface, name, attrs, parameters, l)
2731                 {
2732                 }
2733
2734                 public override AttributeTargets AttributeTargets {
2735                         get {
2736                                 return AttributeTargets.Method | AttributeTargets.ReturnValue;
2737                         }
2738                 }
2739                 
2740                 //
2741                 // Returns the `System.Type' for the ReturnType of this
2742                 // function.  Provides a nice cache.  (used between semantic analysis
2743                 // and actual code generation
2744                 //
2745                 public Type GetReturnType ()
2746                 {
2747                         return MemberType;
2748                 }
2749
2750                 public override string GetSignatureForError()
2751                 {
2752                         return TypeManager.CSharpSignature (MethodBuilder);
2753                 }
2754
2755                 /// <summary>
2756                 /// Use this method when MethodBuilder is null
2757                 /// </summary>
2758                 public override string GetSignatureForError (TypeContainer tc)
2759                 {
2760                         // TODO: move to parameters
2761                         System.Text.StringBuilder args = new System.Text.StringBuilder ();
2762                         if (parameter_info.Parameters.FixedParameters != null) {
2763                                 for (int i = 0; i < parameter_info.Parameters.FixedParameters.Length; ++i) {
2764                                         Parameter p = parameter_info.Parameters.FixedParameters [i];
2765                                         args.Append (p.GetSignatureForError ());
2766
2767                                         if (i < parameter_info.Parameters.FixedParameters.Length - 1)
2768                                                 args.Append (',');
2769                                 }
2770                         }
2771
2772                         return String.Concat (base.GetSignatureForError (tc), "(", args.ToString (), ")");
2773                 }
2774
2775                 void DuplicateEntryPoint (MethodInfo b, Location location)
2776                 {
2777                         Report.Error (
2778                                 17, location,
2779                                 "Program `" + CodeGen.FileName +
2780                                 "'  has more than one entry point defined: `" +
2781                                 TypeManager.CSharpSignature(b) + "'");
2782                 }
2783
2784                 void Report28 (MethodInfo b)
2785                 {
2786                         Report.Warning (
2787                                 28, Location,
2788                                 "`" + TypeManager.CSharpSignature(b) +
2789                                 "' has the wrong signature to be an entry point");
2790                 }
2791
2792                 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2793                 {
2794                         if (b.ReturnType != TypeManager.void_type &&
2795                             b.ReturnType != TypeManager.int32_type)
2796                                 return false;
2797
2798                         if (pinfo.Count == 0)
2799                                 return true;
2800
2801                         if (pinfo.Count > 1)
2802                                 return false;
2803
2804                         Type t = pinfo.ParameterType(0);
2805                         if (t.IsArray &&
2806                             (t.GetArrayRank() == 1) &&
2807                             (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2808                             (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2809                                 return true;
2810                         else
2811                                 return false;
2812                 }
2813
2814                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2815                 {
2816                         if (a.Target == "return") {
2817                                 if (return_attributes == null)
2818                                         return_attributes = new ReturnParameter (MethodBuilder, Location);
2819
2820                                 return_attributes.ApplyAttributeBuilder (a, cb);
2821                                 return;
2822                         }
2823
2824                         if (a.Type == TypeManager.methodimpl_attr_type && a.IsInternalCall) {
2825                                 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
2826                         }
2827
2828                         if (a.Type == TypeManager.dllimport_type) {
2829                                 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2830                                 if ((ModFlags & extern_static) != extern_static) {
2831                                         //"The DllImport attribute must be specified on a method marked `static' and `extern'"
2832                                         Report.Error_T (601, a.Location);
2833                                 }
2834
2835                                 return;
2836                         }
2837
2838                         MethodBuilder.SetCustomAttribute (cb);
2839                 }
2840
2841                 //
2842                 // Checks our base implementation if any
2843                 //
2844                 protected override bool CheckBase (TypeContainer container)
2845                 {
2846                         base.CheckBase (container);
2847                         
2848                         // Check whether arguments were correct.
2849                         if (!DoDefineParameters ())
2850                                 return false;
2851
2852                         MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2853                         if (IsOperator) {
2854                                 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2855                         } else {
2856                                 //
2857                                 // Check in our class for dups
2858                                 //
2859                                 ArrayList ar = container.Methods;
2860                                 if (ar != null) {
2861                                         int arLen = ar.Count;
2862                                         
2863                                         for (int i = 0; i < arLen; i++) {
2864                                                 Method m = (Method) ar [i];
2865                                                 if (IsDuplicateImplementation (container, m))
2866                                                         return false;
2867                                         }
2868                                 }
2869                         }
2870                         
2871
2872                         //
2873                         // Verify if the parent has a type with the same name, and then
2874                         // check whether we have to create a new slot for it or not.
2875                         //
2876                         Type ptype = container.TypeBuilder.BaseType;
2877
2878                         // ptype is only null for System.Object while compiling corlib.
2879                         if (ptype != null) {
2880                                 
2881                                 //
2882                                 // Explicit implementations do not have `parent' methods, however,
2883                                 // the member cache stores them there. Without this check, we get
2884                                 // an incorrect warning in corlib.
2885                                 //
2886                                 if (! IsExplicitImpl) {
2887                                         parent_method = (MethodInfo)((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
2888                                                 container.TypeBuilder, Name, ParameterTypes, false);
2889                                 }
2890                                 
2891                                 if (parent_method != null) {
2892                                         string name = parent_method.DeclaringType.Name + "." +
2893                                                 parent_method.Name;
2894
2895                                         if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2896                                                 return false;
2897
2898                                         if ((ModFlags & Modifiers.NEW) == 0) {
2899                                                 Type parent_ret = TypeManager.TypeToCoreType (
2900                                                         parent_method.ReturnType);
2901
2902                                                 if (parent_ret != MemberType) {
2903                                                         Report.Error (
2904                                                                 508, Location, container.MakeName (Name) + ": cannot " +
2905                                                                 "change return type when overriding " +
2906                                                                 "inherited member " + name);
2907                                                         return false;
2908                                                 }
2909                                         }
2910
2911                                         ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (parent_method);
2912                                         if (oa != null) {
2913                                                 Report.SymbolRelatedToPreviousError (parent_method);
2914                                                 Report.Warning_T (672, Location, GetSignatureForError (container));
2915                                         }
2916                                 } else {
2917                                         if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2918                                                 WarningNotHiding (container);
2919
2920                                         if ((ModFlags & Modifiers.OVERRIDE) != 0){
2921                                                 Report.Error (115, Location,
2922                                                               container.MakeName (Name) +
2923                                                               " no suitable methods found to override");
2924                                         }
2925                                 }
2926                         } else if ((ModFlags & Modifiers.NEW) != 0)
2927                                 WarningNotHiding (container);
2928
2929                         return true;
2930                 }
2931
2932                 //
2933                 // Creates the type
2934                 //
2935                 public override bool Define (TypeContainer container)
2936                 {
2937                         if (!DoDefine (container))
2938                                 return false;
2939
2940                         if (!CheckBase (container))
2941                                 return false;
2942
2943                         MethodData = new MethodData (this, ParameterInfo, ModFlags, flags, true, this);
2944
2945                         if (!MethodData.Define (container))
2946                                 return false;
2947
2948                         //
2949                         // Setup iterator if we are one
2950                         //
2951                         if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2952                                 IteratorHandler ih = new  IteratorHandler (
2953                                             Name, container, MemberType,
2954                                             ParameterTypes, ParameterInfo,
2955                                             ModFlags, Location);
2956
2957                                 Block new_block = ih.Setup (block);
2958                                 if (new_block == null)
2959                                         return false;
2960                                 block = new_block;
2961                         }
2962
2963                         MethodBuilder = MethodData.MethodBuilder;
2964                         
2965                         //
2966                         // This is used to track the Entry Point,
2967                         //
2968                         if (Name == "Main" &&
2969                             ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint && 
2970                             (RootContext.MainClass == null ||
2971                              RootContext.MainClass == container.TypeBuilder.FullName)){
2972                                 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2973                                         if (RootContext.EntryPoint == null) {
2974                                                 RootContext.EntryPoint = MethodBuilder;
2975                                                 RootContext.EntryPointLocation = Location;
2976                                         } else {
2977                                                 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2978                                                 DuplicateEntryPoint (MethodBuilder, Location);
2979                                         }
2980                                 } else                                  
2981                                         Report28(MethodBuilder);
2982                         }
2983
2984                         return true;
2985                 }
2986
2987                 //
2988                 // Emits the code
2989                 // 
2990                 public override void Emit (TypeContainer container)
2991                 {
2992                         MethodData.Emit (container, this);
2993                         base.Emit (container);
2994                         Block = null;
2995                         MethodData = null;
2996                 }
2997
2998                 void IIteratorContainer.SetYields ()
2999                 {
3000                         ModFlags |= Modifiers.METHOD_YIELDS;
3001                 }
3002         
3003                 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3004                 {
3005                         return IsIdentifierAndParamClsCompliant (ds, Name, MethodBuilder, parameter_types);
3006                 }
3007
3008                 #region IMethodData Members
3009
3010                 public CallingConventions CallingConventions {
3011                         get {
3012                                 CallingConventions cc = Parameters.GetCallingConvention ();
3013
3014                                 if (!IsInterface)
3015                                         if ((ModFlags & Modifiers.STATIC) == 0)
3016                                                 cc |= CallingConventions.HasThis;
3017
3018                                 // FIXME: How is `ExplicitThis' used in C#?
3019                         
3020                                 return cc;
3021                         }
3022                 }
3023
3024                 public Type ReturnType {
3025                         get {
3026                                 return MemberType;
3027                         }
3028                 }
3029
3030                 public string MethodName {
3031                         get {
3032                                 return ShortName;
3033                         }
3034                 }
3035
3036                 public new Location Location {
3037                         get {
3038                                 return base.Location;
3039                         }
3040                 }
3041
3042                 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
3043                 {
3044                         return new EmitContext (tc, ds, Location, ig, ReturnType, ModFlags, false);
3045                 }
3046
3047                 public ObsoleteAttribute GetObsoleteAttribute ()
3048                 {
3049                         return GetObsoleteAttribute (ds);
3050                 }
3051
3052                 /// <summary>
3053                 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
3054                 /// </summary>
3055                 public bool IsExcluded (EmitContext ec)
3056                 {
3057                         if ((caching_flags & Flags.Excluded_Undetected) == 0)
3058                                 return (caching_flags & Flags.Excluded) != 0;
3059
3060                         caching_flags &= ~Flags.Excluded_Undetected;
3061
3062                         if (parent_method == null) {
3063                                 if (OptAttributes == null)
3064                                         return false;
3065
3066                                 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type, ec);
3067
3068                                 if (attrs == null)
3069                                         return false;
3070
3071                                 foreach (Attribute a in attrs) {
3072                                         string condition = a.GetConditionalAttributeValue (ds);
3073                                         if (RootContext.AllDefines.Contains (condition))
3074                                                 return false;
3075                                 }
3076
3077                                 caching_flags |= Flags.Excluded;
3078                                 return true;
3079                         }
3080
3081                         IMethodData md = TypeManager.GetMethod (parent_method);
3082                         if (md == null) {
3083                                 if (AttributeTester.IsConditionalMethodExcluded (parent_method)) {
3084                                         caching_flags |= Flags.Excluded;
3085                                         return true;
3086                                 }
3087                                 return false;
3088                         }
3089
3090                         if (md.IsExcluded (ec)) {
3091                                 caching_flags |= Flags.Excluded;
3092                                 return true;
3093                         }
3094                         return false;
3095                 }
3096
3097                 #endregion
3098         }
3099
3100         public abstract class ConstructorInitializer {
3101                 ArrayList argument_list;
3102                 protected ConstructorInfo parent_constructor;
3103                 Parameters parameters;
3104                 Location loc;
3105                 
3106                 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
3107                                                Location loc)
3108                 {
3109                         this.argument_list = argument_list;
3110                         this.parameters = parameters;
3111                         this.loc = loc;
3112                 }
3113
3114                 public ArrayList Arguments {
3115                         get {
3116                                 return argument_list;
3117                         }
3118                 }
3119
3120                 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
3121                 {
3122                         Expression parent_constructor_group;
3123                         Type t;
3124
3125                         ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
3126
3127                         if (argument_list != null){
3128                                 foreach (Argument a in argument_list){
3129                                         if (!a.Resolve (ec, loc))
3130                                                 return false;
3131                                 }
3132                         }
3133                         ec.CurrentBlock = null;
3134
3135                         if (this is ConstructorBaseInitializer) {
3136                                 if (ec.ContainerType.BaseType == null)
3137                                         return true;
3138
3139                                 t = ec.ContainerType.BaseType;
3140                                 if (ec.ContainerType.IsValueType) {
3141                                         Report.Error (522, loc,
3142                                                 "structs cannot call base class constructors");
3143                                         return false;
3144                                 }
3145                         } else
3146                                 t = ec.ContainerType;
3147
3148                         parent_constructor_group = Expression.MemberLookup (
3149                                 ec, t, ".ctor", MemberTypes.Constructor,
3150                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3151                                 loc);
3152                         
3153                         if (parent_constructor_group == null){
3154                                 parent_constructor_group = Expression.MemberLookup (
3155                                         ec, t, ".ctor", MemberTypes.Constructor,
3156                                         BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3157                                         loc);
3158
3159                                 if (parent_constructor_group != null)
3160                                         Report.Error (
3161                                                 112, loc, "`{0}.{1}' is inaccessible due to " +
3162                                                 "its protection level", t.FullName, t.Name);
3163                                 else
3164                                         Report.Error (
3165                                                 1501, loc, "Can not find a constructor for " +
3166                                                 "this argument list");
3167                                 return false;
3168                         }
3169                         
3170                         parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
3171                                 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
3172                         
3173                         if (parent_constructor == null){
3174                                 Report.Error (1501, loc,
3175                                        "Can not find a constructor for this argument list");
3176                                 return false;
3177                         }
3178
3179                         if (parent_constructor == caller_builder){
3180                                 Report.Error (515, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
3181                                 return false;
3182                         }
3183                         
3184                         return true;
3185                 }
3186
3187                 public void Emit (EmitContext ec)
3188                 {
3189                         if (parent_constructor != null){
3190                                 ec.Mark (loc, false);
3191                                 if (ec.IsStatic)
3192                                         Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
3193                                 else
3194                                         Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
3195                         }
3196                 }
3197
3198                 /// <summary>
3199                 /// Method search for base ctor. (We do not cache it).
3200                 /// </summary>
3201                 Constructor GetOverloadedConstructor (TypeContainer tc)
3202                 {
3203                         if (tc.InstanceConstructors == null)
3204                                 return null;
3205
3206                         foreach (Constructor c in tc.InstanceConstructors) {
3207                                 if (Arguments == null) {
3208                                         if (c.ParameterTypes.Length == 0)
3209                                                 return c;
3210
3211                                         continue;
3212                                 }
3213
3214                                 bool ok = true;
3215
3216                                 int count = c.ParameterInfo.Count;
3217                                 if ((count > 0) &&
3218                                     c.ParameterInfo.ParameterModifier (count - 1) == Parameter.Modifier.PARAMS) {
3219                                         for (int i = 0; i < count-1; i++)
3220                                                 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
3221                                                         ok = false;
3222                                                         break;
3223                                                 }
3224                                 } else {
3225                                         if (c.ParameterTypes.Length != Arguments.Count)
3226                                                 continue;
3227
3228                                         for (int i = 0; i < Arguments.Count; ++i)
3229                                                 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
3230                                                         ok = false;
3231                                                         break;
3232                                                 }
3233                                 }
3234
3235                                 if (!ok)
3236                                         continue;
3237
3238                                 return c;
3239                         }
3240
3241                         throw new InternalErrorException ();
3242                 }
3243
3244                 //TODO: implement caching when it will be necessary
3245                 public virtual void CheckObsoleteAttribute (TypeContainer tc, Location loc)
3246                 {
3247                         Constructor ctor = GetOverloadedConstructor (tc);
3248                         if (ctor == null)
3249                                 return;
3250
3251                         ObsoleteAttribute oa = ctor.GetObsoleteAttribute (tc);
3252                         if (oa == null)
3253                                 return;
3254
3255                         AttributeTester.Report_ObsoleteMessage (oa, ctor.GetSignatureForError (), loc);
3256                 }
3257         }
3258
3259         public class ConstructorBaseInitializer : ConstructorInitializer {
3260                 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
3261                         base (argument_list, pars, l)
3262                 {
3263                 }
3264
3265                 public override void CheckObsoleteAttribute(TypeContainer tc, Location loc) {
3266                         if (parent_constructor == null)
3267                                 return;
3268
3269                         TypeContainer type_ds = TypeManager.LookupTypeContainer (tc.base_classs_type);
3270                         if (type_ds == null) {
3271                                 ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (parent_constructor);
3272
3273                                 if (oa != null)
3274                                         AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (parent_constructor), loc);
3275
3276                                 return;
3277                         }
3278
3279                         base.CheckObsoleteAttribute (type_ds, loc);
3280                 }
3281
3282         }
3283
3284         public class ConstructorThisInitializer : ConstructorInitializer {
3285                 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
3286                         base (argument_list, pars, l)
3287                 {
3288                 }
3289         }
3290         
3291         public class Constructor : MethodCore {
3292                 public ConstructorBuilder ConstructorBuilder;
3293                 public ConstructorInitializer Initializer;
3294
3295                 // <summary>
3296                 //   Modifiers allowed for a constructor.
3297                 // </summary>
3298                 public const int AllowedModifiers =
3299                         Modifiers.PUBLIC |
3300                         Modifiers.PROTECTED |
3301                         Modifiers.INTERNAL |
3302                         Modifiers.STATIC |
3303                         Modifiers.UNSAFE |
3304                         Modifiers.EXTERN |              
3305                         Modifiers.PRIVATE;
3306
3307                 bool has_compliant_args = false;
3308                 //
3309                 // The spec claims that static is not permitted, but
3310                 // my very own code has static constructors.
3311                 //
3312                 public Constructor (DeclSpace ds, string name, int mod, Parameters args,
3313                                     ConstructorInitializer init, Location l)
3314                         : base (ds, null, mod, AllowedModifiers, false, name, null, args, l)
3315                 {
3316                         Initializer = init;
3317                 }
3318
3319                 public override string GetSignatureForError()
3320                 {
3321                         return TypeManager.CSharpSignature (ConstructorBuilder);
3322                 }
3323
3324                 public bool HasCompliantArgs {
3325                         get {
3326                                 return has_compliant_args;
3327                         }
3328                 }
3329
3330                 public override AttributeTargets AttributeTargets {
3331                         get {
3332                                 return AttributeTargets.Constructor;
3333                         }
3334                 }
3335
3336
3337                 //
3338                 // Returns true if this is a default constructor
3339                 //
3340                 public bool IsDefault ()
3341                 {
3342                         if ((ModFlags & Modifiers.STATIC) != 0)
3343                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3344                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty);
3345                         
3346                         else
3347                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3348                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
3349                                         (Initializer is ConstructorBaseInitializer) &&
3350                                         (Initializer.Arguments == null);
3351                 }
3352
3353                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3354                 {
3355                         ConstructorBuilder.SetCustomAttribute (cb);
3356                 }
3357                 
3358                 protected override bool CheckBase (TypeContainer container)
3359                 {
3360                         base.CheckBase (container);
3361                         
3362                         // Check whether arguments were correct.
3363                         if (!DoDefineParameters ())
3364                                 return false;
3365                         
3366                         if ((ModFlags & Modifiers.STATIC) != 0)
3367                                 return true;
3368                         
3369                         if (container is Struct && ParameterTypes.Length == 0) {
3370                                 Report.Error (568, Location, 
3371                                         "Structs can not contain explicit parameterless " +
3372                                         "constructors");
3373                                 return false;
3374                         }
3375                                 
3376                         //
3377                         // Check in our class for dups
3378                         //
3379                         ArrayList ar = container.InstanceConstructors;
3380                         if (ar != null) {
3381                                 int arLen = ar.Count;
3382                                         
3383                                 for (int i = 0; i < arLen; i++) {
3384                                         Constructor m = (Constructor) ar [i];
3385                                         if (IsDuplicateImplementation (container, m))
3386                                                 return false;
3387                                 }
3388                         }
3389                         
3390                         return true;
3391                 }
3392                 
3393                 //
3394                 // Creates the ConstructorBuilder
3395                 //
3396                 public override bool Define (TypeContainer container)
3397                 {
3398                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
3399                                                MethodAttributes.SpecialName);
3400                         
3401                         if ((ModFlags & Modifiers.STATIC) != 0) {
3402                                 ca |= MethodAttributes.Static | MethodAttributes.Private;
3403                         } else {
3404                                 ca |= MethodAttributes.HideBySig;
3405
3406                                 if ((ModFlags & Modifiers.PUBLIC) != 0)
3407                                         ca |= MethodAttributes.Public;
3408                                 else if ((ModFlags & Modifiers.PROTECTED) != 0){
3409                                         if ((ModFlags & Modifiers.INTERNAL) != 0)
3410                                                 ca |= MethodAttributes.FamORAssem;
3411                                         else 
3412                                                 ca |= MethodAttributes.Family;
3413                                 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
3414                                         ca |= MethodAttributes.Assembly;
3415                                 else if (IsDefault ())
3416                                         ca |= MethodAttributes.Public;
3417                                 else
3418                                         ca |= MethodAttributes.Private;
3419                         }
3420                         
3421                         // Check if arguments were correct.
3422                         if (!CheckBase (container))
3423                                 return false;
3424
3425                         ConstructorBuilder = container.TypeBuilder.DefineConstructor (
3426                                 ca, GetCallingConvention (container is Class), ParameterTypes);
3427
3428                         if ((ModFlags & Modifiers.UNSAFE) != 0)
3429                                 ConstructorBuilder.InitLocals = false;
3430                         
3431                         //
3432                         // HACK because System.Reflection.Emit is lame
3433                         //
3434                         TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
3435
3436                         return true;
3437                 }
3438
3439                 //
3440                 // Emits the code
3441                 //
3442                 public override void Emit (TypeContainer container)
3443                 {
3444                         ILGenerator ig = ConstructorBuilder.GetILGenerator ();
3445                         EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
3446
3447                         //
3448                         // extern methods have no bodies
3449                         //
3450                         if ((ModFlags & Modifiers.EXTERN) != 0) {
3451                                 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
3452                                         Report.Error (
3453                                                 179, Location, "External constructor `" +
3454                                                 TypeManager.CSharpSignature (ConstructorBuilder) +
3455                                                 "' can not have a body");
3456                                         return;
3457                                 }
3458                         } else if (block == null) {
3459                                 Report.Error (
3460                                         501, Location, "Constructor `" +
3461                                         TypeManager.CSharpSignature (ConstructorBuilder) +
3462                                         "' must declare a body since it is not marked extern");
3463                                 return;
3464                         }
3465
3466                         if ((ModFlags & Modifiers.STATIC) == 0){
3467                                 if (container is Class && Initializer == null)
3468                                         Initializer = new ConstructorBaseInitializer (
3469                                                 null, Parameters.EmptyReadOnlyParameters, Location);
3470
3471
3472                                 //
3473                                 // Spec mandates that Initializers will not have
3474                                 // `this' access
3475                                 //
3476                                 ec.IsStatic = true;
3477                                 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
3478                                         return;
3479                                 ec.IsStatic = false;
3480                         }
3481
3482                         Parameters.LabelParameters (ec, ConstructorBuilder, Location);
3483                         
3484                         SymbolWriter sw = CodeGen.SymbolWriter;
3485                         bool generate_debugging = false;
3486
3487                         if ((sw != null) && (block != null) &&
3488                                 !Location.IsNull (Location) &&
3489                                 !Location.IsNull (block.EndLocation) &&
3490                                 (Location.SymbolDocument != null)) {
3491                                 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
3492
3493                                 generate_debugging = true;
3494                         }
3495
3496                         //
3497                         // Classes can have base initializers and instance field initializers.
3498                         //
3499                         if (container is Class){
3500                                 if ((ModFlags & Modifiers.STATIC) == 0){
3501
3502                                         //
3503                                         // If we use a "this (...)" constructor initializer, then
3504                                         // do not emit field initializers, they are initialized in the other constructor
3505                                         //
3506                                         if (!(Initializer != null && Initializer is ConstructorThisInitializer))
3507                                                 container.EmitFieldInitializers (ec);
3508                                 }
3509                         }
3510                         if (Initializer != null) {
3511                                 Initializer.CheckObsoleteAttribute (container, Location);
3512                                 Initializer.Emit (ec);
3513                         }
3514                         
3515                         if ((ModFlags & Modifiers.STATIC) != 0)
3516                                 container.EmitFieldInitializers (ec);
3517
3518                         if (OptAttributes != null) 
3519                                 OptAttributes.Emit (ec, this);
3520
3521                         // If this is a non-static `struct' constructor and doesn't have any
3522                         // initializer, it must initialize all of the struct's fields.
3523                         if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
3524                                 Block.AddThisVariable (container, Location);
3525
3526                         ec.EmitTopBlock (block, ParameterInfo, Location);
3527
3528                         if (generate_debugging)
3529                                 sw.CloseMethod ();
3530
3531                         base.Emit (container);
3532
3533                         block = null;
3534                 }
3535
3536                 // For constructors is needed to test only parameters
3537                 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3538                 {
3539                         if (parameter_types == null || parameter_types.Length == 0)
3540                                 return true;
3541
3542                         TypeContainer tc = ds as TypeContainer;
3543
3544                         for (int i = 0; i < tc.InstanceConstructors.Count; i++) {
3545                                 Constructor c = (Constructor) tc.InstanceConstructors [i];
3546                                                 
3547                                 if (c == this || c.ParameterTypes.Length == 0)
3548                                         continue;
3549
3550                                 if (!c.IsClsCompliaceRequired (ds))
3551                                         continue;
3552                                 
3553                                 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, c.ParameterTypes)) {
3554                                         Report.Error_T (3006, Location, GetSignatureForError ());
3555                                         return false;
3556                                 }
3557                         }
3558
3559                         if (tc.TypeBuilder.BaseType == null)
3560                                 return true;
3561
3562                         DeclSpace temp_ds = TypeManager.LookupDeclSpace (tc.TypeBuilder.BaseType);
3563                         if (temp_ds != null)
3564                                 return IsIdentifierClsCompliant (temp_ds);
3565
3566                         MemberInfo[] ml = tc.TypeBuilder.BaseType.FindMembers (MemberTypes.Constructor, BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance, null, null);
3567                         // Skip parameter-less ctor
3568                         if (ml.Length < 2)
3569                                 return true;
3570
3571                         foreach (ConstructorInfo ci in ml) {
3572                                 object[] cls_attribute = ci.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
3573                                 if (cls_attribute.Length == 1 && (!((CLSCompliantAttribute)cls_attribute[0]).IsCompliant))
3574                                         continue;
3575
3576                                 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, TypeManager.GetArgumentTypes (ci))) {
3577                                         Report.Error_T (3006, Location, GetSignatureForError ());
3578                                         return false;
3579                                 }
3580                         }
3581                         
3582                         return true;
3583                 }
3584
3585                 protected override bool VerifyClsCompliance (DeclSpace ds)
3586                 {
3587                         if (!base.VerifyClsCompliance (ds) || !IsExposedFromAssembly (ds)) {
3588                                 return false;
3589                         }
3590                         
3591                         if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
3592                                 foreach (Type param in parameter_types) {
3593                                         if (param.IsArray) {
3594                                                 return false;
3595                                         }
3596                                 }
3597                         }
3598                         has_compliant_args = true;
3599                         return true;
3600                 }
3601
3602         }
3603
3604         /// <summary>
3605         /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
3606         /// </summary>
3607         public interface IMethodData
3608         {
3609                 CallingConventions CallingConventions { get; }
3610                 Location Location { get; }
3611                 string MethodName { get; }
3612                 Type[] ParameterTypes { get; }
3613                 Type ReturnType { get; }
3614
3615                 Attributes OptAttributes { get; }
3616                 Block Block { get; }
3617
3618                 EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
3619                 ObsoleteAttribute GetObsoleteAttribute ();
3620                 string GetSignatureForError (TypeContainer tc);
3621                 bool IsExcluded (EmitContext ec);
3622         }
3623
3624         //
3625         // Encapsulates most of the Method's state
3626         //
3627         public class MethodData {
3628
3629                 readonly IMethodData method;
3630
3631                 //
3632                 // The return type of this method
3633                 //
3634                 public readonly InternalParameters ParameterInfo;
3635
3636                 //
3637                 // Are we implementing an interface ?
3638                 //
3639                 public bool IsImplementing = false;
3640
3641                 //
3642                 // Protected data.
3643                 //
3644                 protected MemberBase member;
3645                 protected int modifiers;
3646                 protected MethodAttributes flags;
3647                 protected bool is_method;
3648
3649                 MethodBuilder builder = null;
3650                 public MethodBuilder MethodBuilder {
3651                         get {
3652                                 return builder;
3653                         }
3654                 }
3655
3656                 public MethodData (MemberBase member, InternalParameters parameters,
3657                                    int modifiers, MethodAttributes flags, bool is_method, IMethodData method)
3658                 {
3659                         this.member = member;
3660                         this.ParameterInfo = parameters;
3661                         this.modifiers = modifiers;
3662                         this.flags = flags;
3663                         this.is_method = is_method;
3664
3665                         this.method = method;
3666                 }
3667
3668                 //
3669                 // Attributes.
3670                 //
3671                 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method,
3672                                                      EmitContext ec)
3673                 {
3674                         if ((opt_attrs == null) || (opt_attrs.Attrs == null))
3675                                 return true;
3676
3677                         foreach (Attribute a in opt_attrs.Attrs) {
3678                                 Type attr_type = a.ResolveType (ec, true);
3679                                 if (attr_type == TypeManager.conditional_attribute_type) {
3680                                         if (!ApplyConditionalAttribute (a))
3681                                                 return false;
3682                                 }
3683                         }
3684
3685                         return true;
3686                 }
3687
3688                 //
3689                 // Applies the `Conditional' attribute to the method.
3690                 //
3691                 protected virtual bool ApplyConditionalAttribute (Attribute a)
3692                 {
3693                         // The Conditional attribute is only valid on methods.
3694                         if (!is_method) {
3695                                 Attribute.Error_AttributeNotValidForElement (a, method.Location);
3696                                 return false;
3697                         }
3698
3699                         string condition = a.Conditional_GetConditionName ();
3700
3701                         if (condition == null)
3702                                 return false;
3703
3704                         if (method.ReturnType != TypeManager.void_type) {
3705                                 Report.Error (578, method.Location,
3706                                               "Conditional not valid on `" + member.Name + "' " +
3707                                               "because its return type is not void");
3708                                 return false;
3709                         }
3710
3711                         if ((modifiers & Modifiers.OVERRIDE) != 0) {
3712                                 Report.Error (243, method.Location,
3713                                               "Conditional not valid on `" + member.Name + "' " +
3714                                               "because it is an override method");
3715                                 return false;
3716                         }
3717
3718                         if (member.IsExplicitImpl) {
3719                                 Report.Error (577, method.Location,
3720                                               "Conditional not valid on `" + member.Name + "' " +
3721                                               "because it is an explicit interface implementation");
3722                                 return false;
3723                         }
3724
3725                         if (IsImplementing) {
3726                                 Report.Error (623, method.Location,
3727                                               "Conditional not valid on `" + member.Name + "' " +
3728                                               "because it is an interface method");
3729                                 return false;
3730                         }
3731
3732                         return true;
3733                 }
3734
3735                 public bool Define (TypeContainer container)
3736                 {
3737                         MethodInfo implementing = null;
3738                         string prefix;
3739
3740                         EmitContext ec = method.CreateEmitContext (container, null);
3741                                 
3742                         if (method.OptAttributes != null)
3743                                 if (!ApplyAttributes (method.OptAttributes, is_method, ec))
3744                                         return false;
3745
3746                         if (member.IsExplicitImpl)
3747                                 prefix = member.InterfaceType.FullName + ".";
3748                         else
3749                                 prefix = "";
3750
3751                         string name = method.MethodName;
3752                         string method_name = prefix + name;
3753                         Type[] ParameterTypes = method.ParameterTypes;
3754
3755                         if (container.Pending != null){
3756                                 if (member is Indexer)
3757                                         implementing = container.Pending.IsInterfaceIndexer (
3758                                                 member.InterfaceType, method.ReturnType, ParameterTypes);
3759                                 else
3760                                         implementing = container.Pending.IsInterfaceMethod (
3761                                                 member.InterfaceType, name, method.ReturnType, ParameterTypes);
3762
3763                                 if (member.InterfaceType != null && implementing == null){
3764                                         Report.Error (539, method.Location, "'{0}' in explicit interface declaration is not an interface", method_name);
3765                                         return false;
3766                                 }
3767                         }
3768
3769                         //
3770                         // For implicit implementations, make sure we are public, for
3771                         // explicit implementations, make sure we are private.
3772                         //
3773                         if (implementing != null){
3774                                 //
3775                                 // Setting null inside this block will trigger a more
3776                                 // verbose error reporting for missing interface implementations
3777                                 //
3778                                 // The "candidate" function has been flagged already
3779                                 // but it wont get cleared
3780                                 //
3781                                 if (member.IsExplicitImpl){
3782                                         if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3783                                                 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
3784                                                 implementing = null;
3785                                         }
3786                                 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3787                                         if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3788                                                 //
3789                                                 // If this is an interface method implementation,
3790                                                 // check for public accessibility
3791                                                 //
3792                                                 implementing = null;
3793                                         } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3794                                                 // We may never be private.
3795                                                 implementing = null;
3796                                         } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3797                                                 //
3798                                                 // We may be protected if we're overriding something.
3799                                                 //
3800                                                 implementing = null;
3801                                         }
3802                                 } 
3803                                         
3804                                 //
3805                                 // Static is not allowed
3806                                 //
3807                                 if ((modifiers & Modifiers.STATIC) != 0){
3808                                         implementing = null;
3809                                         Modifiers.Error_InvalidModifier (method.Location, "static");
3810                                 }
3811                         }
3812                         
3813                         //
3814                         // If implementing is still valid, set flags
3815                         //
3816                         if (implementing != null){
3817                                 //
3818                                 // When implementing interface methods, set NewSlot
3819                                 // unless, we are overwriting a method.
3820                                 //
3821                                 if (implementing.DeclaringType.IsInterface){
3822                                         if ((modifiers & Modifiers.OVERRIDE) == 0)
3823                                                 flags |= MethodAttributes.NewSlot;
3824                                 }
3825                                 flags |=
3826                                         MethodAttributes.Virtual |
3827                                         MethodAttributes.HideBySig;
3828
3829                                 // Set Final unless we're virtual, abstract or already overriding a method.
3830                                 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3831                                         flags |= MethodAttributes.Final;
3832
3833                                 // Get the method name from the explicit interface.
3834                                 if (member.InterfaceType != null) {
3835                                         name = implementing.Name;
3836                                         method_name = prefix + name;
3837                                 }
3838
3839                                 IsImplementing = true;
3840                         }
3841
3842                         DefineMethodBuilder (ec, container, method_name, ParameterTypes);
3843
3844                         if (builder == null)
3845                                 return false;
3846
3847                         if ((modifiers & Modifiers.UNSAFE) != 0)
3848                                 builder.InitLocals = false;
3849
3850                         if (IsImplementing){
3851                                 //
3852                                 // clear the pending implemntation flag
3853                                 //
3854                                 if (member is Indexer) {
3855                                         container.Pending.ImplementIndexer (
3856                                                 member.InterfaceType, builder, method.ReturnType,
3857                                                 ParameterTypes, true);
3858                                 } else
3859                                         container.Pending.ImplementMethod (
3860                                                 member.InterfaceType, name, method.ReturnType,
3861                                                 ParameterTypes, member.IsExplicitImpl);
3862
3863                                 if (member.IsExplicitImpl)
3864                                         container.TypeBuilder.DefineMethodOverride (
3865                                                 builder, implementing);
3866
3867                         }
3868
3869                         if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3870                                 Report.Error (111, method.Location,
3871                                               "Class `" + container.Name +
3872                                               "' already contains a definition with the " +
3873                                               "same return value and parameter types as the " +
3874                                               "'get' method of property `" + member.Name + "'");
3875                                 return false;
3876                         }
3877
3878                         TypeManager.AddMethod (builder, method);
3879
3880                         return true;
3881                 }
3882
3883
3884                 /// <summary>
3885                 /// Create the MethodBuilder for the method 
3886                 /// </summary>
3887                 void DefineMethodBuilder (EmitContext ec, TypeContainer container, string method_name, Type[] ParameterTypes)
3888                 {
3889                         const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3890
3891                         if ((modifiers & extern_static) == extern_static) {
3892
3893                                 if (method.OptAttributes != null) {
3894                                         Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type, ec);
3895                                         if (dllimport_attribute != null) {
3896                                                 flags |= MethodAttributes.PinvokeImpl;
3897                                                 builder = dllimport_attribute.DefinePInvokeMethod (
3898                                                         ec, container.TypeBuilder, method_name, flags,
3899                                                         method.ReturnType, ParameterTypes);
3900
3901                                                 return;
3902                                         }
3903                                 }
3904
3905                                 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3906                                 // We are more strict than Microsoft and report CS0626 like error
3907                                 if (method.OptAttributes == null ||
3908                                         !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type, ec)) {
3909                                         //"Method, operator, or accessor '{0}' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation"
3910                                         Report.Error_T (626, method.Location, method.GetSignatureForError (container));
3911                                         return;
3912                                 }
3913                         }
3914
3915                         builder = container.TypeBuilder.DefineMethod (
3916                                 method_name, flags, method.CallingConventions,
3917                                 method.ReturnType, ParameterTypes);
3918                 }
3919
3920                 //
3921                 // Emits the code
3922                 // 
3923                 public void Emit (TypeContainer container, Attributable kind)
3924                 {
3925                         EmitContext ec;
3926
3927                         if ((flags & MethodAttributes.PinvokeImpl) == 0)
3928                                 ec = method.CreateEmitContext (container, builder.GetILGenerator ());
3929                         else
3930                                 ec = method.CreateEmitContext (container, null);
3931
3932                         Location loc = method.Location;
3933                         Attributes OptAttributes = method.OptAttributes;
3934
3935                         if (OptAttributes != null)
3936                                 OptAttributes.Emit (ec, kind);
3937
3938                         if (member is MethodCore)
3939                                 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
3940
3941                         SymbolWriter sw = CodeGen.SymbolWriter;
3942                         Block block = method.Block;
3943                         
3944                         //
3945                         // abstract or extern methods have no bodies
3946                         //
3947                         if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3948                                 if (block == null) {
3949                                         if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0) &&
3950                                             !Location.IsNull (loc) &&
3951                                             (method.Location.SymbolDocument != null)) {
3952                                                 sw.OpenMethod (container, MethodBuilder, loc, loc);
3953                                                 sw.CloseMethod ();
3954                                         }
3955
3956                                         return;
3957                                 }
3958
3959                                 //
3960                                 // abstract or extern methods have no bodies.
3961                                 //
3962                                 if ((modifiers & Modifiers.ABSTRACT) != 0)
3963                                         Report.Error (
3964                                                 500, method.Location, "Abstract method `" +
3965                                                 TypeManager.CSharpSignature (builder) +
3966                                                 "' can not have a body");
3967
3968                                 if ((modifiers & Modifiers.EXTERN) != 0)
3969                                         Report.Error (
3970                                                 179, method.Location, "External method `" +
3971                                                 TypeManager.CSharpSignature (builder) +
3972                                                 "' can not have a body");
3973
3974                                 return;
3975                         }
3976
3977                         //
3978                         // Methods must have a body unless they're extern or abstract
3979                         //
3980                         if (block == null) {
3981                                 Report.Error (
3982                                         501, method.Location, "Method `" +
3983                                         TypeManager.CSharpSignature (builder) +
3984                                         "' must declare a body since it is not marked " +
3985                                         "abstract or extern");
3986                                 return;
3987                         }
3988
3989                         //
3990                         // Handle destructors specially
3991                         //
3992                         // FIXME: This code generates buggy code
3993                         //
3994                         if ((sw != null) && !Location.IsNull (loc) &&
3995                             !Location.IsNull (block.EndLocation) &&
3996                             (loc.SymbolDocument != null)) {
3997                                 sw.OpenMethod (container, MethodBuilder, loc, block.EndLocation);
3998
3999                                 if (member is Destructor)
4000                                         EmitDestructor (ec, block);
4001                                 else
4002                                         ec.EmitTopBlock (block, ParameterInfo, loc);
4003
4004                                 sw.CloseMethod ();
4005                         } else {
4006                                 if (member is Destructor)
4007                                         EmitDestructor (ec, block);
4008                                 else
4009                                         ec.EmitTopBlock (block, ParameterInfo, loc);
4010                         }
4011                 }
4012
4013                 void EmitDestructor (EmitContext ec, Block block)
4014                 {
4015                         ILGenerator ig = ec.ig;
4016                         
4017                         Label finish = ig.DefineLabel ();
4018
4019                         block.SetDestructor ();
4020                         
4021                         ig.BeginExceptionBlock ();
4022                         ec.ReturnLabel = finish;
4023                         ec.HasReturnLabel = true;
4024                         ec.EmitTopBlock (block, null, method.Location);
4025                         
4026                         // ig.MarkLabel (finish);
4027                         ig.BeginFinallyBlock ();
4028                         
4029                         if (ec.ContainerType.BaseType != null) {
4030                                 Expression member_lookup = Expression.MemberLookup (
4031                                         ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
4032                                         "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
4033
4034                                 if (member_lookup != null){
4035                                         MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
4036                                 
4037                                         ig.Emit (OpCodes.Ldarg_0);
4038                                         ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
4039                                 }
4040                         }
4041                         
4042                         ig.EndExceptionBlock ();
4043                         //ig.MarkLabel (ec.ReturnLabel);
4044                         ig.Emit (OpCodes.Ret);
4045                 }
4046         }
4047
4048         public class Destructor : Method {
4049
4050                 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
4051                                    Parameters parameters, Attributes attrs, Location l)
4052                         : base (ds, return_type, mod, false, name, parameters, attrs, l)
4053                 { }
4054
4055         }
4056         
4057         abstract public class MemberBase : MemberCore {
4058                 public Expression Type;
4059
4060                 public MethodAttributes flags;
4061                         
4062                 protected readonly int explicit_mod_flags;
4063
4064                 //
4065                 // The "short" name of this property / indexer / event.  This is the
4066                 // name without the explicit interface.
4067                 //
4068                 public string ShortName;
4069
4070                 //
4071                 // The type of this property / indexer / event
4072                 //
4073                 public Type MemberType;
4074
4075                 //
4076                 // If true, this is an explicit interface implementation
4077                 //
4078                 public bool IsExplicitImpl = false;
4079
4080                 //
4081                 // The name of the interface we are explicitly implementing
4082                 //
4083                 public string ExplicitInterfaceName = null;
4084
4085                 //
4086                 // Whether this is an interface member.
4087                 //
4088                 public bool IsInterface;
4089
4090                 //
4091                 // If true, the interface type we are explicitly implementing
4092                 //
4093                 public Type InterfaceType = null;
4094
4095                 //
4096                 // The method we're overriding if this is an override method.
4097                 //
4098                 protected MethodInfo parent_method = null;
4099                 public MethodInfo ParentMethod {
4100                         get {
4101                                 return parent_method;
4102                         }
4103                 }
4104
4105                 //
4106                 // The constructor is only exposed to our children
4107                 //
4108                 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod, string name,
4109                                       Attributes attrs, Location loc)
4110                         : base (name, attrs, loc)
4111                 {
4112                         explicit_mod_flags = mod;
4113                         Type = type;
4114                         ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
4115                 }
4116
4117                 protected virtual bool CheckBase (TypeContainer container)
4118                 {
4119                         if ((container is Struct) || (RootContext.WarningLevel > 3)){
4120                                 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
4121                                         if (container is Struct){
4122                                                 Report.Error (666, Location, "Protected member in struct declaration");
4123                                                 return false;
4124                                         } else
4125                                                 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
4126                                 }
4127                         }
4128                         return true;
4129                 }
4130
4131                 protected void WarningNotHiding (TypeContainer parent)
4132                 {
4133                         Report.Warning (
4134                                 109, Location,
4135                                 "The member " + parent.MakeName (Name) + " does not hide an " +
4136                                 "inherited member.  The keyword new is not required");
4137                                                            
4138                 }
4139
4140                 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
4141                                                         string name)
4142                 {
4143                         //
4144                         // FIXME: report the old/new permissions?
4145                         //
4146                         Report.Error (
4147                                 507, Location, parent.MakeName (Name) +
4148                                 ": can't change the access modifiers when overriding inherited " +
4149                                 "member `" + name + "'");
4150                 }
4151                 
4152                 //
4153                 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
4154                 // that have been defined.
4155                 //
4156                 // `name' is the user visible name for reporting errors (this is used to
4157                 // provide the right name regarding method names and properties)
4158                 //
4159                 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
4160                                                        MethodInfo mb, string name)
4161                 {
4162                         bool ok = true;
4163                         
4164                         if ((ModFlags & Modifiers.OVERRIDE) != 0){
4165                                 if (!(mb.IsAbstract || mb.IsVirtual)){
4166                                         Report.Error (
4167                                                 506, Location, parent.MakeName (Name) +
4168                                                 ": cannot override inherited member `" +
4169                                                 name + "' because it is not " +
4170                                                 "virtual, abstract or override");
4171                                         ok = false;
4172                                 }
4173                                 
4174                                 // Now we check that the overriden method is not final
4175                                 
4176                                 if (mb.IsFinal) {
4177                                         // This happens when implementing interface methods.
4178                                         if (mb.IsHideBySig && mb.IsVirtual) {
4179                                                 Report.Error (
4180                                                         506, Location, parent.MakeName (Name) +
4181                                                         ": cannot override inherited member `" +
4182                                                         name + "' because it is not " +
4183                                                         "virtual, abstract or override");
4184                                         } else
4185                                                 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
4186                                                               "override inherited member `" + name +
4187                                                               "' because it is sealed.");
4188                                         ok = false;
4189                                 }
4190                                 //
4191                                 // Check that the permissions are not being changed
4192                                 //
4193                                 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
4194                                 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
4195
4196                                 //
4197                                 // special case for "protected internal"
4198                                 //
4199
4200                                 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4201                                         //
4202                                         // when overriding protected internal, the method can be declared
4203                                         // protected internal only within the same assembly
4204                                         //
4205
4206                                         if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4207                                                 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
4208                                                         //
4209                                                         // assemblies differ - report an error
4210                                                         //
4211                                                         
4212                                                         Error_CannotChangeAccessModifiers (parent, mb, name);
4213                                                     ok = false;
4214                                                 } else if (thisp != parentp) {
4215                                                         //
4216                                                         // same assembly, but other attributes differ - report an error
4217                                                         //
4218                                                         
4219                                                         Error_CannotChangeAccessModifiers (parent, mb, name);
4220                                                         ok = false;
4221                                                 };
4222                                         } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
4223                                                 //
4224                                                 // if it's not "protected internal", it must be "protected"
4225                                                 //
4226
4227                                                 Error_CannotChangeAccessModifiers (parent, mb, name);
4228                                                 ok = false;
4229                                         } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
4230                                                 //
4231                                                 // protected within the same assembly - an error
4232                                                 //
4233                                                 Error_CannotChangeAccessModifiers (parent, mb, name);
4234                                                 ok = false;
4235                                         } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) != 
4236                                                    (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
4237                                                 //
4238                                                 // protected ok, but other attributes differ - report an error
4239                                                 //
4240                                                 Error_CannotChangeAccessModifiers (parent, mb, name);
4241                                                 ok = false;
4242                                         }
4243                                 } else {
4244                                         if (thisp != parentp){
4245                                                 Error_CannotChangeAccessModifiers (parent, mb, name);
4246                                                 ok = false;
4247                                         }
4248                                 }
4249                         }
4250
4251                         if (mb.IsVirtual || mb.IsAbstract){
4252                                 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4253                                         if (Name != "Finalize"){
4254                                                 Report.Warning (
4255                                                         114, 2, Location, parent.MakeName (Name) + 
4256                                                         " hides inherited member `" + name +
4257                                                         "'.  To make the current member override that " +
4258                                                         "implementation, add the override keyword, " +
4259                                                         "otherwise use the new keyword");
4260                                                 ModFlags |= Modifiers.NEW;
4261                                         }
4262                                 }
4263                         } else {
4264                                 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4265                                         if (Name != "Finalize"){
4266                                                 Report.Warning (
4267                                                         108, 1, Location, "The keyword new is required on " +
4268                                                         parent.MakeName (Name) + " because it hides " +
4269                                                         "inherited member `" + name + "'");
4270                                                 ModFlags |= Modifiers.NEW;
4271                                         }
4272                                 }
4273                         }
4274
4275                         return ok;
4276                 }
4277
4278                 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
4279                 {
4280                         bool error = false;
4281
4282                         foreach (Type partype in parameters){
4283                                 if (partype == TypeManager.void_type) {
4284                                         Report.Error (
4285                                                 1547, Location, "Keyword 'void' cannot " +
4286                                                 "be used in this context");
4287                                         return false;
4288                                 }
4289
4290                                 if (partype.IsPointer){
4291                                         if (!UnsafeOK (ds))
4292                                                 error = true;
4293                                         if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
4294                                                 error = true;
4295                                 }
4296
4297                                 if (ds.AsAccessible (partype, ModFlags))
4298                                         continue;
4299
4300                                 if (this is Indexer)
4301                                         Report.Error (55, Location,
4302                                                       "Inconsistent accessibility: parameter type `" +
4303                                                       TypeManager.CSharpName (partype) + "' is less " +
4304                                                       "accessible than indexer `" + Name + "'");
4305                                 else if ((this is Method) && ((Method) this).IsOperator)
4306                                         Report.Error (57, Location,
4307                                                       "Inconsistent accessibility: parameter type `" +
4308                                                       TypeManager.CSharpName (partype) + "' is less " +
4309                                                       "accessible than operator `" + Name + "'");
4310                                 else
4311                                         Report.Error (51, Location,
4312                                                       "Inconsistent accessibility: parameter type `" +
4313                                                       TypeManager.CSharpName (partype) + "' is less " +
4314                                                       "accessible than method `" + Name + "'");
4315                                 error = true;
4316                         }
4317
4318                         return !error;
4319                 }
4320
4321                 protected virtual bool DoDefine (TypeContainer container)
4322                 {
4323                         if (Name == null)
4324                                 Name = "this";
4325
4326                         if (IsInterface) {
4327                                 ModFlags = Modifiers.PUBLIC |
4328                                         Modifiers.ABSTRACT |
4329                                         Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE);
4330
4331                                 flags = MethodAttributes.Public |
4332                                         MethodAttributes.Abstract |
4333                                         MethodAttributes.HideBySig |
4334                                         MethodAttributes.NewSlot |
4335                                         MethodAttributes.Virtual;
4336                         } else {
4337                                 if (!container.MethodModifiersValid (ModFlags, Name, Location))
4338                                         return false;
4339
4340                                 flags = Modifiers.MethodAttr (ModFlags);
4341                         }
4342
4343                         // Lookup Type, verify validity
4344                         MemberType = container.ResolveType (Type, false, Location);
4345                         if (MemberType == null)
4346                                 return false;
4347
4348                         if ((container.ModFlags & Modifiers.SEALED) != 0){
4349                                 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
4350                                         Report.Error (549, Location, "Virtual method can not be contained in sealed class");
4351                                         return false;
4352                                 }
4353                         }
4354                         
4355                         // verify accessibility
4356                         if (!container.AsAccessible (MemberType, ModFlags)) {
4357                                 if (this is Property)
4358                                         Report.Error (53, Location,
4359                                                       "Inconsistent accessibility: property type `" +
4360                                                       TypeManager.CSharpName (MemberType) + "' is less " +
4361                                                       "accessible than property `" + Name + "'");
4362                                 else if (this is Indexer)
4363                                         Report.Error (54, Location,
4364                                                       "Inconsistent accessibility: indexer return type `" +
4365                                                       TypeManager.CSharpName (MemberType) + "' is less " +
4366                                                       "accessible than indexer `" + Name + "'");
4367                                 else if (this is Method) {
4368                                         if (((Method) this).IsOperator)
4369                                                 Report.Error (56, Location,
4370                                                               "Inconsistent accessibility: return type `" +
4371                                                               TypeManager.CSharpName (MemberType) + "' is less " +
4372                                                               "accessible than operator `" + Name + "'");
4373                                         else
4374                                                 Report.Error (50, Location,
4375                                                               "Inconsistent accessibility: return type `" +
4376                                                               TypeManager.CSharpName (MemberType) + "' is less " +
4377                                                               "accessible than method `" + Name + "'");
4378                                 } else
4379                                         Report.Error (52, Location,
4380                                                       "Inconsistent accessibility: field type `" +
4381                                                       TypeManager.CSharpName (MemberType) + "' is less " +
4382                                                       "accessible than field `" + Name + "'");
4383                                 return false;
4384                         }
4385
4386                         if (MemberType.IsPointer && !UnsafeOK (container))
4387                                 return false;
4388                         
4389                         //
4390                         // Check for explicit interface implementation
4391                         //
4392                         if ((ExplicitInterfaceName == null) && (Name.IndexOf ('.') != -1)){
4393                                 int pos = Name.LastIndexOf ('.');
4394
4395                                 ExplicitInterfaceName = Name.Substring (0, pos);
4396                                 ShortName = Name.Substring (pos + 1);
4397                         } else
4398                                 ShortName = Name;
4399
4400                         if (ExplicitInterfaceName != null) {
4401                                 InterfaceType  = container.FindType (
4402                                         Location, ExplicitInterfaceName);
4403                                 if (InterfaceType == null)
4404                                         return false;
4405
4406                                 if (InterfaceType.IsClass) {
4407                                         Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
4408                                         return false;
4409                                 }
4410
4411                                 // Compute the full name that we need to export.
4412                                 Name = InterfaceType.FullName + "." + ShortName;
4413                                 
4414                                 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
4415                                         return false;
4416                                 
4417                                 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4418                                 
4419                                 IsExplicitImpl = true;
4420                         } else
4421                                 IsExplicitImpl = false;
4422
4423                         return true;
4424                 }
4425
4426                 /// <summary>
4427                 /// Use this method when MethodBuilder is null
4428                 /// </summary>
4429                 public virtual string GetSignatureForError (TypeContainer tc)
4430                 {
4431                         return String.Concat (tc.Name, '.', Name);
4432                 }
4433
4434                 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4435                 {
4436                         return IsIdentifierAndParamClsCompliant (ds, Name, null, null);
4437                 }
4438
4439                 protected override bool VerifyClsCompliance(DeclSpace ds)
4440                 {
4441                         if (base.VerifyClsCompliance (ds)) {
4442                                 return true;
4443                         }
4444
4445                         if (IsInterface && HasClsCompliantAttribute && ds.IsClsCompliaceRequired (ds)) {
4446                                 Report.Error_T (3010, Location, GetSignatureForError ());
4447                         }
4448                         return false;
4449                 }
4450
4451                 protected override void VerifyObsoleteAttribute()
4452                 {
4453                         CheckUsageOfObsoleteAttribute (MemberType);
4454                 }
4455         }
4456
4457         //
4458         // Fields and Events both generate FieldBuilders, we use this to share 
4459         // their common bits.  This is also used to flag usage of the field
4460         //
4461         abstract public class FieldBase : MemberBase {
4462                 public FieldBuilder  FieldBuilder;
4463                 public Status status;
4464
4465                 [Flags]
4466                 public enum Status : byte { ASSIGNED = 1, USED = 2 }
4467
4468                 static string[] attribute_targets = new string [] { "field" };
4469
4470                 //
4471                 // The constructor is only exposed to our children
4472                 //
4473                 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
4474                                      object init, Attributes attrs, Location loc)
4475                         : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
4476                 {
4477                         this.init = init;
4478                 }
4479
4480                 public override AttributeTargets AttributeTargets {
4481                         get {
4482                                 return AttributeTargets.Field;
4483                         }
4484                 }
4485
4486                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4487                 {
4488                         if (a.Type == TypeManager.marshal_as_attr_type) {
4489                                 UnmanagedMarshal marshal = a.GetMarshal ();
4490                                 if (marshal != null) {
4491                                         FieldBuilder.SetMarshal (marshal);
4492                                         return;
4493                                 }
4494                                 Report.Warning_T (-24, a.Location);
4495                                 return;
4496                         }
4497
4498                         
4499                         FieldBuilder.SetCustomAttribute (cb);
4500                 }
4501
4502                 //
4503                 // Whether this field has an initializer.
4504                 //
4505                 public bool HasInitializer {
4506                         get {
4507                                 return init != null;
4508                         }
4509                 }
4510
4511                 protected readonly Object init;
4512                 // Private.
4513                 Expression init_expr;
4514                 bool init_expr_initialized = false;
4515
4516                 //
4517                 // Resolves and returns the field initializer.
4518                 //
4519                 public Expression GetInitializerExpression (EmitContext ec)
4520                 {
4521                         if (init_expr_initialized)
4522                                 return init_expr;
4523
4524                         Expression e;
4525                         if (init is Expression)
4526                                 e = (Expression) init;
4527                         else
4528                                 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
4529
4530                         ec.IsFieldInitializer = true;
4531                         e = e.DoResolve (ec);
4532                         ec.IsFieldInitializer = false;
4533
4534                         init_expr = e;
4535                         init_expr_initialized = true;
4536
4537                         return init_expr;
4538                 }
4539
4540                 protected override bool DoDefine (TypeContainer container)
4541                 {
4542                         if (!base.DoDefine (container))
4543                                 return false;
4544
4545                         if (MemberType == TypeManager.void_type) {
4546                                 Report.Error (1547, Location,
4547                                               "Keyword 'void' cannot be used in this context");
4548                                 return false;
4549                         }
4550
4551                         return true;
4552                 }
4553
4554                 public override string GetSignatureForError ()
4555                 {
4556                         return TypeManager.GetFullNameSignature (FieldBuilder);
4557                 }
4558
4559                 protected override string[] ValidAttributeTargets {
4560                         get {
4561                                 return attribute_targets;
4562                         }
4563                 }
4564
4565                 protected override bool VerifyClsCompliance (DeclSpace ds)
4566                 {
4567                         if (!base.VerifyClsCompliance (ds))
4568                                 return false;
4569
4570                         if (FieldBuilder == null) {
4571                                 return true;
4572                         }
4573
4574                         if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
4575                                 Report.Error_T (3003, Location, GetSignatureForError ());
4576                         }
4577                         return true;
4578                 }
4579
4580
4581                 public void SetAssigned ()
4582                 {
4583                         status |= Status.ASSIGNED;
4584                 }
4585         }
4586
4587         //
4588         // The Field class is used to represents class/struct fields during parsing.
4589         //
4590         public class Field : FieldBase {
4591                 // <summary>
4592                 //   Modifiers allowed in a class declaration
4593                 // </summary>
4594                 const int AllowedModifiers =
4595                         Modifiers.NEW |
4596                         Modifiers.PUBLIC |
4597                         Modifiers.PROTECTED |
4598                         Modifiers.INTERNAL |
4599                         Modifiers.PRIVATE |
4600                         Modifiers.STATIC |
4601                         Modifiers.VOLATILE |
4602                         Modifiers.UNSAFE |
4603                         Modifiers.READONLY;
4604
4605                 public Field (Expression type, int mod, string name, Object expr_or_array_init,
4606                               Attributes attrs, Location loc)
4607                         : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
4608                 {
4609                 }
4610
4611                 public override bool Define (TypeContainer container)
4612                 {
4613                         MemberType = container.ResolveType (Type, false, Location);
4614                         
4615                         if (MemberType == null)
4616                                 return false;
4617
4618                         CheckBase (container);
4619                         
4620                         if (!container.AsAccessible (MemberType, ModFlags)) {
4621                                 Report.Error (52, Location,
4622                                               "Inconsistent accessibility: field type `" +
4623                                               TypeManager.CSharpName (MemberType) + "' is less " +
4624                                               "accessible than field `" + Name + "'");
4625                                 return false;
4626                         }
4627
4628                         if (MemberType.IsPointer && !UnsafeOK (container))
4629                                 return false;
4630                         
4631                         if (RootContext.WarningLevel > 1){
4632                                 Type ptype = container.TypeBuilder.BaseType;
4633
4634                                 // ptype is only null for System.Object while compiling corlib.
4635                                 if (ptype != null){
4636                                         TypeContainer.FindMembers (
4637                                                 ptype, MemberTypes.Method,
4638                                                 BindingFlags.Public |
4639                                                 BindingFlags.Static | BindingFlags.Instance,
4640                                                 System.Type.FilterName, Name);
4641                                 }
4642                         }
4643
4644                         if ((ModFlags & Modifiers.VOLATILE) != 0){
4645                                 if (!MemberType.IsClass){
4646                                         Type vt = MemberType;
4647                                         
4648                                         if (TypeManager.IsEnumType (vt))
4649                                                 vt = TypeManager.EnumToUnderlying (MemberType);
4650
4651                                         if (!((vt == TypeManager.bool_type) ||
4652                                               (vt == TypeManager.sbyte_type) ||
4653                                               (vt == TypeManager.byte_type) ||
4654                                               (vt == TypeManager.short_type) ||
4655                                               (vt == TypeManager.ushort_type) ||
4656                                               (vt == TypeManager.int32_type) ||
4657                                               (vt == TypeManager.uint32_type) ||    
4658                                               (vt == TypeManager.char_type) ||
4659                                               (vt == TypeManager.float_type) ||
4660                                               (!vt.IsValueType))){
4661                                                 Report.Error (
4662                                                         677, Location, container.MakeName (Name) +
4663                                                         " A volatile field can not be of type `" +
4664                                                         TypeManager.CSharpName (vt) + "'");
4665                                                 return false;
4666                                         }
4667                                 }
4668
4669                                 if ((ModFlags & Modifiers.READONLY) != 0){
4670                                         Report.Error (
4671                                                       678, Location,
4672                                                       "A field can not be both volatile and readonly");
4673                                         return false;
4674                                 }
4675                         }
4676
4677                         FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4678
4679                         if (container is Struct && 
4680                             ((fa & FieldAttributes.Static) == 0) &&
4681                             MemberType == container.TypeBuilder &&
4682                             !TypeManager.IsBuiltinType (MemberType)){
4683                                 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name + 
4684                                               "' causes a cycle in the structure layout");
4685                                 return false;
4686                         }
4687
4688                         try {
4689                                 FieldBuilder = container.TypeBuilder.DefineField (
4690                                         Name, MemberType, Modifiers.FieldAttr (ModFlags));
4691
4692                                 TypeManager.RegisterFieldBase (FieldBuilder, this);
4693                         }
4694                         catch (ArgumentException) {
4695                                 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
4696                                 return false;
4697                         }
4698
4699                         return true;
4700                 }
4701
4702                 public override void Emit (TypeContainer tc)
4703                 {
4704                         if (OptAttributes != null) {
4705                                 EmitContext ec = new EmitContext (tc, Location, null, FieldBuilder.FieldType, ModFlags);
4706                                 OptAttributes.Emit (ec, this);
4707                         }
4708
4709                         base.Emit (tc);
4710                 }
4711         }
4712
4713         //
4714         // `set' and `get' accessors are represented with an Accessor.
4715         // 
4716         public class Accessor {
4717                 //
4718                 // Null if the accessor is empty, or a Block if not
4719                 //
4720                 public Block Block;
4721                 public Attributes Attributes;
4722                 
4723                 public Accessor (Block b, Attributes attrs)
4724                 {
4725                         Block = b;
4726                         Attributes = attrs;
4727                 }
4728         }
4729
4730         //
4731         // Properties and Indexers both generate PropertyBuilders, we use this to share 
4732         // their common bits.
4733         //
4734         abstract public class PropertyBase : MethodCore {
4735
4736                 public class GetMethod: PropertyMethod
4737                 {
4738                         static string[] attribute_targets = new string [] { "method", "return" };
4739
4740                         public GetMethod (MethodCore method, Accessor accessor):
4741                                 base (method, accessor)
4742                         {
4743                         }
4744
4745                         public override MethodBuilder Define(TypeContainer container)
4746                         {
4747                                 method_data = new MethodData (method, method.ParameterInfo, method.ModFlags, method.flags, false, this);
4748
4749                                 if (!method_data.Define (container))
4750                                         return null;
4751
4752                                 return method_data.MethodBuilder;
4753                         }
4754
4755                         public override string GetSignatureForError (TypeContainer tc)
4756                         {
4757                                 return String.Concat (base.GetSignatureForError (tc), ".get");
4758                         }
4759
4760                         public override string MethodName 
4761                         {
4762                                 get {
4763                                         return "get_" + method.ShortName;
4764                                 }
4765                         }
4766
4767                         public override Type ReturnType {
4768                                 get {
4769                                         return method.MemberType;
4770                                 }
4771                         }
4772
4773                         protected override string[] ValidAttributeTargets {
4774                                 get {
4775                                         return attribute_targets;
4776                                 }
4777                         }
4778                 }
4779
4780                 public class SetMethod: PropertyMethod {
4781
4782                         static string[] attribute_targets = new string [] { "method", "param", "return" };
4783                         ImplicitParameter param_attr;
4784
4785                         public SetMethod (MethodCore method, Accessor accessor):
4786                                 base (method, accessor)
4787                         {
4788                         }
4789
4790                         public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4791                         {
4792                                 if (a.Target == "param") {
4793                                         if (param_attr == null)
4794                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder);
4795
4796                                         param_attr.ApplyAttributeBuilder (a, cb);
4797                                         return;
4798                                 }
4799
4800                                 base.ApplyAttributeBuilder (a, cb);
4801                         }
4802
4803                         protected virtual InternalParameters GetParameterInfo (TypeContainer container)
4804                         {
4805                                 Parameter [] parms = new Parameter [1];
4806                                 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null);
4807                                 return new InternalParameters (
4808                                         container, new Parameters (parms, null, method.Location));
4809                         }
4810
4811                         public override MethodBuilder Define(TypeContainer container)
4812                         {
4813                                 method_data = new MethodData (method, GetParameterInfo (container), method.ModFlags, method.flags, false, this);
4814
4815                                 if (!method_data.Define (container))
4816                                         return null;
4817
4818                                 return method_data.MethodBuilder;
4819                         }
4820
4821                         public override string GetSignatureForError (TypeContainer tc)
4822                         {
4823                                 return String.Concat (base.GetSignatureForError (tc), ".set");
4824                         }
4825
4826                         public override string MethodName {
4827                                 get {
4828                                         return "set_" + method.ShortName;
4829                                 }
4830                         }
4831
4832                         public override Type[] ParameterTypes {
4833                                 get {
4834                                         return new Type[] { method.MemberType };
4835                                 }
4836                         }
4837
4838                         public override Type ReturnType {
4839                                 get {
4840                                         return TypeManager.void_type;
4841                                 }
4842                         }
4843
4844                         protected override string[] ValidAttributeTargets {
4845                                 get {
4846                                         return attribute_targets;
4847                                 }
4848                         }
4849                 }
4850
4851
4852                 static string[] attribute_targets = new string [] { "property" };
4853
4854                 public abstract class PropertyMethod: Attributable, IMethodData 
4855                 {
4856                         protected readonly MethodCore method;
4857                         protected MethodData method_data;
4858                         Block block;
4859
4860                         ReturnParameter return_attributes;
4861
4862                         public PropertyMethod (MethodCore method, Accessor accessor):
4863                                 base (accessor.Attributes)
4864                         {
4865                                 this.method = method;
4866                                 this.block = accessor.Block;
4867                         }
4868
4869                         public override AttributeTargets AttributeTargets {
4870                                 get {
4871                                         return AttributeTargets.Method | AttributeTargets.ReturnValue;
4872                                 }
4873                         }
4874
4875                         public override bool IsClsCompliaceRequired(DeclSpace ds)
4876                         {
4877                                 return method.IsClsCompliaceRequired (ds);
4878                         }
4879
4880                         public InternalParameters ParameterInfo 
4881                         {
4882                                 get {
4883                                         return method_data.ParameterInfo;
4884                                 }
4885                         }
4886
4887                         #region IMethodData Members
4888
4889                         public Block Block {
4890                                 get {
4891                                         return block;
4892                                 }
4893                         }
4894
4895                         public CallingConventions CallingConventions {
4896                                 get {
4897                                         return CallingConventions.Standard;
4898                                 }
4899                         }
4900
4901                         public abstract MethodBuilder Define (TypeContainer container);
4902
4903                         public void Emit (TypeContainer container)
4904                         {
4905                                 method_data.Emit (container, this);
4906                                 block = null;
4907                         }
4908
4909                         public virtual string GetSignatureForError (TypeContainer tc)
4910                         {
4911                                 return String.Concat (tc.Name, '.', method.Name);
4912                         }
4913
4914                         public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4915                         {
4916                                 if (a.Target == "return") {
4917                                         if (return_attributes == null)
4918                                                 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
4919
4920                                         return_attributes.ApplyAttributeBuilder (a, cb);
4921                                         return;
4922                                 }
4923
4924                                 method_data.MethodBuilder.SetCustomAttribute (cb);
4925                         }
4926
4927                         public virtual Type[] ParameterTypes {
4928                                 get {
4929                                         return TypeManager.NoTypes;
4930                                 }
4931                         }
4932
4933                         public abstract Type ReturnType { get; }
4934
4935                         public Location Location {
4936                                 get {
4937                                         return method.Location;
4938                                 }
4939                         }
4940
4941                         public abstract string MethodName { get; }
4942
4943                         public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
4944                         {
4945                                 return new EmitContext (tc, method.ds, method.Location, ig, ReturnType, method.ModFlags, false);
4946                         }
4947
4948                         public ObsoleteAttribute GetObsoleteAttribute ()
4949                         {
4950                                 return method.GetObsoleteAttribute (method.ds);
4951                         }
4952
4953                         public bool IsExcluded (EmitContext ec)
4954                         {
4955                                 return false;
4956                         }
4957
4958                         #endregion
4959                 }
4960
4961
4962                 public PropertyMethod Get, Set;
4963                 public PropertyBuilder PropertyBuilder;
4964                 public MethodBuilder GetBuilder, SetBuilder;
4965
4966                 protected EmitContext ec;
4967
4968                 public PropertyBase (DeclSpace ds, Expression type, int mod_flags,
4969                                      int allowed_mod, bool is_iface, string name,
4970                                      Parameters parameters, Attributes attrs,
4971                                      Location loc)
4972                         : base (ds, type, mod_flags, allowed_mod, is_iface, name,
4973                                 attrs, parameters, loc)
4974                 {
4975                 }
4976
4977                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4978                 {
4979                         PropertyBuilder.SetCustomAttribute (cb);
4980                 }
4981
4982                 public override AttributeTargets AttributeTargets {
4983                         get {
4984                                 return AttributeTargets.Property;
4985                         }
4986                 }
4987
4988                 protected override bool DoDefine (TypeContainer container)
4989                 {
4990                         if (!base.DoDefine (container))
4991                                 return false;
4992
4993                         ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4994
4995                         return true;
4996                 }
4997
4998                 public override string GetSignatureForError()
4999                 {
5000                         return TypeManager.CSharpSignature (PropertyBuilder, false);
5001                 }
5002
5003                 protected virtual string RealMethodName {
5004                         get {
5005                                 return Name;
5006                         }
5007                 }
5008
5009                 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
5010                 {
5011                         if (!IsIdentifierAndParamClsCompliant (ds, RealMethodName, null, null))
5012                                 return false;
5013
5014                         if (Get != null && !IsIdentifierAndParamClsCompliant (ds, "get_" + RealMethodName, null, null))
5015                                 return false;
5016
5017                         if (Set != null && !IsIdentifierAndParamClsCompliant (ds, "set_" + RealMethodName, null, null))
5018                                 return false;
5019
5020                         return true;
5021                 }
5022
5023
5024                 //
5025                 // Checks our base implementation if any
5026                 //
5027                 protected override bool CheckBase (TypeContainer container)
5028                 {
5029                         base.CheckBase (container);
5030                         
5031                         // Check whether arguments were correct.
5032                         if (!DoDefineParameters ())
5033                                 return false;
5034
5035                         if (IsExplicitImpl)
5036                                 return true;
5037
5038                         //
5039                         // Check in our class for dups
5040                         //
5041                         ArrayList ar = container.Properties;
5042                         if (ar != null) {
5043                                 int arLen = ar.Count;
5044                                         
5045                                 for (int i = 0; i < arLen; i++) {
5046                                         Property m = (Property) ar [i];
5047                                         if (IsDuplicateImplementation (container, m))
5048                                                 return false;
5049                                 }
5050                         }
5051
5052                         if (IsInterface)
5053                                 return true;
5054
5055                         string report_name;
5056                         MethodSignature ms, base_ms;
5057                         if (this is Indexer) {
5058                                 string name, base_name;
5059
5060                                 report_name = "this";
5061                                 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
5062                                 ms = new MethodSignature (name, null, ParameterTypes);
5063                                 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
5064                                 base_ms = new MethodSignature (base_name, null, ParameterTypes);
5065                         } else {
5066                                 report_name = Name;
5067                                 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
5068                         }
5069
5070                         //
5071                         // Verify if the parent has a type with the same name, and then
5072                         // check whether we have to create a new slot for it or not.
5073                         //
5074                         Type ptype = container.TypeBuilder.BaseType;
5075
5076                         // ptype is only null for System.Object while compiling corlib.
5077                         if (ptype == null) {
5078                                 if ((ModFlags & Modifiers.NEW) != 0)
5079                                         WarningNotHiding (container);
5080
5081                                 return true;
5082                         }
5083
5084                         MemberInfo parent_member = null;
5085                         
5086                         //
5087                         // Explicit implementations do not have `parent' methods, however,
5088                         // the member cache stores them there. Without this check, we get
5089                         // an incorrect warning in corlib.
5090                         //
5091                         if (! IsExplicitImpl) {
5092                                 parent_member = ((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
5093                                         container.TypeBuilder, Name, ParameterTypes, true);
5094                         }
5095
5096                         if (parent_member is PropertyInfo) {
5097                                 PropertyInfo parent_property = (PropertyInfo)parent_member;
5098
5099                                 string name = parent_property.DeclaringType.Name + "." +
5100                                         parent_property.Name;
5101
5102                                 MethodInfo get, set, parent_method;
5103                                 get = parent_property.GetGetMethod (true);
5104                                 set = parent_property.GetSetMethod (true);
5105
5106                                 if (get != null)
5107                                         parent_method = get;
5108                                 else if (set != null)
5109                                         parent_method = set;
5110                                 else
5111                                         throw new Exception ("Internal error!");
5112
5113                                 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
5114                                         return false;
5115
5116                                 if ((ModFlags & Modifiers.NEW) == 0) {
5117                                         Type parent_type = TypeManager.TypeToCoreType (
5118                                                 parent_property.PropertyType);
5119
5120                                         if (parent_type != MemberType) {
5121                                                 Report.Error (
5122                                                         508, Location, container.MakeName (Name) + ": cannot " +
5123                                                         "change return type when overriding " +
5124                                                         "inherited member " + name);
5125                                                 return false;
5126                                         }
5127                                 }
5128                         } else if (parent_member == null){
5129                                 if ((ModFlags & Modifiers.NEW) != 0)
5130                                         WarningNotHiding (container);
5131
5132                                 if ((ModFlags & Modifiers.OVERRIDE) != 0){
5133                                         if (this is Indexer)
5134                                                 Report.Error (115, Location,
5135                                                               container.MakeName (Name) +
5136                                                               " no suitable indexers found to override");
5137                                         else
5138                                                 Report.Error (115, Location,
5139                                                               container.MakeName (Name) +
5140                                                               " no suitable properties found to override");
5141                                         return false;
5142                                 }
5143                         }
5144                         return true;
5145                 }
5146
5147                 public override void Emit (TypeContainer tc)
5148                 {
5149                         //
5150                         // The PropertyBuilder can be null for explicit implementations, in that
5151                         // case, we do not actually emit the ".property", so there is nowhere to
5152                         // put the attribute
5153                         //
5154                         if (PropertyBuilder != null && OptAttributes != null)
5155                                 OptAttributes.Emit (ec, this);
5156
5157                         if (Get != null)
5158                                 Get.Emit (tc);
5159
5160                         if (Set != null)
5161                                 Set.Emit (tc);
5162
5163                         base.Emit (tc);
5164                 }
5165
5166                 protected override string[] ValidAttributeTargets {
5167                         get {
5168                                 return attribute_targets;
5169                         }
5170                 }
5171         }
5172                         
5173         public class Property : PropertyBase, IIteratorContainer {
5174                 const int AllowedModifiers =
5175                         Modifiers.NEW |
5176                         Modifiers.PUBLIC |
5177                         Modifiers.PROTECTED |
5178                         Modifiers.INTERNAL |
5179                         Modifiers.PRIVATE |
5180                         Modifiers.STATIC |
5181                         Modifiers.SEALED |
5182                         Modifiers.OVERRIDE |
5183                         Modifiers.ABSTRACT |
5184                         Modifiers.UNSAFE |
5185                         Modifiers.EXTERN |
5186                         Modifiers.METHOD_YIELDS |
5187                         Modifiers.VIRTUAL;
5188
5189                 const int AllowedInterfaceModifiers =
5190                         Modifiers.NEW;
5191
5192                 public Property (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
5193                                  string name, Attributes attrs, Accessor get_block,
5194                                  Accessor set_block, Location loc)
5195                         : base (ds, type, mod_flags,
5196                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5197                                 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
5198                                 loc)
5199                 {
5200                         if (get_block != null)
5201                                 Get = new GetMethod (this, get_block);
5202
5203                         if (set_block != null)
5204                                 Set = new SetMethod (this, set_block);
5205                 }
5206
5207                 public override bool Define (TypeContainer container)
5208                 {
5209                         if (!DoDefine (container))
5210                                 return false;
5211
5212                         if (!CheckBase (container))
5213                                 return false;
5214
5215                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5216
5217                         if (Get != null) {
5218
5219                                 GetBuilder = Get.Define (container);
5220                                 if (GetBuilder == null)
5221                                         return false;
5222
5223                                 //
5224                                 // Setup iterator if we are one
5225                                 //
5226                                 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
5227                                         IteratorHandler ih = new  IteratorHandler (
5228                                                                                    "get", container, MemberType,
5229                                                                                    TypeManager.NoTypes, Get.ParameterInfo, ModFlags, Location);
5230                                         
5231                                         Block new_block = ih.Setup (block);
5232                                         if (new_block == null)
5233                                                 return false;
5234                                         block = new_block;
5235                                 }
5236                         }
5237
5238                         if (Set != null) {
5239                                 SetBuilder = Set.Define (container);
5240                                 if (SetBuilder == null)
5241                                         return false;
5242
5243                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
5244                         }
5245
5246                         // FIXME - PropertyAttributes.HasDefault ?
5247                         
5248                         PropertyAttributes prop_attr = PropertyAttributes.None;
5249                         if (!IsInterface)
5250                                 prop_attr |= PropertyAttributes.RTSpecialName |
5251                                         PropertyAttributes.SpecialName;
5252
5253                         if (!IsExplicitImpl){
5254                                 PropertyBuilder = container.TypeBuilder.DefineProperty (
5255                                         Name, prop_attr, MemberType, null);
5256                                 
5257                                 if (Get != null)
5258                                         PropertyBuilder.SetGetMethod (GetBuilder);
5259                                 
5260                                 if (Set != null)
5261                                         PropertyBuilder.SetSetMethod (SetBuilder);
5262
5263                                 //
5264                                 // HACK for the reasons exposed above
5265                                 //
5266                                 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
5267                                         Report.Error (
5268                                                 111, Location,
5269                                                 "Class `" + container.Name +
5270                                                 "' already contains a definition for the property `" +
5271                                                 Name + "'");
5272                                         return false;
5273                                 }
5274                         }
5275                         return true;
5276                 }
5277
5278                 public void SetYields ()
5279                 {
5280                         ModFlags |= Modifiers.METHOD_YIELDS;
5281                 }
5282         }
5283
5284         /// </summary>
5285         ///  Gigantic workaround  for lameness in SRE follows :
5286         ///  This class derives from EventInfo and attempts to basically
5287         ///  wrap around the EventBuilder so that FindMembers can quickly
5288         ///  return this in it search for members
5289         /// </summary>
5290         public class MyEventBuilder : EventInfo {
5291                 
5292                 //
5293                 // We use this to "point" to our Builder which is
5294                 // not really a MemberInfo
5295                 //
5296                 EventBuilder MyBuilder;
5297                 
5298                 //
5299                 // We "catch" and wrap these methods
5300                 //
5301                 MethodInfo raise, remove, add;
5302
5303                 EventAttributes attributes;
5304                 Type declaring_type, reflected_type, event_type;
5305                 string name;
5306
5307                 Event my_event;
5308
5309                 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
5310                 {
5311                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
5312
5313                         // And now store the values in our own fields.
5314                         
5315                         declaring_type = type_builder;
5316
5317                         reflected_type = type_builder;
5318                         
5319                         attributes = event_attr;
5320                         this.name = name;
5321                         my_event = ev;
5322                         this.event_type = event_type;
5323                 }
5324                 
5325                 //
5326                 // Methods that you have to override.  Note that you only need 
5327                 // to "implement" the variants that take the argument (those are
5328                 // the "abstract" methods, the others (GetAddMethod()) are 
5329                 // regular.
5330                 //
5331                 public override MethodInfo GetAddMethod (bool nonPublic)
5332                 {
5333                         return add;
5334                 }
5335                 
5336                 public override MethodInfo GetRemoveMethod (bool nonPublic)
5337                 {
5338                         return remove;
5339                 }
5340                 
5341                 public override MethodInfo GetRaiseMethod (bool nonPublic)
5342                 {
5343                         return raise;
5344                 }
5345                 
5346                 //
5347                 // These methods make "MyEventInfo" look like a Builder
5348                 //
5349                 public void SetRaiseMethod (MethodBuilder raiseMethod)
5350                 {
5351                         raise = raiseMethod;
5352                         MyBuilder.SetRaiseMethod (raiseMethod);
5353                 }
5354
5355                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
5356                 {
5357                         remove = removeMethod;
5358                         MyBuilder.SetRemoveOnMethod (removeMethod);
5359                 }
5360
5361                 public void SetAddOnMethod (MethodBuilder addMethod)
5362                 {
5363                         add = addMethod;
5364                         MyBuilder.SetAddOnMethod (addMethod);
5365                 }
5366
5367                 public void SetCustomAttribute (CustomAttributeBuilder cb)
5368                 {
5369                         MyBuilder.SetCustomAttribute (cb);
5370                 }
5371                 
5372                 public override object [] GetCustomAttributes (bool inherit)
5373                 {
5374                         // FIXME : There's nothing which can be seemingly done here because
5375                         // we have no way of getting at the custom attribute objects of the
5376                         // EventBuilder !
5377                         return null;
5378                 }
5379
5380                 public override object [] GetCustomAttributes (Type t, bool inherit)
5381                 {
5382                         // FIXME : Same here !
5383                         return null;
5384                 }
5385
5386                 public override bool IsDefined (Type t, bool b)
5387                 {
5388                         return true;
5389                 }
5390
5391                 public override EventAttributes Attributes {
5392                         get {
5393                                 return attributes;
5394                         }
5395                 }
5396
5397                 public override string Name {
5398                         get {
5399                                 return name;
5400                         }
5401                 }
5402
5403                 public override Type DeclaringType {
5404                         get {
5405                                 return declaring_type;
5406                         }
5407                 }
5408
5409                 public override Type ReflectedType {
5410                         get {
5411                                 return reflected_type;
5412                         }
5413                 }
5414
5415                 public Type EventType {
5416                         get {
5417                                 return event_type;
5418                         }
5419                 }
5420                 
5421                 public void SetUsed ()
5422                 {
5423                         if (my_event != null)
5424                                 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
5425                 }
5426         }
5427         
5428         /// <summary>
5429         /// For case when event is declared like property (with add and remove accessors).
5430         /// </summary>
5431         public class EventProperty: Event {
5432
5433                 static string[] attribute_targets = new string [] { "event", "property" };
5434
5435                 public EventProperty (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
5436                         Object init, Attributes attrs, Accessor add, Accessor remove, Location loc)
5437                         : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
5438                 {
5439                         Add = new AddDelegateMethod (this, add);
5440                         Remove = new RemoveDelegateMethod (this, remove);
5441                 }
5442
5443                 protected override string[] ValidAttributeTargets {
5444                         get {
5445                                 return attribute_targets;
5446                         }
5447                 }
5448         }
5449
5450         /// <summary>
5451         /// Event is declared like field.
5452         /// </summary>
5453         public class EventField: Event {
5454
5455                 static string[] attribute_targets = new string [] { "method", "field", "event" };
5456
5457                 public EventField (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
5458                         Object init, Attributes attrs, Location loc)
5459                         : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
5460                 {
5461                         Add = new AddDelegateMethod (this);
5462                         Remove = new RemoveDelegateMethod (this);
5463                 }
5464
5465                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5466                 {
5467                         if (a.Target == "field") {
5468                                 FieldBuilder.SetCustomAttribute (cb);
5469                                 return;
5470                         }
5471
5472                         if (a.Target == "method") {
5473                                 AddBuilder.SetCustomAttribute (cb);
5474                                 RemoveBuilder.SetCustomAttribute (cb);
5475                                 return;
5476                         }
5477
5478                         base.ApplyAttributeBuilder (a, cb);
5479                 }
5480
5481                 protected override string[] ValidAttributeTargets {
5482                         get {
5483                                 return attribute_targets;
5484                         }
5485                 }
5486         }
5487
5488         public abstract class Event : FieldBase {
5489
5490                 protected sealed class AddDelegateMethod: DelegateMethod
5491                 {
5492                         public AddDelegateMethod (Event method):
5493                                 base (method)
5494                         {
5495                         }
5496
5497                         public AddDelegateMethod (Event method, Accessor accessor):
5498                                 base (method, accessor)
5499                         {
5500                         }
5501
5502                         public override string MethodName {
5503                                 get {
5504                                         return "add_" + method.ShortName;
5505                                 }
5506                         }
5507
5508                         protected override MethodInfo DelegateMethodInfo {
5509                                 get {
5510                                         return TypeManager.delegate_combine_delegate_delegate;
5511                                 }
5512                         }
5513
5514                 }
5515
5516                 protected sealed class RemoveDelegateMethod: DelegateMethod
5517                 {
5518                         public RemoveDelegateMethod (Event method):
5519                                 base (method)
5520                         {
5521                         }
5522
5523                         public RemoveDelegateMethod (Event method, Accessor accessor):
5524                                 base (method, accessor)
5525                         {
5526                         }
5527
5528                         public override string MethodName {
5529                                 get {
5530                                         return "remove_" + method.ShortName;
5531                                 }
5532                         }
5533
5534                         protected override MethodInfo DelegateMethodInfo {
5535                                 get {
5536                                         return TypeManager.delegate_remove_delegate_delegate;
5537                                 }
5538                         }
5539
5540                 }
5541
5542                 public abstract class DelegateMethod: Attributable, IMethodData
5543                 {
5544                         protected readonly Event method;
5545                         protected MethodData method_data;
5546                         Block block;
5547                         ReturnParameter return_attributes;
5548                         ImplicitParameter param_attr;
5549
5550                         static string[] attribute_targets = new string [] { "method", "param", "return" };
5551
5552                         public DelegateMethod (Event method):
5553                                 base (null)
5554                         {
5555                                 this.method = method;
5556                         }
5557
5558                         public DelegateMethod (Event method, Accessor accessor):
5559                                 base (accessor.Attributes)
5560                         {
5561                                 this.method = method;
5562                                 this.block = accessor.Block;
5563                         }
5564
5565                         public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5566                         {
5567                                 if (a.Target == "return") {
5568                                         if (return_attributes == null)
5569                                                 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5570
5571                                         return_attributes.ApplyAttributeBuilder (a, cb);
5572                                         return;
5573                                 }
5574
5575                                 if (a.Target == "param") {
5576                                         if (param_attr == null)
5577                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5578
5579                                         param_attr.ApplyAttributeBuilder (a, cb);
5580                                         return;
5581                                 }
5582
5583                                 method_data.MethodBuilder.SetCustomAttribute (cb);
5584                         }
5585
5586                         public override AttributeTargets AttributeTargets {
5587                                 get {
5588                                         return AttributeTargets.Method;
5589                                 }
5590                         }
5591
5592                         public override bool IsClsCompliaceRequired(DeclSpace ds)
5593                         {
5594                                 return method.IsClsCompliaceRequired (ds);
5595                         }
5596
5597                         public MethodBuilder Define (TypeContainer container, InternalParameters ip)
5598                         {
5599                                 method_data = new MethodData (method, ip, method.ModFlags,
5600                                         method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, false, this);
5601
5602                                 if (!method_data.Define (container))
5603                                         return null;
5604
5605                                 MethodBuilder mb = method_data.MethodBuilder;
5606                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
5607                                 return mb;
5608                         }
5609
5610                         #region IMethodData Members
5611
5612                         public Block Block {
5613                                 get {
5614                                         return block;
5615                                 }
5616                         }
5617
5618                         public CallingConventions CallingConventions {
5619                                 get {
5620                                         return CallingConventions.Standard;
5621                                 }
5622                         }
5623
5624                         public void Emit (TypeContainer tc)
5625                         {
5626                                 if (block != null) {
5627                                         method_data.Emit (tc, this);
5628                                         block = null;
5629                                         return;
5630                                 }
5631
5632                                 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
5633                                 EmitContext ec = CreateEmitContext (tc, ig);
5634                                 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
5635
5636                                 if ((method.ModFlags & Modifiers.STATIC) != 0) {
5637                                         ig.Emit (OpCodes.Ldsfld, field_info);
5638                                         ig.Emit (OpCodes.Ldarg_0);
5639                                         ig.Emit (OpCodes.Call, DelegateMethodInfo);
5640                                         ig.Emit (OpCodes.Castclass, method.MemberType);
5641                                         ig.Emit (OpCodes.Stsfld, field_info);
5642                                 } else {
5643                                         ig.Emit (OpCodes.Ldarg_0);
5644                                         ig.Emit (OpCodes.Ldarg_0);
5645                                         ig.Emit (OpCodes.Ldfld, field_info);
5646                                         ig.Emit (OpCodes.Ldarg_1);
5647                                         ig.Emit (OpCodes.Call, DelegateMethodInfo);
5648                                         ig.Emit (OpCodes.Castclass, method.MemberType);
5649                                         ig.Emit (OpCodes.Stfld, field_info);
5650                                 }
5651                                 ig.Emit (OpCodes.Ret);
5652                         }
5653
5654                         public string GetSignatureForError (TypeContainer tc)
5655                         {
5656                                 return String.Concat (tc.Name, '.', method.Name);
5657                         }
5658
5659                         protected abstract MethodInfo DelegateMethodInfo { get; }
5660
5661                         public Type[] ParameterTypes {
5662                                 get {
5663                                         return new Type[] { method.MemberType };
5664                                 }
5665                         }
5666
5667                         public Type ReturnType {
5668                                 get {
5669                                         return TypeManager.void_type;
5670                                 }
5671                         }
5672
5673                         public Location Location {
5674                                 get {
5675                                         return method.Location;
5676                                 }
5677                         }
5678
5679                         public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
5680                         {
5681                                 return new EmitContext (tc, method.ds, Location, ig, ReturnType, method.ModFlags, false);
5682                         }
5683
5684                         public ObsoleteAttribute GetObsoleteAttribute ()
5685                         {
5686                                 return method.GetObsoleteAttribute (method.ds);
5687                         }
5688
5689                         public bool IsExcluded (EmitContext ec)
5690                         {
5691                                 return false;
5692                         }
5693
5694                         public abstract string MethodName { get; }
5695
5696                         #endregion
5697
5698                         protected override string[] ValidAttributeTargets {
5699                                 get {
5700                                         return attribute_targets;
5701                                 }
5702                         }
5703                 }
5704
5705
5706                 const int AllowedModifiers =
5707                         Modifiers.NEW |
5708                         Modifiers.PUBLIC |
5709                         Modifiers.PROTECTED |
5710                         Modifiers.INTERNAL |
5711                         Modifiers.PRIVATE |
5712                         Modifiers.STATIC |
5713                         Modifiers.VIRTUAL |
5714                         Modifiers.SEALED |
5715                         Modifiers.OVERRIDE |
5716                         Modifiers.UNSAFE |
5717                         Modifiers.ABSTRACT;
5718
5719                 const int AllowedInterfaceModifiers =
5720                         Modifiers.NEW;
5721
5722                 protected DelegateMethod Add, Remove;
5723                 public MyEventBuilder     EventBuilder;
5724                 public MethodBuilder AddBuilder, RemoveBuilder;
5725                 public DeclSpace ds;
5726
5727                 public Event (DeclSpace ds, Expression type, int mod_flags, bool is_iface, string name,
5728                                 Object init, Attributes attrs, Location loc)
5729                         : base (type, mod_flags, is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5730                                 name, init, attrs, loc)
5731                 {
5732                         IsInterface = is_iface;
5733                         this.ds = ds;
5734                 }
5735
5736                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5737                 {
5738                         EventBuilder.SetCustomAttribute (cb);
5739                 }
5740
5741                 public override AttributeTargets AttributeTargets {
5742                         get {
5743                                 return AttributeTargets.Event;
5744                         }
5745                 }
5746
5747                 public override bool Define (TypeContainer container)
5748                 {
5749                         EventAttributes e_attr;
5750                         if (IsInterface)
5751                                 e_attr = EventAttributes.None;
5752                         else
5753                                 e_attr = EventAttributes.RTSpecialName |
5754                                         EventAttributes.SpecialName;
5755
5756                         if (!DoDefine (container))
5757                                 return false;
5758
5759                         if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
5760                                 Report.Error (74, Location, "'" + container.Name + "." + Name +
5761                                               "': abstract event can not have an initializer");
5762                                 return false;
5763                         }
5764                         
5765                         if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
5766                                 Report.Error (66, Location, "'" + container.Name + "." + Name +
5767                                               "' : event must be of a delegate type");
5768                                 return false;
5769                         }
5770
5771                         Parameter [] parms = new Parameter [1];
5772                         parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
5773                         InternalParameters ip = new InternalParameters (
5774                                 container, new Parameters (parms, null, Location)); 
5775
5776                         if (!CheckBase (container))
5777                                 return false;
5778
5779                         //
5780                         // Now define the accessors
5781                         //
5782
5783                         AddBuilder = Add.Define (container, ip);
5784                         if (AddBuilder == null)
5785                                 return false;
5786
5787                         RemoveBuilder = Remove.Define (container, ip);
5788                         if (RemoveBuilder == null)
5789                                 return false;
5790
5791                         if (!IsExplicitImpl){
5792                                 EventBuilder = new MyEventBuilder (this,
5793                                         container.TypeBuilder, Name, e_attr, MemberType);
5794                                         
5795                                 if (Add.Block == null && Remove.Block == null &&
5796                                     !IsInterface) {
5797                                         FieldBuilder = container.TypeBuilder.DefineField (
5798                                                 Name, MemberType,
5799                                                 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
5800                                         TypeManager.RegisterPrivateFieldOfEvent (
5801                                                 (EventInfo) EventBuilder, FieldBuilder);
5802                                         TypeManager.RegisterFieldBase (FieldBuilder, this);
5803                                 }
5804                         
5805                                 EventBuilder.SetAddOnMethod (AddBuilder);
5806                                 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
5807
5808                                 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
5809                                         Report.Error (111, Location,
5810                                                       "Class `" + container.Name +
5811                                                       "' already contains a definition for the event `" +
5812                                                       Name + "'");
5813                                         return false;
5814                                 }
5815                         }
5816                         
5817                         return true;
5818                 }
5819
5820                 public override void Emit (TypeContainer tc)
5821                 {
5822                         if (OptAttributes != null) {
5823                                 EmitContext ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
5824                                 OptAttributes.Emit (ec, this);
5825                         }
5826
5827                         if (!IsInterface) {
5828                                 Add.Emit (tc);
5829                                 Remove.Emit (tc);
5830                         }
5831
5832                         base.Emit (tc);
5833                 }
5834         }
5835
5836         //
5837         // FIXME: This does not handle:
5838         //
5839         //   int INTERFACENAME [ args ]
5840         //   Does not 
5841         //
5842         // Only:
5843         // 
5844         // int this [ args ]
5845  
5846         public class Indexer : PropertyBase {
5847
5848                 class GetIndexerMethod: GetMethod
5849                 {
5850                         public GetIndexerMethod (MethodCore method, Accessor accessor):
5851                                 base (method, accessor)
5852                         {
5853                         }
5854
5855                         public override Type[] ParameterTypes {
5856                                 get {
5857                                         return method.ParameterTypes;
5858                                 }
5859                         }
5860                 }
5861
5862                 class SetIndexerMethod: SetMethod
5863                 {
5864                         readonly Parameters parameters;
5865
5866                         public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
5867                                 base (method, accessor)
5868                         {
5869                                 this.parameters = parameters;
5870                         }
5871
5872                         public override Type[] ParameterTypes {
5873                                 get {
5874                                         int top = method.ParameterTypes.Length;
5875                                         Type [] set_pars = new Type [top + 1];
5876                                         method.ParameterTypes.CopyTo (set_pars, 0);
5877                                         set_pars [top] = method.MemberType;
5878                                         return set_pars;
5879                                 }
5880                         }
5881
5882                         protected override InternalParameters GetParameterInfo (TypeContainer container)
5883                         {
5884                                 Parameter [] fixed_parms = parameters.FixedParameters;
5885
5886                                 if (fixed_parms == null){
5887                                         throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
5888                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5889                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5890                                         //
5891                                         // Here is the problem: the `value' parameter has
5892                                         // to come *after* the array parameter in the declaration
5893                                         // like this:
5894                                         // X (object [] x, Type value)
5895                                         // .param [0]
5896                                         //
5897                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5898                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5899                                         
5900                                 }
5901                                 
5902                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
5903
5904                                 fixed_parms.CopyTo (tmp, 0);
5905                                 tmp [fixed_parms.Length] = new Parameter (
5906                                         method.Type, "value", Parameter.Modifier.NONE, null);
5907
5908                                 Parameters set_formal_params = new Parameters (tmp, null, method.Location);
5909                                 
5910                                 return new InternalParameters (container, set_formal_params);
5911                         }
5912
5913                 }
5914
5915
5916                 const int AllowedModifiers =
5917                         Modifiers.NEW |
5918                         Modifiers.PUBLIC |
5919                         Modifiers.PROTECTED |
5920                         Modifiers.INTERNAL |
5921                         Modifiers.PRIVATE |
5922                         Modifiers.VIRTUAL |
5923                         Modifiers.SEALED |
5924                         Modifiers.OVERRIDE |
5925                         Modifiers.UNSAFE |
5926                         Modifiers.EXTERN |
5927                         Modifiers.ABSTRACT;
5928
5929                 const int AllowedInterfaceModifiers =
5930                         Modifiers.NEW;
5931
5932                 public string IndexerName;
5933                 public string InterfaceIndexerName;
5934
5935                 //
5936                 // Are we implementing an interface ?
5937                 //
5938                 public Indexer (DeclSpace ds, Expression type, string int_type, int mod_flags,
5939                                 bool is_iface, Parameters parameters, Attributes attrs,
5940                                 Accessor get_block, Accessor set_block, Location loc)
5941                         : base (ds, type, mod_flags,
5942                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5943                                 is_iface, "", parameters, attrs, loc)
5944                 {
5945                         ExplicitInterfaceName = int_type;
5946
5947                         if (get_block != null)
5948                                 Get = new GetIndexerMethod (this, get_block);
5949
5950                         if (set_block != null)
5951                                 Set = new SetIndexerMethod (this, parameters, set_block);
5952                 }
5953                        
5954                 public override bool Define (TypeContainer container)
5955                 {
5956                         PropertyAttributes prop_attr =
5957                                 PropertyAttributes.RTSpecialName |
5958                                 PropertyAttributes.SpecialName;
5959                         
5960                         if (!DoDefine (container))
5961                                 return false;
5962
5963                         if (OptAttributes != null)
5964                                 IndexerName = OptAttributes.ScanForIndexerName (ec);
5965
5966                         if (IndexerName == null)
5967                                 IndexerName = "Item";
5968                         else {
5969                                 if (! Tokenizer.IsValidIdentifier (IndexerName)) {
5970                                         Report.Error (633, Location, "The IndexerName specified is an invalid identifier");
5971                                         return false;
5972                                 }
5973                                 
5974                                 if (IsExplicitImpl) {
5975                                         Report.Error (592, Location,
5976                                                       "Attribute 'IndexerName' is not valid on explicit implementations.");
5977                                         return false;
5978                                 }
5979                         }
5980
5981                         ShortName = IndexerName;
5982                         if (IsExplicitImpl) {
5983                                 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
5984                                 Name = InterfaceType.FullName + "." + IndexerName;
5985                         } else {
5986                                 InterfaceIndexerName = IndexerName;
5987                                 Name = ShortName;
5988                         }
5989
5990                         if (!CheckNameCollision (container))
5991                                 return false;
5992
5993                         if (!CheckBase (container))
5994                                 return false;
5995
5996                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5997                         if (Get != null){
5998                                 GetBuilder = Get.Define (container);
5999                                 if (GetBuilder == null)
6000                                         return false;
6001                         }
6002                         
6003                         if (Set != null){
6004                                 SetBuilder = Set.Define (container);
6005                                 if (SetBuilder == null)
6006                                         return false;
6007                         }
6008
6009                         //
6010                         // Now name the parameters
6011                         //
6012                         Parameter [] p = Parameters.FixedParameters;
6013                         if (p != null) {
6014                                 int i;
6015                                 
6016                                 for (i = 0; i < p.Length; ++i) {
6017                                         if (Get != null)
6018                                                 GetBuilder.DefineParameter (
6019                                                         i + 1, p [i].Attributes, p [i].Name);
6020
6021                                         if (Set != null)
6022                                                 SetBuilder.DefineParameter (
6023                                                         i + 1, p [i].Attributes, p [i].Name);
6024                                 }
6025
6026                                 if (Set != null)
6027                                         SetBuilder.DefineParameter (
6028                                                 i + 1, ParameterAttributes.None, "value");
6029                                         
6030                                 if (i != ParameterTypes.Length) {
6031                                         Parameter array_param = Parameters.ArrayParameter;
6032
6033                                         SetBuilder.DefineParameter (
6034                                                 i + 1, array_param.Attributes, array_param.Name);
6035                                 }
6036                         }
6037
6038                         //
6039                         // Define the PropertyBuilder if one of the following conditions are met:
6040                         // a) we're not implementing an interface indexer.
6041                         // b) the indexer has a different IndexerName and this is no
6042                         //    explicit interface implementation.
6043                         //
6044                         if (!IsExplicitImpl) {
6045                                 PropertyBuilder = container.TypeBuilder.DefineProperty (
6046                                         IndexerName, prop_attr, MemberType, ParameterTypes);
6047
6048                                 if (Get != null)
6049                                         PropertyBuilder.SetGetMethod (GetBuilder);
6050
6051                                 if (Set != null)
6052                                         PropertyBuilder.SetSetMethod (SetBuilder);
6053                                 
6054                                 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
6055                                                              ParameterTypes);
6056                         }
6057
6058                         return true;
6059                 }
6060
6061                 bool CheckNameCollision (TypeContainer container) {
6062                         switch (VerifyName (container)){
6063                                 case DeclSpace.AdditionResult.NameExists:
6064                                         Report.Error (102, Location, "The container '{0}' already contains a definition for '{1}'", container.GetSignatureForError (), Name);
6065                                         return false;
6066
6067                                 case DeclSpace.AdditionResult.Success:
6068                                         return true;
6069                         }
6070                         throw new NotImplementedException ();
6071                 }
6072
6073                 DeclSpace.AdditionResult VerifyName (TypeContainer container) {
6074                         if (!AddIndexer (container, container.Name + "." + Name))
6075                                 return DeclSpace.AdditionResult.NameExists;
6076
6077                         if (Get != null) {
6078                                 if (!AddIndexer (container, container.Name + ".get_" + Name))
6079                                         return DeclSpace.AdditionResult.NameExists;
6080                         }
6081
6082                         if (Set != null) {
6083                                 if (!AddIndexer (container, container.Name + ".set_" + Name))
6084                                         return DeclSpace.AdditionResult.NameExists;
6085                         }
6086                         return DeclSpace.AdditionResult.Success;
6087                 }
6088
6089                 bool AddIndexer (TypeContainer container, string fullname)
6090                 {
6091                         object value = container.GetDefinition (fullname);
6092
6093                         if (value != null) {
6094                                 return value.GetType () != GetType () ? false : true;
6095                         }
6096
6097                         container.DefineName (fullname, this);
6098                         return true;
6099                 }
6100
6101                 public override string GetSignatureForError ()
6102                 {
6103                         return TypeManager.CSharpSignature (PropertyBuilder, true);
6104                 }
6105
6106                 protected override string RealMethodName {
6107                         get {
6108                                 return IndexerName;
6109                         }
6110                 }
6111         }
6112
6113         public class Operator : MemberBase, IIteratorContainer {
6114
6115                 const int AllowedModifiers =
6116                         Modifiers.PUBLIC |
6117                         Modifiers.UNSAFE |
6118                         Modifiers.EXTERN |
6119                         Modifiers.STATIC;
6120
6121                 const int RequiredModifiers =
6122                         Modifiers.PUBLIC |
6123                         Modifiers.STATIC;
6124
6125                 public enum OpType : byte {
6126
6127                         // Unary operators
6128                         LogicalNot,
6129                         OnesComplement,
6130                         Increment,
6131                         Decrement,
6132                         True,
6133                         False,
6134
6135                         // Unary and Binary operators
6136                         Addition,
6137                         Subtraction,
6138
6139                         UnaryPlus,
6140                         UnaryNegation,
6141                         
6142                         // Binary operators
6143                         Multiply,
6144                         Division,
6145                         Modulus,
6146                         BitwiseAnd,
6147                         BitwiseOr,
6148                         ExclusiveOr,
6149                         LeftShift,
6150                         RightShift,
6151                         Equality,
6152                         Inequality,
6153                         GreaterThan,
6154                         LessThan,
6155                         GreaterThanOrEqual,
6156                         LessThanOrEqual,
6157
6158                         // Implicit and Explicit
6159                         Implicit,
6160                         Explicit
6161                 };
6162
6163                 public readonly OpType OperatorType;
6164                 public readonly Expression ReturnType;
6165                 public readonly Expression FirstArgType, SecondArgType;
6166                 public readonly string FirstArgName, SecondArgName;
6167                 public Block           Block;
6168                 public MethodBuilder   OperatorMethodBuilder;
6169                 
6170                 public string MethodName;
6171                 public Method OperatorMethod;
6172
6173                 static string[] attribute_targets = new string [] { "method", "return" };
6174
6175                 public Operator (OpType type, Expression ret_type, int mod_flags,
6176                                  Expression arg1type, string arg1name,
6177                                  Expression arg2type, string arg2name,
6178                                  Block block, Attributes attrs, Location loc)
6179                         : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
6180                 {
6181                         OperatorType = type;
6182                         Name = "op_" + OperatorType;
6183                         ReturnType = ret_type;
6184                         FirstArgType = arg1type;
6185                         FirstArgName = arg1name;
6186                         SecondArgType = arg2type;
6187                         SecondArgName = arg2name;
6188                         Block = block;
6189                 }
6190
6191                 string Prototype (TypeContainer container)
6192                 {
6193                         return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
6194                                 SecondArgType + ")";
6195                 }
6196
6197                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) 
6198                 {
6199                         OperatorMethod.ApplyAttributeBuilder (a, cb);
6200                 }
6201
6202                 public override AttributeTargets AttributeTargets {
6203                         get {
6204                                 return AttributeTargets.Method; 
6205                         }
6206                 }
6207                 
6208                 public override bool Define (TypeContainer container)
6209                 {
6210                         int length = 1;
6211                         MethodName = "op_" + OperatorType;
6212                         
6213                         if (SecondArgType != null)
6214                                 length = 2;
6215                         
6216                         Parameter [] param_list = new Parameter [length];
6217
6218                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
6219                                 Report.Error (
6220                                         558, Location, 
6221                                         "User defined operators `" +
6222                                         Prototype (container) +
6223                                         "' must be declared static and public");
6224                                 return false;
6225                         }
6226
6227                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
6228                                                        Parameter.Modifier.NONE, null);
6229                         if (SecondArgType != null)
6230                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
6231                                                                Parameter.Modifier.NONE, null);
6232                         
6233                         OperatorMethod = new Method (
6234                                 container, ReturnType, ModFlags, false, MethodName,
6235                                 new Parameters (param_list, null, Location),
6236                                 OptAttributes, Location);
6237
6238                         OperatorMethod.Block = Block;
6239                         OperatorMethod.IsOperator = true;                       
6240                         OperatorMethod.Define (container);
6241
6242                         if (OperatorMethod.MethodBuilder == null)
6243                                 return false;
6244                         
6245                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
6246
6247                         Type [] param_types = OperatorMethod.ParameterTypes;
6248                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
6249                         Type return_type = OperatorMethod.GetReturnType ();
6250                         Type first_arg_type = param_types [0];
6251
6252                         // Rules for conversion operators
6253                         
6254                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
6255                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
6256                                         Report.Error (
6257                                                 555, Location,
6258                                                 "User-defined conversion cannot take an object of the " +
6259                                                 "enclosing type and convert to an object of the enclosing" +
6260                                                 " type");
6261                                         return false;
6262                                 }
6263                                 
6264                                 if (first_arg_type != declaring_type && return_type != declaring_type){
6265                                         Report.Error (
6266                                                 556, Location, 
6267                                                 "User-defined conversion must convert to or from the " +
6268                                                 "enclosing type");
6269                                         return false;
6270                                 }
6271                                 
6272                                 if (first_arg_type == TypeManager.object_type ||
6273                                     return_type == TypeManager.object_type){
6274                                         Report.Error (
6275                                                 -8, Location,
6276                                                 "User-defined conversion cannot convert to or from " +
6277                                                 "object type");
6278                                         return false;
6279                                 }
6280
6281                                 if (first_arg_type.IsInterface || return_type.IsInterface){
6282                                         Report.Error (
6283                                                 552, Location,
6284                                                 "User-defined conversion cannot convert to or from an " +
6285                                                 "interface type");
6286                                         return false;
6287                                 }
6288                                 
6289                                 if (first_arg_type.IsSubclassOf (return_type) ||
6290                                     return_type.IsSubclassOf (first_arg_type)){
6291                                         Report.Error (
6292                                                 -10, Location,
6293                                                 "User-defined conversion cannot convert between types " +
6294                                                 "that derive from each other");
6295                                         return false;
6296                                 }
6297                         } else if (SecondArgType == null) {
6298                                 // Checks for Unary operators
6299                                 
6300                                 if (first_arg_type != declaring_type){
6301                                         Report.Error (
6302                                                 562, Location,
6303                                                 "The parameter of a unary operator must be the " +
6304                                                 "containing type");
6305                                         return false;
6306                                 }
6307                                 
6308                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
6309                                         if (return_type != declaring_type){
6310                                                 Report.Error (
6311                                                         559, Location,
6312                                                         "The parameter and return type for ++ and -- " +
6313                                                         "must be the containing type");
6314                                                 return false;
6315                                         }
6316                                         
6317                                 }
6318                                 
6319                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
6320                                         if (return_type != TypeManager.bool_type){
6321                                                 Report.Error (
6322                                                         215, Location,
6323                                                         "The return type of operator True or False " +
6324                                                         "must be bool");
6325                                                 return false;
6326                                         }
6327                                 }
6328                                 
6329                         } else {
6330                                 // Checks for Binary operators
6331                                 
6332                                 if (first_arg_type != declaring_type &&
6333                                     param_types [1] != declaring_type){
6334                                         Report.Error (
6335                                                 563, Location,
6336                                                 "One of the parameters of a binary operator must " +
6337                                                 "be the containing type");
6338                                         return false;
6339                                 }
6340                         }
6341
6342                         return true;
6343                 }
6344                 
6345                 public override void Emit (TypeContainer container)
6346                 {
6347                         //
6348                         // abstract or extern methods have no bodies
6349                         //
6350                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
6351                                 return;
6352                         
6353                         OperatorMethod.Emit (container);
6354                         Block = null;
6355                 }
6356
6357                 public static string GetName (OpType ot)
6358                 {
6359                         switch (ot){
6360                         case OpType.LogicalNot:
6361                                 return "!";
6362                         case OpType.OnesComplement:
6363                                 return "~";
6364                         case OpType.Increment:
6365                                 return "++";
6366                         case OpType.Decrement:
6367                                 return "--";
6368                         case OpType.True:
6369                                 return "true";
6370                         case OpType.False:
6371                                 return "false";
6372                         case OpType.Addition:
6373                                 return "+";
6374                         case OpType.Subtraction:
6375                                 return "-";
6376                         case OpType.UnaryPlus:
6377                                 return "+";
6378                         case OpType.UnaryNegation:
6379                                 return "-";
6380                         case OpType.Multiply:
6381                                 return "*";
6382                         case OpType.Division:
6383                                 return "/";
6384                         case OpType.Modulus:
6385                                 return "%";
6386                         case OpType.BitwiseAnd:
6387                                 return "&";
6388                         case OpType.BitwiseOr:
6389                                 return "|";
6390                         case OpType.ExclusiveOr:
6391                                 return "^";
6392                         case OpType.LeftShift:
6393                                 return "<<";
6394                         case OpType.RightShift:
6395                                 return ">>";
6396                         case OpType.Equality:
6397                                 return "==";
6398                         case OpType.Inequality:
6399                                 return "!=";
6400                         case OpType.GreaterThan:
6401                                 return ">";
6402                         case OpType.LessThan:
6403                                 return "<";
6404                         case OpType.GreaterThanOrEqual:
6405                                 return ">=";
6406                         case OpType.LessThanOrEqual:
6407                                 return "<=";
6408                         case OpType.Implicit:
6409                                 return "implicit";
6410                         case OpType.Explicit:
6411                                 return "explicit";
6412                         default: return "";
6413                         }
6414                 }
6415
6416                 public override string GetSignatureForError(TypeContainer tc)
6417                 {
6418                         return Prototype (tc);
6419                 }
6420                 
6421                 public override string ToString ()
6422                 {
6423                         Type return_type = OperatorMethod.GetReturnType();
6424                         Type [] param_types = OperatorMethod.ParameterTypes;
6425                         
6426                         if (SecondArgType == null)
6427                                 return String.Format (
6428                                         "{0} operator {1}({2})",
6429                                         TypeManager.CSharpName (return_type),
6430                                         GetName (OperatorType),
6431                                         param_types [0]);
6432                         else
6433                                 return String.Format (
6434                                         "{0} operator {1}({2}, {3})",
6435                                         TypeManager.CSharpName (return_type),
6436                                         GetName (OperatorType),
6437                                         param_types [0], param_types [1]);
6438                 }
6439
6440                 protected override string[] ValidAttributeTargets {
6441                         get {
6442                                 return attribute_targets;
6443                         }
6444                 }
6445
6446                 public void SetYields ()
6447                 {
6448                         ModFlags |= Modifiers.METHOD_YIELDS;
6449                 }
6450         }
6451
6452         //
6453         // This is used to compare method signatures
6454         //
6455         struct MethodSignature {
6456                 public string Name;
6457                 public Type RetType;
6458                 public Type [] Parameters;
6459                 
6460                 /// <summary>
6461                 ///    This delegate is used to extract methods which have the
6462                 ///    same signature as the argument
6463                 /// </summary>
6464                 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
6465                 
6466                 public MethodSignature (string name, Type ret_type, Type [] parameters)
6467                 {
6468                         Name = name;
6469                         RetType = ret_type;
6470
6471                         if (parameters == null)
6472                                 Parameters = TypeManager.NoTypes;
6473                         else
6474                                 Parameters = parameters;
6475                 }
6476
6477                 public override string ToString ()
6478                 {
6479                         string pars = "";
6480                         if (Parameters.Length != 0){
6481                                 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
6482                                 for (int i = 0; i < Parameters.Length; i++){
6483                                         sb.Append (Parameters [i]);
6484                                         if (i+1 < Parameters.Length)
6485                                                 sb.Append (", ");
6486                                 }
6487                                 pars = sb.ToString ();
6488                         }
6489
6490                         return String.Format ("{0} {1} ({2})", RetType, Name, pars);
6491                 }
6492                 
6493                 public override int GetHashCode ()
6494                 {
6495                         return Name.GetHashCode ();
6496                 }
6497
6498                 public override bool Equals (Object o)
6499                 {
6500                         MethodSignature other = (MethodSignature) o;
6501
6502                         if (other.Name != Name)
6503                                 return false;
6504
6505                         if (other.RetType != RetType)
6506                                 return false;
6507                         
6508                         if (Parameters == null){
6509                                 if (other.Parameters == null)
6510                                         return true;
6511                                 return false;
6512                         }
6513
6514                         if (other.Parameters == null)
6515                                 return false;
6516                         
6517                         int c = Parameters.Length;
6518                         if (other.Parameters.Length != c)
6519                                 return false;
6520
6521                         for (int i = 0; i < c; i++)
6522                                 if (other.Parameters [i] != Parameters [i])
6523                                         return false;
6524
6525                         return true;
6526                 }
6527
6528                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
6529                 {
6530                         MethodSignature sig = (MethodSignature) filter_criteria;
6531
6532                         if (m.Name != sig.Name)
6533                                 return false;
6534
6535                         Type ReturnType;
6536                         MethodInfo mi = m as MethodInfo;
6537                         PropertyInfo pi = m as PropertyInfo;
6538
6539                         if (mi != null)
6540                                 ReturnType = mi.ReturnType;
6541                         else if (pi != null)
6542                                 ReturnType = pi.PropertyType;
6543                         else
6544                                 return false;
6545                         
6546                         //
6547                         // we use sig.RetType == null to mean `do not check the
6548                         // method return value.  
6549                         //
6550                         if (sig.RetType != null)
6551                                 if (ReturnType != sig.RetType)
6552                                         return false;
6553
6554                         Type [] args;
6555                         if (mi != null)
6556                                 args = TypeManager.GetArgumentTypes (mi);
6557                         else
6558                                 args = TypeManager.GetArgumentTypes (pi);
6559                         Type [] sigp = sig.Parameters;
6560
6561                         if (args.Length != sigp.Length)
6562                                 return false;
6563
6564                         for (int i = args.Length; i > 0; ){
6565                                 i--;
6566                                 if (args [i] != sigp [i])
6567                                         return false;
6568                         }
6569                         return true;
6570                 }
6571         }
6572 }