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