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