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