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