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