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