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