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