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