585b1f15efcb39ec8bcf8179f64f188436987381
[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, CurrentTypeParameters, 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                         DeclSpace decl;
2640                         MethodBuilder mb = null;
2641                         if (GenericMethod != null) {
2642                                 mb = container.TypeBuilder.DefineGenericMethod (Name, flags);
2643                                 if (!GenericMethod.Define (mb))
2644                                         return false;
2645                                 decl = GenericMethod;
2646                         } else
2647                                 decl = container;
2648
2649                         if (!DoDefine (decl, container))
2650                                 return false;
2651
2652                         if (!CheckBase (container))
2653                                 return false;
2654
2655                         CallingConventions cc = GetCallingConvention (container is Class);
2656
2657                         MethodData = new MethodData (ds, this, null, MemberType,
2658                                                      ParameterTypes, ParameterInfo, cc,
2659                                                      OptAttributes, ModFlags, flags, true, mb);
2660
2661                         if (!MethodData.Define (container))
2662                                 return false;
2663
2664                         //
2665                         // Setup iterator if we are one
2666                         //
2667                         if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2668                                 IteratorHandler ih = new  IteratorHandler (
2669                                             Name, container, MemberType,
2670                                             ParameterTypes, ParameterInfo,
2671                                             ModFlags, Location);
2672
2673                                 Block new_block = ih.Setup (block);
2674                                 if (new_block == null)
2675                                         return false;
2676                                 block = new_block;
2677                         }
2678
2679                         MethodBuilder = MethodData.MethodBuilder;
2680
2681                         //
2682                         // This is used to track the Entry Point,
2683                         //
2684                         if (Name == "Main" &&
2685                             ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint && 
2686                             (RootContext.MainClass == null ||
2687                              RootContext.MainClass == container.TypeBuilder.FullName)){
2688                                 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2689                                         if (RootContext.EntryPoint == null) {
2690                                                 if (container.IsGeneric){
2691                                                         Report.Error (-201, Location,
2692                                                                       "Entry point can not be defined in a generic class");
2693                                                 }
2694                                                 
2695                                                 RootContext.EntryPoint = MethodBuilder;
2696                                                 RootContext.EntryPointLocation = Location;
2697                                         } else {
2698                                                 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2699                                                 DuplicateEntryPoint (MethodBuilder, Location);
2700                                         }
2701                                 } else                                  
2702                                         Report28(MethodBuilder);
2703                         }
2704
2705                         return true;
2706                 }
2707
2708                 //
2709                 // Emits the code
2710                 // 
2711                 public void Emit (TypeContainer container)
2712                 {
2713                         MethodData.Emit (container, Block, this);
2714                         Block = null;
2715                         MethodData = null;
2716                 }
2717
2718                 void IIteratorContainer.SetYields ()
2719                 {
2720                         ModFlags |= Modifiers.METHOD_YIELDS;
2721                 }
2722         }
2723
2724         public abstract class ConstructorInitializer {
2725                 ArrayList argument_list;
2726                 ConstructorInfo parent_constructor;
2727                 Parameters parameters;
2728                 Location loc;
2729                 
2730                 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2731                                                Location loc)
2732                 {
2733                         this.argument_list = argument_list;
2734                         this.parameters = parameters;
2735                         this.loc = loc;
2736                 }
2737
2738                 public ArrayList Arguments {
2739                         get {
2740                                 return argument_list;
2741                         }
2742                 }
2743
2744                 public bool Resolve (EmitContext ec)
2745                 {
2746                         Expression parent_constructor_group;
2747                         Type t;
2748
2749                         ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
2750
2751                         if (argument_list != null){
2752                                 foreach (Argument a in argument_list){
2753                                         if (!a.Resolve (ec, loc))
2754                                                 return false;
2755                                 }
2756                         }
2757                         ec.CurrentBlock = null;
2758
2759                         if (this is ConstructorBaseInitializer) {
2760                                 if (ec.ContainerType.BaseType == null)
2761                                         return true;
2762
2763                                 t = ec.ContainerType.BaseType;
2764                                 if (ec.ContainerType.IsValueType) {
2765                                         Report.Error (522, loc,
2766                                                 "structs cannot call base class constructors");
2767                                         return false;
2768                                 }
2769                         } else
2770                                 t = ec.ContainerType;
2771
2772                         parent_constructor_group = Expression.MemberLookup (
2773                                 ec, t, null, t, ".ctor", 
2774                                 MemberTypes.Constructor,
2775                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2776                                 loc);
2777                         
2778                         if (parent_constructor_group == null){
2779                                 Report.Error (1501, loc,
2780                                        "Can not find a constructor for this argument list");
2781                                 return false;
2782                         }
2783                         
2784                         parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
2785                                 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2786                         
2787                         if (parent_constructor == null){
2788                                 Report.Error (1501, loc,
2789                                        "Can not find a constructor for this argument list");
2790                                 return false;
2791                         }
2792                         
2793                         return true;
2794                 }
2795
2796                 public void Emit (EmitContext ec)
2797                 {
2798                         if (parent_constructor != null){
2799                                 ec.Mark (loc, false);
2800                                 if (ec.IsStatic)
2801                                         Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2802                                 else
2803                                         Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
2804                         }
2805                 }
2806         }
2807
2808         public class ConstructorBaseInitializer : ConstructorInitializer {
2809                 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2810                         base (argument_list, pars, l)
2811                 {
2812                 }
2813         }
2814
2815         public class ConstructorThisInitializer : ConstructorInitializer {
2816                 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2817                         base (argument_list, pars, l)
2818                 {
2819                 }
2820         }
2821         
2822         public class Constructor : MethodCore {
2823                 public ConstructorBuilder ConstructorBuilder;
2824                 public ConstructorInitializer Initializer;
2825
2826                 // <summary>
2827                 //   Modifiers allowed for a constructor.
2828                 // </summary>
2829                 public const int AllowedModifiers =
2830                         Modifiers.PUBLIC |
2831                         Modifiers.PROTECTED |
2832                         Modifiers.INTERNAL |
2833                         Modifiers.STATIC |
2834                         Modifiers.UNSAFE |
2835                         Modifiers.EXTERN |              
2836                         Modifiers.PRIVATE;
2837
2838                 //
2839                 // The spec claims that static is not permitted, but
2840                 // my very own code has static constructors.
2841                 //
2842                 public Constructor (DeclSpace ds, string name, Parameters args,
2843                                     ConstructorInitializer init, Location l)
2844                         : base (ds, null, 0, AllowedModifiers, name, null, args, l)
2845                 {
2846                         Initializer = init;
2847                 }
2848
2849                 //
2850                 // Returns true if this is a default constructor
2851                 //
2852                 public bool IsDefault ()
2853                 {
2854                         if ((ModFlags & Modifiers.STATIC) != 0)
2855                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2856                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2857                         
2858                         else
2859                                 return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2860                                         (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2861                                         (Initializer is ConstructorBaseInitializer) &&
2862                                         (Initializer.Arguments == null);
2863                 }
2864
2865                 //
2866                 // Creates the ConstructorBuilder
2867                 //
2868                 public override bool Define (TypeContainer container)
2869                 {
2870                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
2871                                                MethodAttributes.SpecialName);
2872
2873                         // Check if arguments were correct.
2874                         if (!DoDefineParameters ())
2875                                 return false;
2876
2877                         if ((ModFlags & Modifiers.STATIC) != 0){
2878                                 ca |= MethodAttributes.Static | MethodAttributes.Private;
2879                         } else {
2880                                 if (container is Struct && ParameterTypes.Length == 0){
2881                                         Report.Error (
2882                                                 568, Location, 
2883                                                 "Structs can not contain explicit parameterless " +
2884                                                 "constructors");
2885                                         return false;
2886                                 }
2887                                 ca |= MethodAttributes.HideBySig;
2888
2889                                 if ((ModFlags & Modifiers.PUBLIC) != 0)
2890                                         ca |= MethodAttributes.Public;
2891                                 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2892                                         if ((ModFlags & Modifiers.INTERNAL) != 0)
2893                                                 ca |= MethodAttributes.FamORAssem;
2894                                         else 
2895                                                 ca |= MethodAttributes.Family;
2896                                 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2897                                         ca |= MethodAttributes.Assembly;
2898                                 else if (IsDefault ())
2899                                         ca |= MethodAttributes.Public;
2900                                 else
2901                                         ca |= MethodAttributes.Private;
2902                         }
2903
2904                         ConstructorBuilder = container.TypeBuilder.DefineConstructor (
2905                                 ca, GetCallingConvention (container is Class), ParameterTypes);
2906
2907                         if ((ModFlags & Modifiers.UNSAFE) != 0)
2908                                 ConstructorBuilder.InitLocals = false;
2909                         
2910                         //
2911                         // HACK because System.Reflection.Emit is lame
2912                         //
2913                         if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2914                                 Report.Error (
2915                                         111, Location,
2916                                         "Class `" +container.Name+ "' already contains a definition with the " +
2917                                         "same return value and parameter types for constructor `" + Name
2918                                         + "'");
2919                                 return false;
2920                         }
2921
2922                         return true;
2923                 }
2924
2925                 //
2926                 // Emits the code
2927                 //
2928                 public void Emit (TypeContainer container)
2929                 {
2930                         ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2931                         EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
2932
2933                         //
2934                         // extern methods have no bodies
2935                         //
2936                         if ((ModFlags & Modifiers.EXTERN) != 0) {
2937                                 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
2938                                         Report.Error (
2939                                                 179, Location, "External constructor `" +
2940                                                 TypeManager.CSharpSignature (ConstructorBuilder) +
2941                                                 "' can not have a body");
2942                                         return;
2943                                 }
2944                         } else if (block == null) {
2945                                 Report.Error (
2946                                         501, Location, "Constructor `" +
2947                                         TypeManager.CSharpSignature (ConstructorBuilder) +
2948                                         "' must declare a body since it is not marked extern");
2949                                 return;
2950                         }
2951
2952                         if ((ModFlags & Modifiers.STATIC) == 0){
2953                                 if (container is Class && Initializer == null)
2954                                         Initializer = new ConstructorBaseInitializer (
2955                                                 null, Parameters.EmptyReadOnlyParameters, Location);
2956
2957
2958                                 //
2959                                 // Spec mandates that Initializers will not have
2960                                 // `this' access
2961                                 //
2962                                 ec.IsStatic = true;
2963                                 if (Initializer != null && !Initializer.Resolve (ec))
2964                                         return;
2965                                 ec.IsStatic = false;
2966                         }
2967
2968                         MethodCore.LabelParameters (ec, ConstructorBuilder,
2969                                                     Parameters, OptAttributes, Location);
2970                         
2971                         SymbolWriter sw = CodeGen.SymbolWriter;
2972                         bool generate_debugging = false;
2973
2974                         if ((sw != null) && (block != null) &&
2975                                 !Location.IsNull (Location) &&
2976                                 !Location.IsNull (block.EndLocation)) {
2977
2978                                 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
2979
2980                                 generate_debugging = true;
2981                         }
2982
2983                         //
2984                         // Classes can have base initializers and instance field initializers.
2985                         //
2986                         if (container is Class){
2987                                 if ((ModFlags & Modifiers.STATIC) == 0){
2988
2989                                         //
2990                                         // If we use a "this (...)" constructor initializer, then
2991                                         // do not emit field initializers, they are initialized in the other constructor
2992                                         //
2993                                         if (!(Initializer != null && Initializer is ConstructorThisInitializer))
2994                                                 container.EmitFieldInitializers (ec);
2995                                 }
2996                         }
2997                         if (Initializer != null)
2998                                 Initializer.Emit (ec);
2999                         
3000                         if ((ModFlags & Modifiers.STATIC) != 0)
3001                                 container.EmitFieldInitializers (ec);
3002
3003                         Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
3004
3005                         // If this is a non-static `struct' constructor and doesn't have any
3006                         // initializer, it must initialize all of the struct's fields.
3007                         if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
3008                                 Block.AddThisVariable (container, Location);
3009
3010                         ec.EmitTopBlock (block, ParameterInfo, Location);
3011
3012                         if (generate_debugging)
3013                                 sw.CloseMethod ();
3014
3015                         block = null;
3016                 }
3017         }
3018
3019         //
3020         // Encapsulates most of the Method's state
3021         //
3022         public class MethodData {
3023                 //
3024                 // The return type of this method
3025                 //
3026                 public readonly Type ReturnType;
3027                 public readonly Type[] ParameterTypes;
3028                 public readonly InternalParameters ParameterInfo;
3029                 public readonly CallingConventions CallingConventions;
3030                 public readonly Attributes OptAttributes;
3031                 public readonly Location Location;
3032
3033                 //
3034                 // Are we implementing an interface ?
3035                 //
3036                 public bool IsImplementing = false;
3037
3038                 //
3039                 // Protected data.
3040                 //
3041                 protected DeclSpace ds;
3042                 protected MemberBase member;
3043                 protected int modifiers;
3044                 protected MethodAttributes flags;
3045                 protected bool is_method;
3046                 protected string accessor_name;
3047
3048                 //
3049                 // It can either hold a string with the condition, or an arraylist of conditions.
3050                 object conditionals;
3051
3052                 MethodBuilder builder = null;
3053                 public MethodBuilder MethodBuilder {
3054                         get {
3055                                 return builder;
3056                         }
3057                 }
3058
3059                 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3060                                    Type [] parameter_types, InternalParameters parameters,
3061                                    CallingConventions cc, Attributes opt_attrs,
3062                                    int modifiers, MethodAttributes flags, bool is_method)
3063                 {
3064                         this.ds = ds;
3065                         this.member = member;
3066                         this.accessor_name = name;
3067                         this.ReturnType = return_type;
3068                         this.ParameterTypes = parameter_types;
3069                         this.ParameterInfo = parameters;
3070                         this.CallingConventions = cc;
3071                         this.OptAttributes = opt_attrs;
3072                         this.modifiers = modifiers;
3073                         this.flags = flags;
3074                         this.is_method = is_method;
3075                         this.Location = member.Location;
3076                         this.conditionals = null;
3077                 }
3078
3079                 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3080                                    Type [] parameter_types, InternalParameters parameters,
3081                                    CallingConventions cc, Attributes opt_attrs,
3082                                    int modifiers, MethodAttributes flags, bool is_method,
3083                                    MethodBuilder builder)
3084                         : this (ds, member, name, return_type, parameter_types, parameters,
3085                                 cc, opt_attrs, modifiers, flags, is_method)
3086                 {
3087                         this.builder = builder;
3088                 }
3089
3090                 //
3091                 // Attributes.
3092                 //
3093                 Attribute dllimport_attribute = null;
3094                 string obsolete = null;
3095                 bool obsolete_error = false;
3096
3097                 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
3098                 {
3099                         if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
3100                                 return true;
3101
3102                         foreach (AttributeSection asec in opt_attrs.AttributeSections) {
3103                                 if (asec.Attributes == null)
3104                                         continue;
3105                                         
3106                                 foreach (Attribute a in asec.Attributes) {
3107                                         if (a.Name == "Conditional") {
3108                                                 if (!ApplyConditionalAttribute (a))
3109                                                         return false;
3110                                         } else if (a.Name == "Obsolete") {
3111                                                 if (!ApplyObsoleteAttribute (a))
3112                                                         return false;
3113                                         } else if (a.Name.IndexOf ("DllImport") != -1) {
3114                                                 if (!is_method) {
3115                                                         a.Type = TypeManager.dllimport_type;
3116                                                         Attribute.Error_AttributeNotValidForElement (a, Location);
3117                                                         return false;
3118                                                 }
3119                                                 if (!ApplyDllImportAttribute (a))
3120                                                         return false;
3121                                         }
3122                                 }
3123                         }
3124
3125                         return true;
3126                 }
3127
3128                 //
3129                 // Applies the `DllImport' attribute to the method.
3130                 //
3131                 protected virtual bool ApplyDllImportAttribute (Attribute a)
3132                 {
3133                         const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3134                         if ((modifiers & extern_static) != extern_static) {
3135                                 Report.Error (601, Location,
3136                                               "The DllImport attribute must be specified on a method " +
3137                                               "marked `static' and `extern'.");
3138                                 return false;
3139                         }
3140
3141                         flags |= MethodAttributes.PinvokeImpl;
3142                         dllimport_attribute = a;
3143                         return true;
3144                 }
3145
3146                 //
3147                 // Applies the `Obsolete' attribute to the method.
3148                 //
3149                 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3150                 {
3151                         if (obsolete != null) {
3152                                 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
3153                                 return false;
3154                         }
3155
3156                         obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3157                         return obsolete != null;
3158                 }
3159
3160                 //
3161                 // Applies the `Conditional' attribute to the method.
3162                 //
3163                 protected virtual bool ApplyConditionalAttribute (Attribute a)
3164                 {
3165                         // The Conditional attribute is only valid on methods.
3166                         if (!is_method) {
3167                                 Attribute.Error_AttributeNotValidForElement (a, Location);
3168                                 return false;
3169                         }
3170
3171                         string condition = a.Conditional_GetConditionName ();
3172
3173                         if (condition == null)
3174                                 return false;
3175
3176                         if (ReturnType != TypeManager.void_type) {
3177                                 Report.Error (578, Location,
3178                                               "Conditional not valid on `" + member.Name + "' " +
3179                                               "because its return type is not void");
3180                                 return false;
3181                         }
3182
3183                         if ((modifiers & Modifiers.OVERRIDE) != 0) {
3184                                 Report.Error (243, Location,
3185                                               "Conditional not valid on `" + member.Name + "' " +
3186                                               "because it is an override method");
3187                                 return false;
3188                         }
3189
3190                         if (member.IsExplicitImpl) {
3191                                 Report.Error (577, Location,
3192                                               "Conditional not valid on `" + member.Name + "' " +
3193                                               "because it is an explicit interface implementation");
3194                                 return false;
3195                         }
3196
3197                         if (IsImplementing) {
3198                                 Report.Error (623, Location,
3199                                               "Conditional not valid on `" + member.Name + "' " +
3200                                               "because it is an interface method");
3201                                 return false;
3202                         }
3203
3204                         //
3205                         // The likelyhood that the conditional will be more than 1 is very slim
3206                         //
3207                         if (conditionals == null)
3208                                 conditionals = condition;
3209                         else if (conditionals is string){
3210                                 string s = (string) conditionals;
3211                                 conditionals = new ArrayList ();
3212                                 ((ArrayList)conditionals).Add (s);
3213                         } else
3214                                 ((ArrayList)conditionals).Add (condition);
3215
3216                         return true;
3217                 }
3218
3219                 //
3220                 // Checks whether this method should be ignored due to its Conditional attributes.
3221                 //
3222                 bool ShouldIgnore (Location loc)
3223                 {
3224                         // When we're overriding a virtual method, we implicitly inherit the
3225                         // Conditional attributes from our parent.
3226                         if (member.ParentMethod != null) {
3227                                 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3228                                         member.ParentMethod, loc);
3229
3230                                 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3231                                         return true;
3232                         }
3233
3234                         if (conditionals != null){
3235                                 if (conditionals is string){
3236                                         if (RootContext.AllDefines [conditionals] == null)
3237                                                 return true;
3238                                 } else {
3239                                         foreach (string condition in (ArrayList) conditionals)
3240                                         if (RootContext.AllDefines [condition] == null)
3241                                                 return true;
3242                                 }
3243                         }
3244                         return false;
3245                 }
3246
3247                 //
3248                 // Returns the TypeManager.MethodFlags for this method.
3249                 // This emits an error 619 / warning 618 if the method is obsolete.
3250                 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3251                 //
3252                 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3253                 {
3254                         TypeManager.MethodFlags flags = 0;
3255
3256                         if (obsolete != null) {
3257                                 if (obsolete_error) {
3258                                         Report.Error (619, loc, "Method `" + member.Name +
3259                                                       "' is obsolete: `" + obsolete + "'");
3260                                         return TypeManager.MethodFlags.IsObsoleteError;
3261                                 } else
3262                                         Report.Warning (618, loc, "Method `" + member.Name +
3263                                                         "' is obsolete: `" + obsolete + "'");
3264
3265                                 flags |= TypeManager.MethodFlags.IsObsolete;
3266                         }
3267
3268                         if (ShouldIgnore (loc))
3269                                 flags |= TypeManager.MethodFlags.ShouldIgnore;
3270
3271                         return flags;
3272                 }
3273
3274                 public virtual bool Define (TypeContainer container)
3275                 {
3276                         MethodInfo implementing = null;
3277                         string method_name, name, prefix;
3278
3279                         if (OptAttributes != null)
3280                                 if (!ApplyAttributes (OptAttributes, is_method))
3281                                         return false;
3282
3283                         if (member.IsExplicitImpl)
3284                                 prefix = member.InterfaceType.FullName + ".";
3285                         else
3286                                 prefix = "";
3287
3288                         if (accessor_name != null)
3289                                 name = accessor_name + "_" + member.ShortName;
3290                         else
3291                                 name = member.ShortName;
3292                         method_name = prefix + name;
3293
3294                         if (container.Pending != null){
3295                                 if (member is Indexer)
3296                                         implementing = container.Pending.IsInterfaceIndexer (
3297                                                 member.InterfaceType, ReturnType, ParameterTypes);
3298                                 else
3299                                         implementing = container.Pending.IsInterfaceMethod (
3300                                                 member.InterfaceType, name, ReturnType, ParameterTypes);
3301
3302                                 if (member.InterfaceType != null && implementing == null){
3303                                         Report.Error (539, Location, "'{0}' in explicit interface declaration is not an interface", method_name);
3304                                         return false;
3305                                 }
3306                         }
3307
3308                         //
3309                         // For implicit implementations, make sure we are public, for
3310                         // explicit implementations, make sure we are private.
3311                         //
3312                         if (implementing != null){
3313                                 //
3314                                 // Setting null inside this block will trigger a more
3315                                 // verbose error reporting for missing interface implementations
3316                                 //
3317                                 // The "candidate" function has been flagged already
3318                                 // but it wont get cleared
3319                                 //
3320                                 if (member.IsExplicitImpl){
3321                                         if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3322                                                 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3323                                                 implementing = null;
3324                                         }
3325                                 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3326                                         if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3327                                                 //
3328                                                 // If this is an interface method implementation,
3329                                                 // check for public accessibility
3330                                                 //
3331                                                 implementing = null;
3332                                         } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3333                                                 // We may never be private.
3334                                                 implementing = null;
3335                                         } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3336                                                 //
3337                                                 // We may be protected if we're overriding something.
3338                                                 //
3339                                                 implementing = null;
3340                                         }
3341                                 } 
3342                                         
3343                                 //
3344                                 // Static is not allowed
3345                                 //
3346                                 if ((modifiers & Modifiers.STATIC) != 0){
3347                                         implementing = null;
3348                                         Modifiers.Error_InvalidModifier (Location, "static");
3349                                 }
3350                         }
3351                         
3352                         //
3353                         // If implementing is still valid, set flags
3354                         //
3355                         if (implementing != null){
3356                                 //
3357                                 // When implementing interface methods, set NewSlot
3358                                 // unless, we are overwriting a method.
3359                                 //
3360                                 if (implementing.DeclaringType.IsInterface){
3361                                         if ((modifiers & Modifiers.OVERRIDE) == 0)
3362                                                 flags |= MethodAttributes.NewSlot;
3363                                 }
3364                                 flags |=
3365                                         MethodAttributes.Virtual |
3366                                         MethodAttributes.HideBySig;
3367
3368                                 // Set Final unless we're virtual, abstract or already overriding a method.
3369                                 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3370                                         flags |= MethodAttributes.Final;
3371
3372                                 // Get the method name from the explicit interface.
3373                                 if (member.InterfaceType != null) {
3374                                         name = implementing.Name;
3375                                         method_name = prefix + name;
3376                                 }
3377
3378                                 IsImplementing = true;
3379                         }
3380
3381                         //
3382                         // Create the MethodBuilder for the method
3383                         //
3384                         if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3385                                 if ((modifiers & Modifiers.STATIC) == 0) {
3386                                         Report.Error (601, Location,
3387                                                       "The DllImport attribute must be specified on " +
3388                                                       "a method marked 'static' and 'extern'.");
3389                                         return false;
3390                                 }
3391                                 
3392                                 EmitContext ec = new EmitContext (
3393                                         container, ds, Location, null, ReturnType, modifiers, false);
3394                                 
3395                                 builder = dllimport_attribute.DefinePInvokeMethod (
3396                                         ec, container.TypeBuilder, method_name, flags,
3397                                         ReturnType, ParameterTypes);
3398                         } else if (builder == null)
3399                                 builder = container.TypeBuilder.DefineMethod (
3400                                         method_name, flags, CallingConventions,
3401                                         ReturnType, ParameterTypes);
3402                         else
3403                                 builder.SetGenericMethodSignature (
3404                                         flags, CallingConventions,
3405                                         ReturnType, ParameterTypes);
3406
3407                         if (builder == null)
3408                                 return false;
3409
3410                         if ((modifiers & Modifiers.UNSAFE) != 0)
3411                                 builder.InitLocals = false;
3412
3413                         if (IsImplementing){
3414                                 //
3415                                 // clear the pending implemntation flag
3416                                 //
3417                                 if (member is Indexer) {
3418                                         container.Pending.ImplementIndexer (
3419                                                 member.InterfaceType, builder, ReturnType,
3420                                                 ParameterTypes, true);
3421                                 } else
3422                                         container.Pending.ImplementMethod (
3423                                                 member.InterfaceType, name, ReturnType,
3424                                                 ParameterTypes, member.IsExplicitImpl);
3425
3426                                 if (member.IsExplicitImpl)
3427                                         container.TypeBuilder.DefineMethodOverride (
3428                                                 builder, implementing);
3429
3430                         }
3431
3432                         if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3433                                 Report.Error (111, Location,
3434                                               "Class `" + container.Name +
3435                                               "' already contains a definition with the " +
3436                                               "same return value and parameter types as the " +
3437                                               "'get' method of property `" + member.Name + "'");
3438                                 return false;
3439                         }
3440
3441                         TypeManager.AddMethod (builder, this);
3442
3443                         return true;
3444                 }
3445
3446                 //
3447                 // Emits the code
3448                 // 
3449                 public virtual void Emit (TypeContainer container, Block block, object kind)
3450                 {
3451                         ILGenerator ig;
3452                         EmitContext ec;
3453
3454                         if ((flags & MethodAttributes.PinvokeImpl) == 0)
3455                                 ig = builder.GetILGenerator ();
3456                         else
3457                                 ig = null;
3458
3459                         ec = new EmitContext (container, ds, Location, ig, ReturnType, modifiers, false);
3460
3461                         if (OptAttributes != null)
3462                                 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3463
3464                         if (member is MethodCore)
3465                                 MethodCore.LabelParameters (ec, MethodBuilder,
3466                                                             ((MethodCore) member).Parameters,
3467                                                             OptAttributes,
3468                                                             Location);
3469                         
3470                         //
3471                         // abstract or extern methods have no bodies
3472                         //
3473                         if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3474                                 if (block == null) {
3475                                         SymbolWriter sw = CodeGen.SymbolWriter;
3476
3477                                         if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0)) {
3478                                                 sw.OpenMethod (container, MethodBuilder, Location, Location);
3479                                                 sw.CloseMethod ();
3480                                         }
3481
3482                                         return;
3483                                 }
3484
3485                                 //
3486                                 // abstract or extern methods have no bodies.
3487                                 //
3488                                 if ((modifiers & Modifiers.ABSTRACT) != 0)
3489                                         Report.Error (
3490                                                 500, Location, "Abstract method `" +
3491                                                 TypeManager.CSharpSignature (builder) +
3492                                                 "' can not have a body");
3493
3494                                 if ((modifiers & Modifiers.EXTERN) != 0)
3495                                         Report.Error (
3496                                                 179, Location, "External method `" +
3497                                                 TypeManager.CSharpSignature (builder) +
3498                                                 "' can not have a body");
3499
3500                                 return;
3501                         }
3502
3503                         //
3504                         // Methods must have a body unless they're extern or abstract
3505                         //
3506                         if (block == null) {
3507                                 Report.Error (
3508                                         501, Location, "Method `" +
3509                                         TypeManager.CSharpSignature (builder) +
3510                                         "' must declare a body since it is not marked " +
3511                                         "abstract or extern");
3512                                 return;
3513                         }
3514
3515                         //
3516                         // Handle destructors specially
3517                         //
3518                         // FIXME: This code generates buggy code
3519                         //
3520                         if (member is Destructor)
3521                                 EmitDestructor (ec, block);
3522                         else {
3523                                 SymbolWriter sw = CodeGen.SymbolWriter;
3524
3525                                 if ((sw != null) && !Location.IsNull (Location) &&
3526                                     !Location.IsNull (block.EndLocation)) {
3527                                         sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
3528
3529                                         ec.EmitTopBlock (block, ParameterInfo, Location);
3530
3531                                         sw.CloseMethod ();
3532                                 } else
3533                                         ec.EmitTopBlock (block, ParameterInfo, Location);
3534                         }
3535                 }
3536
3537                 void EmitDestructor (EmitContext ec, Block block)
3538                 {
3539                         ILGenerator ig = ec.ig;
3540                         
3541                         Label finish = ig.DefineLabel ();
3542
3543                         block.SetDestructor ();
3544                         
3545                         ig.BeginExceptionBlock ();
3546                         ec.ReturnLabel = finish;
3547                         ec.HasReturnLabel = true;
3548                         ec.EmitTopBlock (block, null, Location);
3549                         
3550                         // ig.MarkLabel (finish);
3551                         ig.BeginFinallyBlock ();
3552                         
3553                         if (ec.ContainerType.BaseType != null) {
3554                                 Expression member_lookup = Expression.MemberLookup (
3555                                         ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3556                                         "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
3557
3558                                 if (member_lookup != null){
3559                                         MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3560                                 
3561                                         ig.Emit (OpCodes.Ldarg_0);
3562                                         ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3563                                 }
3564                         }
3565                         
3566                         ig.EndExceptionBlock ();
3567                         //ig.MarkLabel (ec.ReturnLabel);
3568                         ig.Emit (OpCodes.Ret);
3569                 }
3570         }
3571
3572         public class Destructor : Method {
3573
3574                 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
3575                                    Parameters parameters, Attributes attrs, Location l)
3576                         : base (ds, return_type, mod, name, parameters, attrs, l)
3577                 { }
3578
3579         }
3580         
3581         abstract public class MemberBase : MemberCore {
3582                 public Expression Type;
3583
3584                 protected MethodAttributes flags;
3585
3586                 protected readonly int explicit_mod_flags;
3587
3588                 //
3589                 // The "short" name of this property / indexer / event.  This is the
3590                 // name without the explicit interface.
3591                 //
3592                 public string ShortName;
3593
3594                 //
3595                 // The type of this property / indexer / event
3596                 //
3597                 public Type MemberType;
3598
3599                 //
3600                 // If true, this is an explicit interface implementation
3601                 //
3602                 public bool IsExplicitImpl = false;
3603
3604                 //
3605                 // The name of the interface we are explicitly implementing
3606                 //
3607                 public string ExplicitInterfaceName = null;
3608
3609                 //
3610                 // If true, the interface type we are explicitly implementing
3611                 //
3612                 public Type InterfaceType = null;
3613
3614                 //
3615                 // The method we're overriding if this is an override method.
3616                 //
3617                 protected MethodInfo parent_method = null;
3618                 public MethodInfo ParentMethod {
3619                         get {
3620                                 return parent_method;
3621                         }
3622                 }
3623
3624                 //
3625                 // The constructor is only exposed to our children
3626                 //
3627                 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod, string name,
3628                                       Attributes attrs, Location loc)
3629                         : base (name, attrs, loc)
3630                 {
3631                         explicit_mod_flags = mod;
3632                         Type = type;
3633                         ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
3634                 }
3635
3636                 protected virtual bool CheckBase (TypeContainer container)
3637                 {
3638                         if ((container is Struct) || (RootContext.WarningLevel > 3)){
3639                                 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
3640                                         if (container is Struct){
3641                                                 Report.Error (666, Location, "Protected member in struct declaration");
3642                                                 return false;
3643                                         } else
3644                                                 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
3645                                 }
3646                         }
3647                         return true;
3648                 }
3649
3650                 protected void WarningNotHiding (TypeContainer parent)
3651                 {
3652                         Report.Warning (
3653                                 109, Location,
3654                                 "The member " + parent.MakeName (Name) + " does not hide an " +
3655                                 "inherited member.  The keyword new is not required");
3656                                                            
3657                 }
3658
3659                 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
3660                                                         string name)
3661                 {
3662                         //
3663                         // FIXME: report the old/new permissions?
3664                         //
3665                         Report.Error (
3666                                 507, Location, parent.MakeName (Name) +
3667                                 ": can't change the access modifiers when overriding inherited " +
3668                                 "member `" + name + "'");
3669                 }
3670                 
3671                 //
3672                 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3673                 // that have been defined.
3674                 //
3675                 // `name' is the user visible name for reporting errors (this is used to
3676                 // provide the right name regarding method names and properties)
3677                 //
3678                 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
3679                                                        MethodInfo mb, string name)
3680                 {
3681                         bool ok = true;
3682                         
3683                         if ((ModFlags & Modifiers.OVERRIDE) != 0){
3684                                 if (!(mb.IsAbstract || mb.IsVirtual)){
3685                                         Report.Error (
3686                                                 506, Location, parent.MakeName (Name) +
3687                                                 ": cannot override inherited member `" +
3688                                                 name + "' because it is not " +
3689                                                 "virtual, abstract or override");
3690                                         ok = false;
3691                                 }
3692                                 
3693                                 // Now we check that the overriden method is not final
3694                                 
3695                                 if (mb.IsFinal) {
3696                                         // This happens when implementing interface methods.
3697                                         if (mb.IsHideBySig && mb.IsVirtual) {
3698                                                 Report.Error (
3699                                                         506, Location, parent.MakeName (Name) +
3700                                                         ": cannot override inherited member `" +
3701                                                         name + "' because it is not " +
3702                                                         "virtual, abstract or override");
3703                                         } else
3704                                                 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
3705                                                               "override inherited member `" + name +
3706                                                               "' because it is sealed.");
3707                                         ok = false;
3708                                 }
3709                                 //
3710                                 // Check that the permissions are not being changed
3711                                 //
3712                                 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
3713                                 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
3714
3715                                 //
3716                                 // special case for "protected internal"
3717                                 //
3718
3719                                 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3720                                         //
3721                                         // when overriding protected internal, the method can be declared
3722                                         // protected internal only within the same assembly
3723                                         //
3724
3725                                         if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3726                                                 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
3727                                                         //
3728                                                         // assemblies differ - report an error
3729                                                         //
3730                                                         
3731                                                         Error_CannotChangeAccessModifiers (parent, mb, name);
3732                                                     ok = false;
3733                                                 } else if (thisp != parentp) {
3734                                                         //
3735                                                         // same assembly, but other attributes differ - report an error
3736                                                         //
3737                                                         
3738                                                         Error_CannotChangeAccessModifiers (parent, mb, name);
3739                                                         ok = false;
3740                                                 };
3741                                         } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3742                                                 //
3743                                                 // if it's not "protected internal", it must be "protected"
3744                                                 //
3745
3746                                                 Error_CannotChangeAccessModifiers (parent, mb, name);
3747                                                 ok = false;
3748                                         } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
3749                                                 //
3750                                                 // protected within the same assembly - an error
3751                                                 //
3752                                                 Error_CannotChangeAccessModifiers (parent, mb, name);
3753                                                 ok = false;
3754                                         } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) != 
3755                                                    (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3756                                                 //
3757                                                 // protected ok, but other attributes differ - report an error
3758                                                 //
3759                                                 Error_CannotChangeAccessModifiers (parent, mb, name);
3760                                                 ok = false;
3761                                         }
3762                                 } else {
3763                                         if (thisp != parentp){
3764                                                 Error_CannotChangeAccessModifiers (parent, mb, name);
3765                                                 ok = false;
3766                                         }
3767                                 }
3768                         }
3769
3770                         if (mb.IsVirtual || mb.IsAbstract){
3771                                 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3772                                         if (Name != "Finalize"){
3773                                                 Report.Warning (
3774                                                         114, 2, Location, parent.MakeName (Name) + 
3775                                                         " hides inherited member `" + name +
3776                                                         "'.  To make the current member override that " +
3777                                                         "implementation, add the override keyword, " +
3778                                                         "otherwise use the new keyword");
3779                                                 ModFlags |= Modifiers.NEW;
3780                                         }
3781                                 }
3782                         } else {
3783                                 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3784                                         if (Name != "Finalize"){
3785                                                 Report.Warning (
3786                                                         108, 1, Location, "The keyword new is required on " +
3787                                                         parent.MakeName (Name) + " because it hides " +
3788                                                         "inherited member `" + name + "'");
3789                                                 ModFlags |= Modifiers.NEW;
3790                                         }
3791                                 }
3792                         }
3793
3794                         return ok;
3795                 }
3796
3797                 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
3798                 {
3799                         bool error = false;
3800
3801                         foreach (Type partype in parameters){
3802                                 if (partype.IsPointer){
3803                                         if (!UnsafeOK (ds))
3804                                                 error = true;
3805                                         if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
3806                                                 error = true;
3807                                 }
3808
3809                                 if (ds.AsAccessible (partype, ModFlags))
3810                                         continue;
3811
3812                                 if (this is Indexer)
3813                                         Report.Error (55, Location,
3814                                                       "Inconsistent accessibility: parameter type `" +
3815                                                       TypeManager.CSharpName (partype) + "' is less " +
3816                                                       "accessible than indexer `" + Name + "'");
3817                                 else if ((this is Method) && ((Method) this).IsOperator)
3818                                         Report.Error (57, Location,
3819                                                       "Inconsistent accessibility: parameter type `" +
3820                                                       TypeManager.CSharpName (partype) + "' is less " +
3821                                                       "accessible than operator `" + Name + "'");
3822                                 else
3823                                         Report.Error (51, Location,
3824                                                       "Inconsistent accessibility: parameter type `" +
3825                                                       TypeManager.CSharpName (partype) + "' is less " +
3826                                                       "accessible than method `" + Name + "'");
3827                                 error = true;
3828                         }
3829
3830                         return !error;
3831                 }
3832
3833                 protected virtual bool DoDefine (DeclSpace decl, TypeContainer container)
3834                 {
3835                         if (Name == null)
3836                                 Name = "this";
3837
3838                         if (!container.MethodModifiersValid (ModFlags, Name, Location))
3839                                 return false;
3840
3841                         flags = Modifiers.MethodAttr (ModFlags);
3842
3843                         // Lookup Type, verify validity
3844                         MemberType = decl.ResolveType (Type, false, Location);
3845                         if (MemberType == null)
3846                                 return false;
3847
3848                         if ((container.ModFlags & Modifiers.SEALED) != 0){
3849                                 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
3850                                         Report.Error (549, Location, "Virtual method can not be contained in sealed class");
3851                                         return false;
3852                                 }
3853                         }
3854                         
3855                         // verify accessibility
3856                         if (!container.AsAccessible (MemberType, ModFlags)) {
3857                                 if (this is Property)
3858                                         Report.Error (53, Location,
3859                                                       "Inconsistent accessibility: property type `" +
3860                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3861                                                       "accessible than property `" + Name + "'");
3862                                 else if (this is Indexer)
3863                                         Report.Error (54, Location,
3864                                                       "Inconsistent accessibility: indexer return type `" +
3865                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3866                                                       "accessible than indexer `" + Name + "'");
3867                                 else if (this is Method) {
3868                                         if (((Method) this).IsOperator)
3869                                                 Report.Error (56, Location,
3870                                                               "Inconsistent accessibility: return type `" +
3871                                                               TypeManager.CSharpName (MemberType) + "' is less " +
3872                                                               "accessible than operator `" + Name + "'");
3873                                         else
3874                                                 Report.Error (50, Location,
3875                                                               "Inconsistent accessibility: return type `" +
3876                                                               TypeManager.CSharpName (MemberType) + "' is less " +
3877                                                               "accessible than method `" + Name + "'");
3878                                 } else
3879                                         Report.Error (52, Location,
3880                                                       "Inconsistent accessibility: field type `" +
3881                                                       TypeManager.CSharpName (MemberType) + "' is less " +
3882                                                       "accessible than field `" + Name + "'");
3883                                 return false;
3884                         }
3885
3886                         if (MemberType.IsPointer && !UnsafeOK (container))
3887                                 return false;
3888                         
3889                         //
3890                         // Check for explicit interface implementation
3891                         //
3892                         if ((ExplicitInterfaceName == null) && (Name.IndexOf ('.') != -1)){
3893                                 int pos = Name.LastIndexOf ('.');
3894
3895                                 ExplicitInterfaceName = Name.Substring (0, pos);
3896                                 ShortName = Name.Substring (pos + 1);
3897                         } else
3898                                 ShortName = Name;
3899
3900                         if (ExplicitInterfaceName != null) {
3901                                 InterfaceType  = RootContext.LookupType (
3902                                         container, ExplicitInterfaceName, false, Location);
3903                                 if (InterfaceType == null)
3904                                         return false;
3905
3906                                 if (InterfaceType.IsClass) {
3907                                         Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
3908                                         return false;
3909                                 }
3910
3911                                 // Compute the full name that we need to export.
3912                                 Name = InterfaceType.FullName + "." + ShortName;
3913                                 
3914                                 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
3915                                         return false;
3916                                 
3917                                 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
3918                                 
3919                                 IsExplicitImpl = true;
3920                         } else
3921                                 IsExplicitImpl = false;
3922
3923                         return true;
3924                 }
3925         }
3926
3927         //
3928         // Fields and Events both generate FieldBuilders, we use this to share 
3929         // their common bits.  This is also used to flag usage of the field
3930         //
3931         abstract public class FieldBase : MemberBase {
3932                 public FieldBuilder  FieldBuilder;
3933                 public Status status;
3934
3935                 [Flags]
3936                 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3937
3938                 //
3939                 // The constructor is only exposed to our children
3940                 //
3941                 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3942                                      object init, Attributes attrs, Location loc)
3943                         : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
3944                 {
3945                         this.init = init;
3946                 }
3947
3948                 //
3949                 // Whether this field has an initializer.
3950                 //
3951                 public bool HasInitializer {
3952                         get {
3953                                 return init != null;
3954                         }
3955                 }
3956
3957                 protected readonly Object init;
3958                 // Private.
3959                 Expression init_expr;
3960                 bool init_expr_initialized = false;
3961
3962                 //
3963                 // Resolves and returns the field initializer.
3964                 //
3965                 public Expression GetInitializerExpression (EmitContext ec)
3966                 {
3967                         if (init_expr_initialized)
3968                                 return init_expr;
3969
3970                         Expression e;
3971                         if (init is Expression)
3972                                 e = (Expression) init;
3973                         else
3974                                 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3975
3976                         ec.IsFieldInitializer = true;
3977                         e = e.DoResolve (ec);
3978                         ec.IsFieldInitializer = false;
3979
3980                         init_expr = e;
3981                         init_expr_initialized = true;
3982
3983                         return init_expr;
3984                 }
3985
3986                 public void SetAssigned ()
3987                 {
3988                         status |= Status.ASSIGNED;
3989                 }
3990         }
3991
3992         //
3993         // The Field class is used to represents class/struct fields during parsing.
3994         //
3995         public class Field : FieldBase {
3996                 // <summary>
3997                 //   Modifiers allowed in a class declaration
3998                 // </summary>
3999                 const int AllowedModifiers =
4000                         Modifiers.NEW |
4001                         Modifiers.PUBLIC |
4002                         Modifiers.PROTECTED |
4003                         Modifiers.INTERNAL |
4004                         Modifiers.PRIVATE |
4005                         Modifiers.STATIC |
4006                         Modifiers.VOLATILE |
4007                         Modifiers.UNSAFE |
4008                         Modifiers.READONLY;
4009
4010                 public Field (Expression type, int mod, string name, Object expr_or_array_init,
4011                               Attributes attrs, Location loc)
4012                         : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
4013                 {
4014                 }
4015
4016                 public override bool Define (TypeContainer container)
4017                 {
4018                         Type t = container.ResolveType (Type, false, Location);
4019                         
4020                         if (t == null)
4021                                 return false;
4022
4023                         CheckBase (container);
4024                         
4025                         if (!container.AsAccessible (t, ModFlags)) {
4026                                 Report.Error (52, Location,
4027                                               "Inconsistent accessibility: field type `" +
4028                                               TypeManager.CSharpName (t) + "' is less " +
4029                                               "accessible than field `" + Name + "'");
4030                                 return false;
4031                         }
4032
4033                         if (t.IsPointer && !UnsafeOK (container))
4034                                 return false;
4035                         
4036                         if (RootContext.WarningLevel > 1){
4037                                 Type ptype = container.TypeBuilder.BaseType;
4038
4039                                 // ptype is only null for System.Object while compiling corlib.
4040                                 if (ptype != null){
4041                                         TypeContainer.FindMembers (
4042                                                 ptype, MemberTypes.Method,
4043                                                 BindingFlags.Public |
4044                                                 BindingFlags.Static | BindingFlags.Instance,
4045                                                 System.Type.FilterName, Name);
4046                                 }
4047                         }
4048
4049                         if ((ModFlags & Modifiers.VOLATILE) != 0){
4050                                 if (!t.IsClass){
4051                                         Type vt = t;
4052                                         
4053                                         if (TypeManager.IsEnumType (vt))
4054                                                 vt = TypeManager.EnumToUnderlying (t);
4055
4056                                         if (!((vt == TypeManager.bool_type) ||
4057                                               (vt == TypeManager.sbyte_type) ||
4058                                               (vt == TypeManager.byte_type) ||
4059                                               (vt == TypeManager.short_type) ||    
4060                                               (vt == TypeManager.ushort_type) ||
4061                                               (vt == TypeManager.int32_type) ||    
4062                                               (vt == TypeManager.uint32_type) ||    
4063                                               (vt == TypeManager.char_type) ||    
4064                                               (vt == TypeManager.float_type))){
4065                                                 Report.Error (
4066                                                         677, Location, container.MakeName (Name) +
4067                                                         " A volatile field can not be of type `" +
4068                                                         TypeManager.CSharpName (vt) + "'");
4069                                                 return false;
4070                                         }
4071                                 }
4072
4073                                 if ((ModFlags & Modifiers.READONLY) != 0){
4074                                         Report.Error (
4075                                                       678, Location,
4076                                                       "A field can not be both volatile and readonly");
4077                                         return false;
4078                                 }
4079                         }
4080
4081                         FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4082
4083                         if (container is Struct && 
4084                             ((fa & FieldAttributes.Static) == 0) &&
4085                             t == container.TypeBuilder &&
4086                             !TypeManager.IsBuiltinType (t)){
4087                                 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name + 
4088                                               "' causes a cycle in the structure layout");
4089                                 return false;
4090                         }
4091
4092                         try {
4093                         FieldBuilder = container.TypeBuilder.DefineField (
4094                                 Name, t, Modifiers.FieldAttr (ModFlags));
4095
4096                         TypeManager.RegisterFieldBase (FieldBuilder, this);
4097                         }
4098                         catch (ArgumentException) {
4099                                 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
4100                                 return false;
4101                         }
4102
4103                         return true;
4104                 }
4105
4106                 public void Emit (TypeContainer tc)
4107                 {
4108                         EmitContext ec = new EmitContext (tc, Location, null,
4109                                                           FieldBuilder.FieldType, ModFlags);
4110
4111                         Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
4112                 }
4113         }
4114
4115         //
4116         // `set' and `get' accessors are represented with an Accessor.
4117         // 
4118         public class Accessor {
4119                 //
4120                 // Null if the accessor is empty, or a Block if not
4121                 //
4122                 public Block Block;
4123                 public Attributes OptAttributes;
4124                 
4125                 public Accessor (Block b, Attributes attrs)
4126                 {
4127                         Block = b;
4128                         OptAttributes = attrs;
4129                 }
4130         }
4131
4132         //
4133         // Properties and Indexers both generate PropertyBuilders, we use this to share 
4134         // their common bits.
4135         //
4136         abstract public class PropertyBase : MethodCore {
4137                 public Accessor Get, Set;
4138                 public PropertyBuilder PropertyBuilder;
4139                 public MethodBuilder GetBuilder, SetBuilder;
4140                 public MethodData GetData, SetData;
4141
4142                 protected EmitContext ec;
4143
4144                 public PropertyBase (DeclSpace ds, Expression type, string name, int mod_flags,
4145                                      int allowed_mod, Parameters parameters,
4146                                      Accessor get_block, Accessor set_block,
4147                                      Attributes attrs, Location loc)
4148                         : base (ds, type, mod_flags, allowed_mod, name, attrs, parameters, loc)
4149                 {
4150                         Get = get_block;
4151                         Set = set_block;
4152                 }
4153
4154                 protected override bool DoDefine (DeclSpace decl, TypeContainer container)
4155                 {
4156                         if (!base.DoDefine (decl, container))
4157                                 return false;
4158
4159                         ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4160
4161                         return true;
4162                 }
4163
4164                 //
4165                 // Checks our base implementation if any
4166                 //
4167                 protected override bool CheckBase (TypeContainer container)
4168                 {
4169                         base.CheckBase (container);
4170                         
4171                         // Check whether arguments were correct.
4172                         if (!DoDefineParameters ())
4173                                 return false;
4174
4175                         if (IsExplicitImpl)
4176                                 return true;
4177
4178                         string report_name;
4179                         MethodSignature ms, base_ms;
4180                         if (this is Indexer) {
4181                                 string name, base_name;
4182
4183                                 report_name = "this";
4184                                 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
4185                                 ms = new MethodSignature (name, null, ParameterTypes);
4186                                 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
4187                                 base_ms = new MethodSignature (base_name, null, ParameterTypes);
4188                         } else {
4189                                 report_name = Name;
4190                                 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
4191                         }
4192
4193                         //
4194                         // Verify if the parent has a type with the same name, and then
4195                         // check whether we have to create a new slot for it or not.
4196                         //
4197                         Type ptype = container.TypeBuilder.BaseType;
4198
4199                         // ptype is only null for System.Object while compiling corlib.
4200                         if (ptype == null) {
4201                                 if ((ModFlags & Modifiers.NEW) != 0)
4202                                         WarningNotHiding (container);
4203
4204                                 return true;
4205                         }
4206
4207                         MemberList props_this;
4208
4209                         props_this = TypeContainer.FindMembers (
4210                                 container.TypeBuilder, MemberTypes.Property,
4211                                 BindingFlags.NonPublic | BindingFlags.Public |
4212                                 BindingFlags.Static | BindingFlags.Instance |
4213                                 BindingFlags.DeclaredOnly,
4214                                 MethodSignature.method_signature_filter, ms);
4215
4216                         if (props_this.Count > 0) {
4217                                 Report.Error (111, Location, "Class `" + container.Name + "' " +
4218                                               "already defines a member called `" + report_name + "' " +
4219                                               "with the same parameter types");
4220                                 return false;
4221                         }
4222
4223                         MemberList mi_props;
4224
4225                         mi_props = TypeContainer.FindMembers (
4226                                 ptype, MemberTypes.Property,
4227                                 BindingFlags.NonPublic | BindingFlags.Public |
4228                                 BindingFlags.Instance | BindingFlags.Static,
4229                                 MethodSignature.inheritable_method_signature_filter, base_ms);
4230
4231                         if (mi_props.Count > 0){
4232                                 PropertyInfo parent_property = (PropertyInfo) mi_props [0];
4233                                 string name = parent_property.DeclaringType.Name + "." +
4234                                         parent_property.Name;
4235
4236                                 MethodInfo get, set, parent_method;
4237                                 get = parent_property.GetGetMethod (true);
4238                                 set = parent_property.GetSetMethod (true);
4239
4240                                 if (get != null)
4241                                         parent_method = get;
4242                                 else if (set != null)
4243                                         parent_method = set;
4244                                 else
4245                                         throw new Exception ("Internal error!");
4246
4247                                 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
4248                                         return false;
4249
4250                                 if ((ModFlags & Modifiers.NEW) == 0) {
4251                                         Type parent_type = TypeManager.TypeToCoreType (
4252                                                 parent_property.PropertyType);
4253
4254                                         if (parent_type != MemberType) {
4255                                                 Report.Error (
4256                                                         508, Location, container.MakeName (Name) + ": cannot " +
4257                                                         "change return type when overriding " +
4258                                                         "inherited member " + name);
4259                                                 return false;
4260                                         }
4261                                 }
4262                         } else {
4263                                 if ((ModFlags & Modifiers.NEW) != 0)
4264                                         WarningNotHiding (container);
4265
4266                                 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4267                                         if (this is Indexer)
4268                                                 Report.Error (115, Location,
4269                                                               container.MakeName (Name) +
4270                                                               " no suitable indexers found to override");
4271                                         else
4272                                                 Report.Error (115, Location,
4273                                                               container.MakeName (Name) +
4274                                                               " no suitable properties found to override");
4275                                         return false;
4276                                 }
4277                         }
4278                         return true;
4279                 }
4280
4281                 public void Emit (TypeContainer tc)
4282                 {
4283                         //
4284                         // The PropertyBuilder can be null for explicit implementations, in that
4285                         // case, we do not actually emit the ".property", so there is nowhere to
4286                         // put the attribute
4287                         //
4288                         if (PropertyBuilder != null)
4289                                 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
4290
4291                         if (GetData != null) {
4292                                 GetData.Emit (tc, Get.Block, Get);
4293                                 Get.Block = null;
4294                         }
4295
4296                         if (SetData != null) {
4297                                 SetData.Emit (tc, Set.Block, Set);
4298                                 Set.Block = null;
4299                         }
4300                 }
4301         }
4302                         
4303         public class Property : PropertyBase {
4304                 const int AllowedModifiers =
4305                         Modifiers.NEW |
4306                         Modifiers.PUBLIC |
4307                         Modifiers.PROTECTED |
4308                         Modifiers.INTERNAL |
4309                         Modifiers.PRIVATE |
4310                         Modifiers.STATIC |
4311                         Modifiers.SEALED |
4312                         Modifiers.OVERRIDE |
4313                         Modifiers.ABSTRACT |
4314                         Modifiers.UNSAFE |
4315                         Modifiers.EXTERN |
4316                         Modifiers.VIRTUAL;
4317
4318                 public Property (DeclSpace ds, Expression type, string name, int mod_flags,
4319                                  Accessor get_block, Accessor set_block,
4320                                  Attributes attrs, Location loc)
4321                         : base (ds, type, name, mod_flags, AllowedModifiers,
4322                                 Parameters.EmptyReadOnlyParameters,
4323                                 get_block, set_block, attrs, loc)
4324                 {
4325                 }
4326
4327                 public override bool Define (TypeContainer container)
4328                 {
4329                         if (!DoDefine (container, container))
4330                                 return false;
4331
4332                         if (!CheckBase (container))
4333                                 return false;
4334
4335                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4336
4337                         if (Get != null) {
4338                                 Type [] parameters = TypeManager.NoTypes;
4339
4340                                 InternalParameters ip = new InternalParameters (
4341                                         container, Parameters.EmptyReadOnlyParameters);
4342
4343                                 GetData = new MethodData (container, this, "get", MemberType,
4344                                                           parameters, ip, CallingConventions.Standard,
4345                                                           Get.OptAttributes, ModFlags, flags, false);
4346
4347                                 if (!GetData.Define (container))
4348                                         return false;
4349
4350                                 GetBuilder = GetData.MethodBuilder;
4351                         }
4352
4353                         if (Set != null) {
4354                                 Type [] parameters = new Type [1];
4355                                 parameters [0] = MemberType;
4356
4357                                 Parameter [] parms = new Parameter [1];
4358                                 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4359                                 InternalParameters ip = new InternalParameters (
4360                                         container, new Parameters (parms, null, Location));
4361
4362                                 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4363                                                           parameters, ip, CallingConventions.Standard,
4364                                                           Set.OptAttributes, ModFlags, flags, false);
4365
4366                                 if (!SetData.Define (container))
4367                                         return false;
4368
4369                                 SetBuilder = SetData.MethodBuilder;
4370                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
4371                         }
4372
4373                         // FIXME - PropertyAttributes.HasDefault ?
4374                         
4375                         PropertyAttributes prop_attr =
4376                         PropertyAttributes.RTSpecialName |
4377                         PropertyAttributes.SpecialName;
4378
4379                         if (!IsExplicitImpl){
4380                                 PropertyBuilder = container.TypeBuilder.DefineProperty (
4381                                         Name, prop_attr, MemberType, null);
4382                                 
4383                                 if (Get != null)
4384                                         PropertyBuilder.SetGetMethod (GetBuilder);
4385                                 
4386                                 if (Set != null)
4387                                         PropertyBuilder.SetSetMethod (SetBuilder);
4388
4389                                 //
4390                                 // HACK for the reasons exposed above
4391                                 //
4392                                 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4393                                         Report.Error (
4394                                                 111, Location,
4395                                                 "Class `" + container.Name +
4396                                                 "' already contains a definition for the property `" +
4397                                                 Name + "'");
4398                                         return false;
4399                                 }
4400                         }
4401                         return true;
4402                 }
4403         }
4404
4405         /// </summary>
4406         ///  Gigantic workaround  for lameness in SRE follows :
4407         ///  This class derives from EventInfo and attempts to basically
4408         ///  wrap around the EventBuilder so that FindMembers can quickly
4409         ///  return this in it search for members
4410         /// </summary>
4411         public class MyEventBuilder : EventInfo {
4412                 
4413                 //
4414                 // We use this to "point" to our Builder which is
4415                 // not really a MemberInfo
4416                 //
4417                 EventBuilder MyBuilder;
4418                 
4419                 //
4420                 // We "catch" and wrap these methods
4421                 //
4422                 MethodInfo raise, remove, add;
4423
4424                 EventAttributes attributes;
4425                 Type declaring_type, reflected_type, event_type;
4426                 string name;
4427
4428                 Event my_event;
4429
4430                 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4431                 {
4432                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4433
4434                         // And now store the values in our own fields.
4435                         
4436                         declaring_type = type_builder;
4437
4438                         reflected_type = type_builder;
4439                         
4440                         attributes = event_attr;
4441                         this.name = name;
4442                         my_event = ev;
4443                         this.event_type = event_type;
4444                 }
4445                 
4446                 //
4447                 // Methods that you have to override.  Note that you only need 
4448                 // to "implement" the variants that take the argument (those are
4449                 // the "abstract" methods, the others (GetAddMethod()) are 
4450                 // regular.
4451                 //
4452                 public override MethodInfo GetAddMethod (bool nonPublic)
4453                 {
4454                         return add;
4455                 }
4456                 
4457                 public override MethodInfo GetRemoveMethod (bool nonPublic)
4458                 {
4459                         return remove;
4460                 }
4461                 
4462                 public override MethodInfo GetRaiseMethod (bool nonPublic)
4463                 {
4464                         return raise;
4465                 }
4466                 
4467                 //
4468                 // These methods make "MyEventInfo" look like a Builder
4469                 //
4470                 public void SetRaiseMethod (MethodBuilder raiseMethod)
4471                 {
4472                         raise = raiseMethod;
4473                         MyBuilder.SetRaiseMethod (raiseMethod);
4474                 }
4475
4476                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4477                 {
4478                         remove = removeMethod;
4479                         MyBuilder.SetRemoveOnMethod (removeMethod);
4480                 }
4481
4482                 public void SetAddOnMethod (MethodBuilder addMethod)
4483                 {
4484                         add = addMethod;
4485                         MyBuilder.SetAddOnMethod (addMethod);
4486                 }
4487
4488                 public void SetCustomAttribute (CustomAttributeBuilder cb)
4489                 {
4490                         MyBuilder.SetCustomAttribute (cb);
4491                 }
4492                 
4493                 public override object [] GetCustomAttributes (bool inherit)
4494                 {
4495                         // FIXME : There's nothing which can be seemingly done here because
4496                         // we have no way of getting at the custom attribute objects of the
4497                         // EventBuilder !
4498                         return null;
4499                 }
4500
4501                 public override object [] GetCustomAttributes (Type t, bool inherit)
4502                 {
4503                         // FIXME : Same here !
4504                         return null;
4505                 }
4506
4507                 public override bool IsDefined (Type t, bool b)
4508                 {
4509                         return true;
4510                 }
4511
4512                 public override EventAttributes Attributes {
4513                         get {
4514                                 return attributes;
4515                         }
4516                 }
4517
4518                 public override string Name {
4519                         get {
4520                                 return name;
4521                         }
4522                 }
4523
4524                 public override Type DeclaringType {
4525                         get {
4526                                 return declaring_type;
4527                         }
4528                 }
4529
4530                 public override Type ReflectedType {
4531                         get {
4532                                 return reflected_type;
4533                         }
4534                 }
4535
4536                 public Type EventType {
4537                         get {
4538                                 return event_type;
4539                         }
4540                 }
4541                 
4542                 public void SetUsed ()
4543                 {
4544                         if (my_event != null)
4545                                 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
4546                 }
4547         }
4548         
4549         public class Event : FieldBase {
4550                 const int AllowedModifiers =
4551                         Modifiers.NEW |
4552                         Modifiers.PUBLIC |
4553                         Modifiers.PROTECTED |
4554                         Modifiers.INTERNAL |
4555                         Modifiers.PRIVATE |
4556                         Modifiers.STATIC |
4557                         Modifiers.VIRTUAL |
4558                         Modifiers.SEALED |
4559                         Modifiers.OVERRIDE |
4560                         Modifiers.UNSAFE |
4561                         Modifiers.ABSTRACT;
4562
4563                 public readonly Accessor  Add;
4564                 public readonly Accessor  Remove;
4565                 public MyEventBuilder     EventBuilder;
4566
4567                 MethodBuilder AddBuilder, RemoveBuilder;
4568                 MethodData AddData, RemoveData;
4569                 
4570                 public Event (Expression type, string name, Object init, int mod, Accessor add,
4571                               Accessor remove, Attributes attrs, Location loc)
4572                         : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4573                 {
4574                         Add = add;
4575                         Remove = remove;
4576                 }
4577
4578                 public override bool Define (TypeContainer container)
4579                 {
4580                         EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4581                         MethodAttributes m_attr = MethodAttributes.HideBySig | MethodAttributes.SpecialName
4582 ;
4583                         if (!DoDefine (container, container))
4584                                 return false;
4585
4586                         if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
4587                                 Report.Error (74, Location, "'" + container.Name + "." + Name +
4588                                               "': abstract event can not have an initializer");
4589                                 return false;
4590                         }
4591                         
4592                         if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4593                                 Report.Error (66, Location, "'" + container.Name + "." + Name +
4594                                               "' : event must be of a delegate type");
4595                                 return false;
4596                         }
4597
4598                         Type [] parameter_types = new Type [1];
4599                         parameter_types [0] = MemberType;
4600
4601                         Parameter [] parms = new Parameter [1];
4602                         parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4603                         InternalParameters ip = new InternalParameters (
4604                                 container, new Parameters (parms, null, Location)); 
4605
4606                         if (!CheckBase (container))
4607                                 return false;
4608
4609                         //
4610                         // Now define the accessors
4611                         //
4612                         AddData = new MethodData (container, this, "add", TypeManager.void_type,
4613                                                   parameter_types, ip, CallingConventions.Standard,
4614                                                   (Add != null) ? Add.OptAttributes : null,
4615                                                   ModFlags, flags | m_attr, false);
4616
4617                         if (!AddData.Define (container))
4618                                 return false;
4619
4620                         AddBuilder = AddData.MethodBuilder;
4621                         AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4622
4623                         RemoveData = new MethodData (container, this, "remove", TypeManager.void_type,
4624                                                      parameter_types, ip, CallingConventions.Standard,
4625                                                      (Remove != null) ? Remove.OptAttributes : null,
4626                                                      ModFlags, flags | m_attr, false);
4627
4628                         if (!RemoveData.Define (container))
4629                                 return false;
4630
4631                         RemoveBuilder = RemoveData.MethodBuilder;
4632                         RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4633
4634                         if (!IsExplicitImpl){
4635                                 EventBuilder = new MyEventBuilder (this,
4636                                         container.TypeBuilder, Name, e_attr, MemberType);
4637                                         
4638                                 if (Add == null && Remove == null) {
4639                                         FieldBuilder = container.TypeBuilder.DefineField (
4640                                                 Name, MemberType,
4641                                                 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4642                                         TypeManager.RegisterPrivateFieldOfEvent (
4643                                                 (EventInfo) EventBuilder, FieldBuilder);
4644                                         TypeManager.RegisterFieldBase (FieldBuilder, this);
4645                                 }
4646                         
4647                                 EventBuilder.SetAddOnMethod (AddBuilder);
4648                                 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4649
4650                                 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4651                                         Report.Error (111, Location,
4652                                                       "Class `" + container.Name +
4653                                                       "' already contains a definition for the event `" +
4654                                                       Name + "'");
4655                                         return false;
4656                                 }
4657                         }
4658                         
4659                         return true;
4660                 }
4661
4662                 void EmitDefaultMethod (EmitContext ec, bool is_add)
4663                 {
4664                         ILGenerator ig = ec.ig;
4665                         MethodInfo method = null;
4666                         
4667                         if (is_add)
4668                                 method = TypeManager.delegate_combine_delegate_delegate;
4669                         else
4670                                 method = TypeManager.delegate_remove_delegate_delegate;
4671
4672                         if ((ModFlags & Modifiers.STATIC) != 0) {
4673                                 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4674                                 ig.Emit (OpCodes.Ldarg_0);
4675                                 ig.Emit (OpCodes.Call, method);
4676                                 ig.Emit (OpCodes.Castclass, MemberType);
4677                                 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4678                         } else {
4679                                 ig.Emit (OpCodes.Ldarg_0);
4680                                 ig.Emit (OpCodes.Ldarg_0);
4681                                 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4682                                 ig.Emit (OpCodes.Ldarg_1);
4683                                 ig.Emit (OpCodes.Call, method);
4684                                 ig.Emit (OpCodes.Castclass, MemberType);
4685                                 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4686                         }
4687                         ig.Emit (OpCodes.Ret);
4688                 }
4689
4690                 public void Emit (TypeContainer tc)
4691                 {
4692                         EmitContext ec;
4693
4694                         ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4695                         Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
4696
4697                         if (Add != null) {
4698                                 AddData.Emit (tc, Add.Block, Add);
4699                                 Add.Block = null;
4700                         } else {
4701                                 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4702                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4703                                 EmitDefaultMethod (ec, true);
4704                         }
4705
4706                         if (Remove != null) {
4707                                 RemoveData.Emit (tc, Remove.Block, Remove);
4708                                 Remove.Block = null;
4709                         } else {
4710                                 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4711                                 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4712                                 EmitDefaultMethod (ec, false);
4713                         }
4714                 }
4715                 
4716         }
4717
4718         //
4719         // FIXME: This does not handle:
4720         //
4721         //   int INTERFACENAME [ args ]
4722         //   Does not 
4723         //
4724         // Only:
4725         // 
4726         // int this [ args ]
4727  
4728         public class Indexer : PropertyBase {
4729
4730                 const int AllowedModifiers =
4731                         Modifiers.NEW |
4732                         Modifiers.PUBLIC |
4733                         Modifiers.PROTECTED |
4734                         Modifiers.INTERNAL |
4735                         Modifiers.PRIVATE |
4736                         Modifiers.VIRTUAL |
4737                         Modifiers.SEALED |
4738                         Modifiers.OVERRIDE |
4739                         Modifiers.UNSAFE |
4740                         Modifiers.EXTERN |
4741                         Modifiers.ABSTRACT;
4742
4743                 public string IndexerName;
4744                 public string InterfaceIndexerName;
4745
4746                 //
4747                 // Are we implementing an interface ?
4748                 //
4749                 public Indexer (DeclSpace ds, Expression type, string int_type, int flags,
4750                                 Parameters parameters, Accessor get_block, Accessor set_block,
4751                                 Attributes attrs, Location loc)
4752                         : base (ds, type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4753                                 attrs, loc)
4754                 {
4755                         ExplicitInterfaceName = int_type;
4756                 }
4757
4758                 public override bool Define (TypeContainer container)
4759                 {
4760                         PropertyAttributes prop_attr =
4761                                 PropertyAttributes.RTSpecialName |
4762                                 PropertyAttributes.SpecialName;
4763                         
4764                         if (!DoDefine (container, container))
4765                                 return false;
4766
4767                         IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4768                         if (IndexerName == null)
4769                                 IndexerName = "Item";
4770                         else if (IsExplicitImpl)
4771                                 Report.Error (592, Location,
4772                                               "Attribute 'IndexerName' is not valid on this declaration " +
4773                                               "type. It is valid on `property' declarations only.");
4774
4775                         ShortName = IndexerName;
4776                         if (IsExplicitImpl) {
4777                                 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4778                                 Name = InterfaceType.FullName + "." + IndexerName;
4779                         } else {
4780                                 InterfaceIndexerName = IndexerName;
4781                                 Name = ShortName;
4782                         }
4783
4784                         if (!CheckBase (container))
4785                                 return false;
4786
4787                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4788                         if (Get != null){
4789                                 InternalParameters ip = new InternalParameters (container, Parameters);
4790
4791                                 GetData = new MethodData (container, this, "get", MemberType,
4792                                                           ParameterTypes, ip, CallingConventions.Standard,
4793                                                           Get.OptAttributes, ModFlags, flags, false);
4794
4795                                 if (!GetData.Define (container))
4796                                         return false;
4797
4798                                 GetBuilder = GetData.MethodBuilder;
4799                         }
4800                         
4801                         if (Set != null){
4802                                 int top = ParameterTypes.Length;
4803                                 Type [] set_pars = new Type [top + 1];
4804                                 ParameterTypes.CopyTo (set_pars, 0);
4805                                 set_pars [top] = MemberType;
4806
4807                                 Parameter [] fixed_parms = Parameters.FixedParameters;
4808
4809                                 if (fixed_parms == null){
4810                                         throw new Exception ("We currently do not support only array arguments in an indexer at: " + Location);
4811                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4812                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4813                                         //
4814                                         // Here is the problem: the `value' parameter has
4815                                         // to come *after* the array parameter in the declaration
4816                                         // like this:
4817                                         // X (object [] x, Type value)
4818                                         // .param [0]
4819                                         //
4820                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4821                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4822                                         
4823                                 }
4824                                 
4825                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4826
4827
4828                                 fixed_parms.CopyTo (tmp, 0);
4829                                 tmp [fixed_parms.Length] = new Parameter (
4830                                         Type, "value", Parameter.Modifier.NONE, null);
4831
4832                                 Parameters set_formal_params = new Parameters (tmp, null, Location);
4833                                 
4834                                 InternalParameters ip = new InternalParameters (container, set_formal_params);
4835
4836                                 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4837                                                           set_pars, ip, CallingConventions.Standard,
4838                                                           Set.OptAttributes, ModFlags, flags, false);
4839
4840                                 if (!SetData.Define (container))
4841                                         return false;
4842
4843                                 SetBuilder = SetData.MethodBuilder;
4844                         }
4845
4846                         //
4847                         // Now name the parameters
4848                         //
4849                         Parameter [] p = Parameters.FixedParameters;
4850                         if (p != null) {
4851                                 int i;
4852                                 
4853                                 for (i = 0; i < p.Length; ++i) {
4854                                         if (Get != null)
4855                                                 GetBuilder.DefineParameter (
4856                                                         i + 1, p [i].Attributes, p [i].Name);
4857
4858                                         if (Set != null)
4859                                                 SetBuilder.DefineParameter (
4860                                                         i + 1, p [i].Attributes, p [i].Name);
4861                                 }
4862
4863                                 if (Set != null)
4864                                         SetBuilder.DefineParameter (
4865                                                 i + 1, ParameterAttributes.None, "value");
4866                                         
4867                                 if (i != ParameterTypes.Length) {
4868                                         Parameter array_param = Parameters.ArrayParameter;
4869
4870                                         SetBuilder.DefineParameter (
4871                                                 i + 1, array_param.Attributes, array_param.Name);
4872                                 }
4873                         }
4874
4875                         //
4876                         // Define the PropertyBuilder if one of the following conditions are met:
4877                         // a) we're not implementing an interface indexer.
4878                         // b) the indexer has a different IndexerName and this is no
4879                         //    explicit interface implementation.
4880                         //
4881                         if (!IsExplicitImpl) {
4882                                 PropertyBuilder = container.TypeBuilder.DefineProperty (
4883                                         IndexerName, prop_attr, MemberType, ParameterTypes);
4884
4885                                 if (GetData != null)
4886                                         PropertyBuilder.SetGetMethod (GetBuilder);
4887
4888                                 if (SetData != null)
4889                                         PropertyBuilder.SetSetMethod (SetBuilder);
4890                                 
4891                                 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4892                                                              ParameterTypes);
4893                         }
4894
4895                         return true;
4896                 }
4897         }
4898
4899         public class Operator : MemberBase {
4900
4901                 const int AllowedModifiers =
4902                         Modifiers.PUBLIC |
4903                         Modifiers.UNSAFE |
4904                         Modifiers.EXTERN |
4905                         Modifiers.STATIC;
4906
4907                 const int RequiredModifiers =
4908                         Modifiers.PUBLIC |
4909                         Modifiers.STATIC;
4910
4911                 public enum OpType : byte {
4912
4913                         // Unary operators
4914                         LogicalNot,
4915                         OnesComplement,
4916                         Increment,
4917                         Decrement,
4918                         True,
4919                         False,
4920
4921                         // Unary and Binary operators
4922                         Addition,
4923                         Subtraction,
4924
4925                         UnaryPlus,
4926                         UnaryNegation,
4927                         
4928                         // Binary operators
4929                         Multiply,
4930                         Division,
4931                         Modulus,
4932                         BitwiseAnd,
4933                         BitwiseOr,
4934                         ExclusiveOr,
4935                         LeftShift,
4936                         RightShift,
4937                         Equality,
4938                         Inequality,
4939                         GreaterThan,
4940                         LessThan,
4941                         GreaterThanOrEqual,
4942                         LessThanOrEqual,
4943
4944                         // Implicit and Explicit
4945                         Implicit,
4946                         Explicit
4947                 };
4948
4949                 public readonly OpType OperatorType;
4950                 public readonly Expression ReturnType;
4951                 public readonly Expression FirstArgType, SecondArgType;
4952                 public readonly string FirstArgName, SecondArgName;
4953                 public Block           Block;
4954                 public MethodBuilder   OperatorMethodBuilder;
4955                 
4956                 public string MethodName;
4957                 public Method OperatorMethod;
4958
4959                 public Operator (OpType type, Expression ret_type, int mod_flags,
4960                                  Expression arg1type, string arg1name,
4961                                  Expression arg2type, string arg2name,
4962                                  Block block, Attributes attrs, Location loc)
4963                         : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
4964                 {
4965                         OperatorType = type;
4966                         ReturnType = ret_type;
4967                         FirstArgType = arg1type;
4968                         FirstArgName = arg1name;
4969                         SecondArgType = arg2type;
4970                         SecondArgName = arg2name;
4971                         Block = block;
4972                 }
4973
4974                 string Prototype (TypeContainer container)
4975                 {
4976                         return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4977                                 SecondArgType + ")";
4978                 }
4979                 
4980                 public override bool Define (TypeContainer container)
4981                 {
4982                         int length = 1;
4983                         MethodName = "op_" + OperatorType;
4984                         
4985                         if (SecondArgType != null)
4986                                 length = 2;
4987                         
4988                         Parameter [] param_list = new Parameter [length];
4989
4990                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4991                                 Report.Error (
4992                                         558, Location, 
4993                                         "User defined operators `" +
4994                                         Prototype (container) +
4995                                         "' must be declared static and public");
4996                                 return false;
4997                         }
4998
4999                         param_list[0] = new Parameter (FirstArgType, FirstArgName,
5000                                                        Parameter.Modifier.NONE, null);
5001                         if (SecondArgType != null)
5002                                 param_list[1] = new Parameter (SecondArgType, SecondArgName,
5003                                                                Parameter.Modifier.NONE, null);
5004                         
5005                         OperatorMethod = new Method (container, ReturnType, ModFlags, MethodName,
5006                                                      new Parameters (param_list, null, Location),
5007                                                      OptAttributes, Location);
5008
5009                         OperatorMethod.IsOperator = true;                       
5010                         OperatorMethod.Define (container);
5011
5012                         if (OperatorMethod.MethodBuilder == null)
5013                                 return false;
5014                         
5015                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
5016
5017                         Type [] param_types = OperatorMethod.ParameterTypes;
5018                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
5019                         Type return_type = OperatorMethod.GetReturnType ();
5020                         Type first_arg_type = param_types [0];
5021
5022                         // Rules for conversion operators
5023                         
5024                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
5025                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
5026                                         Report.Error (
5027                                                 555, Location,
5028                                                 "User-defined conversion cannot take an object of the " +
5029                                                 "enclosing type and convert to an object of the enclosing" +
5030                                                 " type");
5031                                         return false;
5032                                 }
5033                                 
5034                                 if (first_arg_type != declaring_type && return_type != declaring_type){
5035                                         Report.Error (
5036                                                 556, Location, 
5037                                                 "User-defined conversion must convert to or from the " +
5038                                                 "enclosing type");
5039                                         return false;
5040                                 }
5041                                 
5042                                 if (first_arg_type == TypeManager.object_type ||
5043                                     return_type == TypeManager.object_type){
5044                                         Report.Error (
5045                                                 -8, Location,
5046                                                 "User-defined conversion cannot convert to or from " +
5047                                                 "object type");
5048                                         return false;
5049                                 }
5050
5051                                 if (first_arg_type.IsInterface || return_type.IsInterface){
5052                                         Report.Error (
5053                                                 552, Location,
5054                                                 "User-defined conversion cannot convert to or from an " +
5055                                                 "interface type");
5056                                         return false;
5057                                 }
5058                                 
5059                                 if (first_arg_type.IsSubclassOf (return_type) ||
5060                                     return_type.IsSubclassOf (first_arg_type)){
5061                                         Report.Error (
5062                                                 -10, Location,
5063                                                 "User-defined conversion cannot convert between types " +
5064                                                 "that derive from each other");
5065                                         return false;
5066                                 }
5067                         } else if (SecondArgType == null) {
5068                                 // Checks for Unary operators
5069                                 
5070                                 if (first_arg_type != declaring_type){
5071                                         Report.Error (
5072                                                 562, Location,
5073                                                 "The parameter of a unary operator must be the " +
5074                                                 "containing type");
5075                                         return false;
5076                                 }
5077                                 
5078                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
5079                                         if (return_type != declaring_type){
5080                                                 Report.Error (
5081                                                         559, Location,
5082                                                         "The parameter and return type for ++ and -- " +
5083                                                         "must be the containing type");
5084                                                 return false;
5085                                         }
5086                                         
5087                                 }
5088                                 
5089                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
5090                                         if (return_type != TypeManager.bool_type){
5091                                                 Report.Error (
5092                                                         215, Location,
5093                                                         "The return type of operator True or False " +
5094                                                         "must be bool");
5095                                                 return false;
5096                                         }
5097                                 }
5098                                 
5099                         } else {
5100                                 // Checks for Binary operators
5101                                 
5102                                 if (first_arg_type != declaring_type &&
5103                                     param_types [1] != declaring_type){
5104                                         Report.Error (
5105                                                 563, Location,
5106                                                 "One of the parameters of a binary operator must " +
5107                                                 "be the containing type");
5108                                         return false;
5109                                 }
5110                         }
5111
5112                         return true;
5113                 }
5114                 
5115                 public void Emit (TypeContainer container)
5116                 {
5117                         //
5118                         // abstract or extern methods have no bodies
5119                         //
5120                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
5121                                 return;
5122                         
5123                         OperatorMethod.Block = Block;
5124                         OperatorMethod.Emit (container);
5125                         Block = null;
5126                 }
5127
5128                 public static string GetName (OpType ot)
5129                 {
5130                         switch (ot){
5131                         case OpType.LogicalNot:
5132                                 return "!";
5133                         case OpType.OnesComplement:
5134                                 return "~";
5135                         case OpType.Increment:
5136                                 return "++";
5137                         case OpType.Decrement:
5138                                 return "--";
5139                         case OpType.True:
5140                                 return "true";
5141                         case OpType.False:
5142                                 return "false";
5143                         case OpType.Addition:
5144                                 return "+";
5145                         case OpType.Subtraction:
5146                                 return "-";
5147                         case OpType.UnaryPlus:
5148                                 return "+";
5149                         case OpType.UnaryNegation:
5150                                 return "-";
5151                         case OpType.Multiply:
5152                                 return "*";
5153                         case OpType.Division:
5154                                 return "/";
5155                         case OpType.Modulus:
5156                                 return "%";
5157                         case OpType.BitwiseAnd:
5158                                 return "&";
5159                         case OpType.BitwiseOr:
5160                                 return "|";
5161                         case OpType.ExclusiveOr:
5162                                 return "^";
5163                         case OpType.LeftShift:
5164                                 return "<<";
5165                         case OpType.RightShift:
5166                                 return ">>";
5167                         case OpType.Equality:
5168                                 return "==";
5169                         case OpType.Inequality:
5170                                 return "!=";
5171                         case OpType.GreaterThan:
5172                                 return ">";
5173                         case OpType.LessThan:
5174                                 return "<";
5175                         case OpType.GreaterThanOrEqual:
5176                                 return ">=";
5177                         case OpType.LessThanOrEqual:
5178                                 return "<=";
5179                         case OpType.Implicit:
5180                                 return "implicit";
5181                         case OpType.Explicit:
5182                                 return "explicit";
5183                         default: return "";
5184                         }
5185                 }
5186                 
5187                 public override string ToString ()
5188                 {
5189                         Type return_type = OperatorMethod.GetReturnType();
5190                         Type [] param_types = OperatorMethod.ParameterTypes;
5191                         
5192                         if (SecondArgType == null)
5193                                 return String.Format (
5194                                         "{0} operator {1}({2})",
5195                                         TypeManager.CSharpName (return_type),
5196                                         GetName (OperatorType),
5197                                         param_types [0]);
5198                         else
5199                                 return String.Format (
5200                                         "{0} operator {1}({2}, {3})",
5201                                         TypeManager.CSharpName (return_type),
5202                                         GetName (OperatorType),
5203                                         param_types [0], param_types [1]);
5204                 }
5205         }
5206
5207         //
5208         // This is used to compare method signatures
5209         //
5210         struct MethodSignature {
5211                 public string Name;
5212                 public Type RetType;
5213                 public Type [] Parameters;
5214                 
5215                 /// <summary>
5216                 ///    This delegate is used to extract methods which have the
5217                 ///    same signature as the argument
5218                 /// </summary>
5219                 public static MemberFilter method_signature_filter;
5220
5221                 /// <summary>
5222                 ///   This delegate is used to extract inheritable methods which
5223                 ///   have the same signature as the argument.  By inheritable,
5224                 ///   this means that we have permissions to override the method
5225                 ///   from the current assembly and class
5226                 /// </summary>
5227                 public static MemberFilter inheritable_method_signature_filter;
5228
5229                 static MethodSignature ()
5230                 {
5231                         method_signature_filter = new MemberFilter (MemberSignatureCompare);
5232                         inheritable_method_signature_filter = new MemberFilter (
5233                                 InheritableMemberSignatureCompare);
5234                 }
5235                 
5236                 public MethodSignature (string name, Type ret_type, Type [] parameters)
5237                 {
5238                         Name = name;
5239                         RetType = ret_type;
5240
5241                         if (parameters == null)
5242                                 Parameters = TypeManager.NoTypes;
5243                         else
5244                                 Parameters = parameters;
5245                 }
5246
5247                 public override string ToString ()
5248                 {
5249                         string pars = "";
5250                         if (Parameters.Length != 0){
5251                                 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
5252                                 for (int i = 0; i < Parameters.Length; i++){
5253                                         sb.Append (Parameters [i]);
5254                                         if (i+1 < Parameters.Length)
5255                                                 sb.Append (", ");
5256                                 }
5257                                 pars = sb.ToString ();
5258                         }
5259
5260                         return String.Format ("{0} {1} ({2})", RetType, Name, pars);
5261                 }
5262                 
5263                 public override int GetHashCode ()
5264                 {
5265                         return Name.GetHashCode ();
5266                 }
5267
5268                 public override bool Equals (Object o)
5269                 {
5270                         MethodSignature other = (MethodSignature) o;
5271
5272                         if (other.Name != Name)
5273                                 return false;
5274
5275                         if (other.RetType != RetType)
5276                                 return false;
5277                         
5278                         if (Parameters == null){
5279                                 if (other.Parameters == null)
5280                                         return true;
5281                                 return false;
5282                         }
5283
5284                         if (other.Parameters == null)
5285                                 return false;
5286                         
5287                         int c = Parameters.Length;
5288                         if (other.Parameters.Length != c)
5289                                 return false;
5290
5291                         for (int i = 0; i < c; i++)
5292                                 if (other.Parameters [i] != Parameters [i])
5293                                         return false;
5294
5295                         return true;
5296                 }
5297
5298                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
5299                 {
5300                         MethodSignature sig = (MethodSignature) filter_criteria;
5301
5302                         if (m.Name != sig.Name)
5303                                 return false;
5304
5305                         Type ReturnType;
5306                         MethodInfo mi = m as MethodInfo;
5307                         PropertyInfo pi = m as PropertyInfo;
5308
5309                         if (mi != null)
5310                                 ReturnType = mi.ReturnType;
5311                         else if (pi != null)
5312                                 ReturnType = pi.PropertyType;
5313                         else
5314                                 return false;
5315                         
5316                         //
5317                         // we use sig.RetType == null to mean `do not check the
5318                         // method return value.  
5319                         //
5320                         if (sig.RetType != null)
5321                                 if (ReturnType != sig.RetType)
5322                                         return false;
5323
5324                         Type [] args;
5325                         if (mi != null)
5326                                 args = TypeManager.GetArgumentTypes (mi);
5327                         else
5328                                 args = TypeManager.GetArgumentTypes (pi);
5329                         Type [] sigp = sig.Parameters;
5330
5331                         if (args.Length != sigp.Length)
5332                                 return false;
5333
5334                         for (int i = args.Length; i > 0; ){
5335                                 i--;
5336                                 if (args [i] != sigp [i])
5337                                         return false;
5338                         }
5339                         return true;
5340                 }
5341
5342                 //
5343                 // This filter should be used when we are requesting methods that
5344                 // we want to override.
5345                 //
5346                 // This makes a number of assumptions, for example
5347                 // that the methods being extracted are of a parent
5348                 // class (this means we know implicitly that we are
5349                 // being called to find out about members by a derived
5350                 // class).
5351                 // 
5352                 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
5353                 {
5354                         MethodInfo mi;
5355                         PropertyInfo pi = m as PropertyInfo;
5356
5357                         if (pi != null) {
5358                                 mi = pi.GetGetMethod (true);
5359                                 if (mi == null)
5360                                         mi = pi.GetSetMethod (true);
5361                         } else
5362                                 mi = m as MethodInfo;
5363
5364                         if (mi == null){
5365                                 Console.WriteLine ("Nothing found");
5366                         }
5367                         
5368                         MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5369
5370                         // If only accessible to the current class.
5371                         if (prot == MethodAttributes.Private)
5372                                 return false;
5373
5374                         if (!MemberSignatureCompare (m, filter_criteria))
5375                                 return false;
5376
5377                         // If only accessible to the defining assembly or 
5378                         if (prot == MethodAttributes.FamANDAssem ||
5379                             prot == MethodAttributes.Assembly){
5380                                 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
5381                                         return true;
5382                                 else
5383                                         return false;
5384                         }
5385
5386                         // Anything else (FamOrAssembly and Public) is fine
5387                         return true;
5388                 }
5389         }
5390 }