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