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