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