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