2006-04-28 Marek Safar <marek.safar@seznam.cz>
[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                         if (mi.IsSpecialName)
3935                                 return null;
3936
3937                         base_ret_type = mi.ReturnType;
3938                         return mi;
3939                 }
3940
3941                 protected override bool VerifyClsCompliance ()
3942                 {
3943                         if (!base.VerifyClsCompliance ())
3944                                 return false;
3945
3946                         if (ParameterInfo.Count > 0) {
3947                                 ArrayList al = (ArrayList)ParentContainer.MemberCache.Members [Name];
3948                                 if (al.Count > 1)
3949                                         MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder);
3950                         }
3951
3952                         return true;
3953                 }
3954         }
3955
3956         public abstract class ConstructorInitializer {
3957                 ArrayList argument_list;
3958                 protected ConstructorInfo base_constructor;
3959                 Location loc;
3960                 
3961                 public ConstructorInitializer (ArrayList argument_list, Location loc)
3962                 {
3963                         this.argument_list = argument_list;
3964                         this.loc = loc;
3965                 }
3966
3967                 public ArrayList Arguments {
3968                         get {
3969                                 return argument_list;
3970                         }
3971                 }
3972
3973                 public bool Resolve (ConstructorBuilder caller_builder, Block block, EmitContext ec)
3974                 {
3975                         Expression base_constructor_group;
3976                         Type t;
3977                         bool error = false;
3978
3979                         ec.CurrentBlock = block;
3980
3981                         if (argument_list != null){
3982                                 foreach (Argument a in argument_list){
3983                                         if (!a.Resolve (ec, loc))
3984                                                 return false;
3985                                 }
3986                         }
3987                         ec.CurrentBlock = null;
3988
3989                         if (this is ConstructorBaseInitializer) {
3990                                 if (ec.ContainerType.BaseType == null)
3991                                         return true;
3992
3993                                 t = ec.ContainerType.BaseType;
3994                                 if (ec.ContainerType.IsValueType) {
3995                                         Report.Error (522, loc,
3996                                                 "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
3997                                         return false;
3998                                 }
3999                         } else
4000                                 t = ec.ContainerType;
4001
4002                         base_constructor_group = Expression.MemberLookup (
4003                                 ec.ContainerType, t, ".ctor", MemberTypes.Constructor,
4004                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4005                                 loc);
4006                         
4007                         if (base_constructor_group == null){
4008                                 error = true;
4009                                 base_constructor_group = Expression.MemberLookup (
4010                                         t, null, t, ".ctor", MemberTypes.Constructor,
4011                                         BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4012                                         loc);
4013                         }
4014
4015                         int errors = Report.Errors;
4016                         if (base_constructor_group != null)
4017                                 base_constructor = (ConstructorInfo) Invocation.OverloadResolve (
4018                                         ec, (MethodGroupExpr) base_constructor_group, argument_list,
4019                                         false, loc);
4020                         
4021                         if (base_constructor == null) {
4022                                 if (errors == Report.Errors)
4023                                         Invocation.Error_WrongNumArguments (loc, TypeManager.CSharpSignature (caller_builder),
4024                                                 argument_list == null ? 0 : argument_list.Count);
4025                                 return false;
4026                         }
4027
4028                         if (error) {
4029                                 Expression.ErrorIsInaccesible (loc, TypeManager.CSharpSignature (base_constructor));
4030                                 base_constructor = null;
4031                                 return false;
4032                         }
4033
4034                         if (base_constructor == caller_builder){
4035                                 Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
4036                                 return false;
4037                         }
4038                         
4039                         return true;
4040                 }
4041
4042                 public virtual void Emit (EmitContext ec)
4043                 {
4044                         if (base_constructor != null){
4045                                 ec.Mark (loc, false);
4046                                 if (ec.IsStatic)
4047                                         Invocation.EmitCall (ec, true, true, null, base_constructor, argument_list, loc);
4048                                 else
4049                                         Invocation.EmitCall (ec, true, false, ec.GetThis (loc), base_constructor, argument_list, loc);
4050                         }
4051                 }
4052         }
4053
4054         public class ConstructorBaseInitializer : ConstructorInitializer {
4055                 public ConstructorBaseInitializer (ArrayList argument_list, Location l) :
4056                         base (argument_list, l)
4057                 {
4058                 }
4059         }
4060
4061         class GeneratedBaseInitializer: ConstructorBaseInitializer {
4062                 public GeneratedBaseInitializer (Location loc):
4063                         base (null, loc)
4064                 {
4065                 }
4066         }
4067
4068         public class ConstructorThisInitializer : ConstructorInitializer {
4069                 public ConstructorThisInitializer (ArrayList argument_list, Location l) :
4070                         base (argument_list, l)
4071                 {
4072                 }
4073         }
4074         
4075         public class Constructor : MethodCore, IMethodData {
4076                 public ConstructorBuilder ConstructorBuilder;
4077                 public ConstructorInitializer Initializer;
4078                 ListDictionary declarative_security;
4079
4080                 // <summary>
4081                 //   Modifiers allowed for a constructor.
4082                 // </summary>
4083                 public const int AllowedModifiers =
4084                         Modifiers.PUBLIC |
4085                         Modifiers.PROTECTED |
4086                         Modifiers.INTERNAL |
4087                         Modifiers.STATIC |
4088                         Modifiers.UNSAFE |
4089                         Modifiers.EXTERN |              
4090                         Modifiers.PRIVATE;
4091
4092                 static string[] attribute_targets = new string [] { "method" };
4093
4094                 bool has_compliant_args = false;
4095                 //
4096                 // The spec claims that static is not permitted, but
4097                 // my very own code has static constructors.
4098                 //
4099                 public Constructor (DeclSpace parent, string name, int mod, Parameters args,
4100                                     ConstructorInitializer init, Location loc)
4101                         : base (parent, null, mod, AllowedModifiers, false, new MemberName (name, loc),
4102                                 null, args)
4103                 {
4104                         Initializer = init;
4105                 }
4106
4107                 public bool HasCompliantArgs {
4108                         get { return has_compliant_args; }
4109                 }
4110
4111                 public override AttributeTargets AttributeTargets {
4112                         get { return AttributeTargets.Constructor; }
4113                 }
4114
4115
4116                 //
4117                 // Returns true if this is a default constructor
4118                 //
4119                 public bool IsDefault ()
4120                 {
4121                         if ((ModFlags & Modifiers.STATIC) != 0)
4122                                 return Parameters.Empty;
4123                         
4124                         return Parameters.Empty &&
4125                                         (Initializer is ConstructorBaseInitializer) &&
4126                                         (Initializer.Arguments == null);
4127                 }
4128
4129                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4130                 {
4131                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
4132                                 if (declarative_security == null) {
4133                                         declarative_security = new ListDictionary ();
4134                                 }
4135                                 a.ExtractSecurityPermissionSet (declarative_security);
4136                                 return;
4137                         }
4138
4139                         if (a.Type == TypeManager.methodimpl_attr_type &&
4140                                 (a.GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0) {
4141                                 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
4142                         }
4143
4144                         ConstructorBuilder.SetCustomAttribute (cb);
4145                 }
4146                 
4147                 protected override bool CheckForDuplications ()
4148                 {
4149                         ArrayList ar = ParentContainer.InstanceConstructors;
4150                         if (ar != null) {
4151                                 int arLen = ar.Count;
4152                                         
4153                                 for (int i = 0; i < arLen; i++) {
4154                                         Constructor m = (Constructor) ar [i];
4155                                         if (IsDuplicateImplementation (m))
4156                                                 return false;
4157                                 }
4158                         }
4159                         return true;
4160                 }
4161
4162                 protected override bool CheckBase ()
4163                 {
4164                         if ((ModFlags & Modifiers.STATIC) != 0) {
4165                                 if (!Parameters.Empty) {
4166                                         Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
4167                                                 GetSignatureForError ());
4168                                         return false;
4169                                 }
4170
4171                                 // the rest can be ignored
4172                                 return true;
4173                         }
4174
4175                         // Check whether arguments were correct.
4176                         if (!DoDefineParameters ())
4177                                 return false;
4178
4179                         if (!CheckForDuplications ())
4180                                 return false;
4181
4182                         if (ParentContainer.Kind == Kind.Struct) {
4183                                 if (ParameterTypes.Length == 0) {
4184                                         Report.Error (568, Location, 
4185                                                 "Structs cannot contain explicit parameterless constructors");
4186                                         return false;
4187                                 }
4188
4189                                 if ((ModFlags & Modifiers.PROTECTED) != 0) {
4190                                         Report.Error (666, Location, "`{0}': new protected member declared in struct", GetSignatureForError ());
4191                                         return false;
4192                                 }
4193                         }
4194
4195                         if ((RootContext.WarningLevel >= 4) && ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.PROTECTED) != 0)) {
4196                                 Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", GetSignatureForError ());
4197                         }
4198                         
4199                         return true;
4200                 }
4201                 
4202                 //
4203                 // Creates the ConstructorBuilder
4204                 //
4205                 public override bool Define ()
4206                 {
4207                         if (ConstructorBuilder != null)
4208                                 return true;
4209
4210                         MethodAttributes ca = (MethodAttributes.RTSpecialName |
4211                                                MethodAttributes.SpecialName);
4212                         
4213                         if ((ModFlags & Modifiers.STATIC) != 0) {
4214                                 ca |= MethodAttributes.Static | MethodAttributes.Private;
4215                         } else {
4216                                 ca |= MethodAttributes.HideBySig;
4217
4218                                 if ((ModFlags & Modifiers.PUBLIC) != 0)
4219                                         ca |= MethodAttributes.Public;
4220                                 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4221                                         if ((ModFlags & Modifiers.INTERNAL) != 0)
4222                                                 ca |= MethodAttributes.FamORAssem;
4223                                         else 
4224                                                 ca |= MethodAttributes.Family;
4225                                 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4226                                         ca |= MethodAttributes.Assembly;
4227                                 else
4228                                         ca |= MethodAttributes.Private;
4229                         }
4230
4231                         if (!CheckAbstractAndExtern (block != null))
4232                                 return false;
4233                         
4234                         // Check if arguments were correct.
4235                         if (!CheckBase ())
4236                                 return false;
4237
4238                         ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4239                                 ca, CallingConventions,
4240                                 ParameterTypes);
4241
4242                         if ((ModFlags & Modifiers.UNSAFE) != 0)
4243                                 ConstructorBuilder.InitLocals = false;
4244
4245                         if (ParentContainer.IsComImport) {
4246                                 if (!IsDefault ()) {
4247                                         Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
4248                                                 Parent.GetSignatureForError ());
4249                                         return false;
4250                                 }
4251                                 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
4252                         }
4253                         
4254                         TypeManager.AddMethod (ConstructorBuilder, this);
4255
4256                         return true;
4257                 }
4258
4259                 //
4260                 // Emits the code
4261                 //
4262                 public override void Emit ()
4263                 {
4264                         if (OptAttributes != null)
4265                                 OptAttributes.Emit ();
4266
4267                         EmitContext ec = CreateEmitContext (null, null);
4268
4269                         if (block != null) {
4270                                 // If this is a non-static `struct' constructor and doesn't have any
4271                                 // initializer, it must initialize all of the struct's fields.
4272                                 if ((ParentContainer.Kind == Kind.Struct) &&
4273                                         ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4274                                         block.AddThisVariable (Parent, Location);
4275
4276                                 if (!block.ResolveMeta (ec, ParameterInfo))
4277                                         block = null;
4278                         }
4279
4280                         if ((ModFlags & Modifiers.STATIC) == 0){
4281                                 if (ParentContainer.Kind == Kind.Class && Initializer == null)
4282                                         Initializer = new GeneratedBaseInitializer (Location);
4283
4284
4285                                 //
4286                                 // Spec mandates that Initializers will not have
4287                                 // `this' access
4288                                 //
4289                                 ec.IsStatic = true;
4290                                 if ((Initializer != null) &&
4291                                     !Initializer.Resolve (ConstructorBuilder, block, ec))
4292                                         return;
4293                                 ec.IsStatic = false;
4294                         }
4295
4296                         Parameters.ApplyAttributes (ConstructorBuilder);
4297                         
4298                         SourceMethod source = SourceMethod.Create (
4299                                 Parent, ConstructorBuilder, block);
4300
4301                         //
4302                         // Classes can have base initializers and instance field initializers.
4303                         //
4304                         if (ParentContainer.Kind == Kind.Class){
4305                                 if ((ModFlags & Modifiers.STATIC) == 0){
4306
4307                                         //
4308                                         // If we use a "this (...)" constructor initializer, then
4309                                         // do not emit field initializers, they are initialized in the other constructor
4310                                         //
4311                                         if (!(Initializer != null && Initializer is ConstructorThisInitializer))
4312                                                 ParentContainer.EmitFieldInitializers (ec);
4313                                 }
4314                         }
4315                         if (Initializer != null) {
4316                                 Initializer.Emit (ec);
4317                         }
4318                         
4319                         if ((ModFlags & Modifiers.STATIC) != 0)
4320                                 ParentContainer.EmitFieldInitializers (ec);
4321
4322                         ec.EmitTopBlock (this, block);
4323
4324                         if (source != null)
4325                                 source.CloseMethod ();
4326
4327                         base.Emit ();
4328
4329                         if (declarative_security != null) {
4330                                 foreach (DictionaryEntry de in declarative_security) {
4331                                         ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4332                                 }
4333                         }
4334
4335                         block = null;
4336                 }
4337
4338                 // Is never override
4339                 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4340                 {
4341                         return null;
4342                 }
4343
4344                 public override string GetSignatureForError()
4345                 {
4346                         return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4347                 }
4348
4349                 public override string[] ValidAttributeTargets {
4350                         get {
4351                                 return attribute_targets;
4352                         }
4353                 }
4354
4355                 protected override bool VerifyClsCompliance ()
4356                 {
4357                         if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
4358                                 return false;
4359                         }
4360                         
4361                         if (ParameterInfo.Count > 0) {
4362                                 ArrayList al = (ArrayList)Parent.MemberCache.Members [".ctor"];
4363                                 if (al.Count > 3)
4364                                         MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder);
4365  
4366                                 if (Parent.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
4367                                         foreach (Type param in ParameterTypes) {
4368                                                 if (param.IsArray) {
4369                                                         return true;
4370                                                 }
4371                                         }
4372                                 }
4373                         }
4374                         has_compliant_args = true;
4375                         return true;
4376                 }
4377
4378                 #region IMethodData Members
4379
4380                 public System.Reflection.CallingConventions CallingConventions {
4381                         get {
4382                                 CallingConventions cc = Parameters.CallingConvention;
4383
4384                                 if (ParentContainer.Kind == Kind.Class)
4385                                         if ((ModFlags & Modifiers.STATIC) == 0)
4386                                                 cc |= CallingConventions.HasThis;
4387
4388                                 // FIXME: How is `ExplicitThis' used in C#?
4389                         
4390                                 return cc;
4391                         }
4392                 }
4393
4394                 public new Location Location {
4395                         get {
4396                                 return base.Location;
4397                         }
4398                 }
4399
4400                 public MemberName MethodName {
4401                         get {
4402                                 return MemberName;
4403                         }
4404                 }
4405
4406                 public Type ReturnType {
4407                         get {
4408                                 return MemberType;
4409                         }
4410                 }
4411
4412                 public EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
4413                 {
4414                         ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
4415                         return new EmitContext (this, Parent, Location, ig_, null, ModFlags, true);
4416                 }
4417
4418                 public bool IsExcluded()
4419                 {
4420                         return false;
4421                 }
4422
4423                 #endregion
4424         }
4425
4426         /// <summary>
4427         /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
4428         /// </summary>
4429         public interface IMethodData
4430         {
4431                 CallingConventions CallingConventions { get; }
4432                 Location Location { get; }
4433                 MemberName MethodName { get; }
4434                 Type ReturnType { get; }
4435                 Parameters ParameterInfo { get; }
4436
4437                 Attributes OptAttributes { get; }
4438                 ToplevelBlock Block { get; set; }
4439
4440                 EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
4441                 ObsoleteAttribute GetObsoleteAttribute ();
4442                 string GetSignatureForError ();
4443                 bool IsExcluded ();
4444                 bool IsClsComplianceRequired ();
4445                 void SetMemberIsUsed ();
4446         }
4447
4448         //
4449         // Encapsulates most of the Method's state
4450         //
4451         public class MethodData {
4452
4453                 readonly IMethodData method;
4454
4455                 //
4456                 // Are we implementing an interface ?
4457                 //
4458                 public MethodInfo implementing;
4459
4460                 //
4461                 // Protected data.
4462                 //
4463                 protected MemberBase member;
4464                 protected int modifiers;
4465                 protected MethodAttributes flags;
4466
4467                 MethodBuilder builder = null;
4468                 public MethodBuilder MethodBuilder {
4469                         get {
4470                                 return builder;
4471                         }
4472                 }
4473
4474                 public MethodData (MemberBase member,
4475                                    int modifiers, MethodAttributes flags, IMethodData method)
4476                 {
4477                         this.member = member;
4478                         this.modifiers = modifiers;
4479                         this.flags = flags;
4480
4481                         this.method = method;
4482                 }
4483
4484                 public bool Define (DeclSpace parent)
4485                 {
4486                         string name = method.MethodName.Name;
4487                         string method_name = name;
4488
4489                         TypeContainer container = ((TypeContainer) parent).PartialContainer;
4490
4491                         PendingImplementation pending = container.PendingImplementations;
4492                         if (pending != null){
4493                                 if (member is Indexer) // TODO: test it, but it should work without this IF
4494                                         implementing = pending.IsInterfaceIndexer (
4495                                                 member.InterfaceType, method.ReturnType, method.ParameterInfo);
4496                                 else
4497                                         implementing = pending.IsInterfaceMethod (
4498                                                 member.InterfaceType, name, method.ReturnType, method.ParameterInfo);
4499
4500                                 if (member.InterfaceType != null){
4501                                         if (implementing == null){
4502                                                 if (member is PropertyBase) {
4503                                                         Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
4504                                                                       method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
4505                                                                       member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
4506
4507                                                 } else {
4508                                                         Report.Error (539, method.Location,
4509                                                                       "`{0}.{1}' in explicit interface declaration is not a member of interface",
4510                                                                       TypeManager.CSharpName (member.InterfaceType), member.ShortName);
4511                                                 }
4512                                                 return false;
4513                                         }
4514                                         if (implementing.IsSpecialName && !(method is AbstractPropertyEventMethod)) {
4515                                                 Report.SymbolRelatedToPreviousError (implementing);
4516                                                 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
4517                                                         member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
4518                                                 return false;
4519                                         }
4520                                         method_name = member.InterfaceType.FullName + "." + name;
4521                                 } else {
4522                                         if (implementing != null) {
4523                                                 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
4524                                                 if (prop_method != null) {
4525                                                         if (!implementing.IsSpecialName) {
4526                                                                 Report.SymbolRelatedToPreviousError (implementing);
4527                                                                 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
4528                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
4529                                                                 return false;
4530                                                         }
4531                                                         PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
4532                                                         if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
4533                                                                 Report.SymbolRelatedToPreviousError (implementing);
4534                                                                 Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
4535                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing, true));
4536                                                                 return false;
4537                                                         }
4538                                                 }
4539                                         }
4540                                 }
4541                         }
4542
4543                         //
4544                         // For implicit implementations, make sure we are public, for
4545                         // explicit implementations, make sure we are private.
4546                         //
4547                         if (implementing != null){
4548                                 //
4549                                 // Setting null inside this block will trigger a more
4550                                 // verbose error reporting for missing interface implementations
4551                                 //
4552                                 // The "candidate" function has been flagged already
4553                                 // but it wont get cleared
4554                                 //
4555                                 if (member.IsExplicitImpl){
4556                                         if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
4557                                                 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
4558                                                 implementing = null;
4559                                         }
4560                                 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
4561                                         if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
4562                                                 //
4563                                                 // If this is an interface method implementation,
4564                                                 // check for public accessibility
4565                                                 //
4566                                                 implementing = null;
4567                                         } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
4568                                                 // We may never be private.
4569                                                 implementing = null;
4570                                         } else if ((modifiers & Modifiers.OVERRIDE) == 0){
4571                                                 //
4572                                                 // We may be protected if we're overriding something.
4573                                                 //
4574                                                 implementing = null;
4575                                         }
4576                                 } 
4577                                         
4578                                 //
4579                                 // Static is not allowed
4580                                 //
4581                                 if ((modifiers & Modifiers.STATIC) != 0){
4582                                         implementing = null;
4583                                 }
4584                         }
4585                         
4586                         //
4587                         // If implementing is still valid, set flags
4588                         //
4589                         if (implementing != null){
4590                                 //
4591                                 // When implementing interface methods, set NewSlot
4592                                 // unless, we are overwriting a method.
4593                                 //
4594                                 if (implementing.DeclaringType.IsInterface){
4595                                         if ((modifiers & Modifiers.OVERRIDE) == 0)
4596                                                 flags |= MethodAttributes.NewSlot;
4597                                 }
4598                                 flags |=
4599                                         MethodAttributes.Virtual |
4600                                         MethodAttributes.HideBySig;
4601
4602                                 // Set Final unless we're virtual, abstract or already overriding a method.
4603                                 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
4604                                         flags |= MethodAttributes.Final;
4605                         }
4606
4607                         DefineMethodBuilder (container, method_name, method.ParameterInfo.Types);
4608
4609                         if (builder == null)
4610                                 return false;
4611
4612                         if ((modifiers & Modifiers.UNSAFE) != 0)
4613                                 builder.InitLocals = false;
4614
4615                         if (implementing != null){
4616                                 //
4617                                 // clear the pending implemntation flag
4618                                 //
4619                                 if (member is Indexer) {
4620                                         pending.ImplementIndexer (
4621                                                 member.InterfaceType, builder, method.ReturnType,
4622                                                 method.ParameterInfo, member.IsExplicitImpl);
4623                                 } else
4624                                         pending.ImplementMethod (
4625                                                 member.InterfaceType, name, method.ReturnType,
4626                                                 method.ParameterInfo, member.IsExplicitImpl);
4627
4628                                 if (member.IsExplicitImpl)
4629                                         container.TypeBuilder.DefineMethodOverride (
4630                                                 builder, implementing);
4631
4632                         }
4633
4634                         TypeManager.AddMethod (builder, method);
4635
4636                         return true;
4637                 }
4638
4639
4640                 /// <summary>
4641                 /// Create the MethodBuilder for the method 
4642                 /// </summary>
4643                 void DefineMethodBuilder (TypeContainer container, string method_name, Type[] ParameterTypes)
4644                 {
4645                         const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
4646
4647                         if ((modifiers & extern_static) == extern_static) {
4648
4649                                 if (method.OptAttributes != null) {
4650                                         Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type);
4651                                         if (dllimport_attribute != null) {
4652                                                 flags |= MethodAttributes.PinvokeImpl;
4653                                                 builder = dllimport_attribute.DefinePInvokeMethod (
4654                                                         container.TypeBuilder, method_name, flags,
4655                                                         method.ReturnType, ParameterTypes);
4656
4657                                                 return;
4658                                         }
4659                                 }
4660
4661                                 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
4662                                 // We are more strict than Microsoft and report CS0626 like error
4663                                 if (method.OptAttributes == null ||
4664                                         !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type)) {
4665                                         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",
4666                                                 method.GetSignatureForError ());
4667                                         return;
4668                                 }
4669                         }
4670
4671                         builder = container.TypeBuilder.DefineMethod (
4672                                 method_name, flags, method.CallingConventions,
4673                                 method.ReturnType, ParameterTypes);
4674                 }
4675
4676                 //
4677                 // Emits the code
4678                 // 
4679                 public void Emit (DeclSpace parent)
4680                 {
4681                         EmitContext ec;
4682                         if ((flags & MethodAttributes.PinvokeImpl) == 0)
4683                                 ec = method.CreateEmitContext (parent, builder.GetILGenerator ());
4684                         else
4685                                 ec = method.CreateEmitContext (parent, null);
4686
4687                         method.ParameterInfo.ApplyAttributes (MethodBuilder);
4688
4689                         ToplevelBlock block = method.Block;
4690                         
4691                         SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
4692
4693                         //
4694                         // Handle destructors specially
4695                         //
4696                         // FIXME: This code generates buggy code
4697                         //
4698                         if (member is Destructor)
4699                                 EmitDestructor (ec, block);
4700                         else
4701                                 ec.EmitTopBlock (method, block);
4702
4703                         if (source != null)
4704                                 source.CloseMethod ();
4705                 }
4706
4707                 void EmitDestructor (EmitContext ec, ToplevelBlock block)
4708                 {
4709                         ILGenerator ig = ec.ig;
4710                         
4711                         Label finish = ig.DefineLabel ();
4712
4713                         block.SetDestructor ();
4714                         
4715                         ig.BeginExceptionBlock ();
4716                         ec.ReturnLabel = finish;
4717                         ec.HasReturnLabel = true;
4718                         ec.EmitTopBlock (method, block);
4719                         
4720                         // ig.MarkLabel (finish);
4721                         ig.BeginFinallyBlock ();
4722                         
4723                         if (ec.ContainerType.BaseType != null) {
4724                                 Expression member_lookup = Expression.MemberLookup (
4725                                         ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
4726                                         "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
4727
4728                                 if (member_lookup != null){
4729                                         MethodGroupExpr base_destructor = ((MethodGroupExpr) member_lookup);
4730                                 
4731                                         ig.Emit (OpCodes.Ldarg_0);
4732                                         ig.Emit (OpCodes.Call, (MethodInfo) base_destructor.Methods [0]);
4733                                 }
4734                         }
4735                         
4736                         ig.EndExceptionBlock ();
4737                         //ig.MarkLabel (ec.ReturnLabel);
4738                         ig.Emit (OpCodes.Ret);
4739                 }
4740         }
4741
4742         // TODO: Should derive from MethodCore
4743         public class Destructor : Method {
4744
4745                 static string[] attribute_targets = new string [] { "method" };
4746
4747                 public Destructor (DeclSpace parent, Expression return_type, int mod,
4748                                    string name, Parameters parameters, Attributes attrs,
4749                                    Location l)
4750                         : base (parent, return_type, mod, false, new MemberName (name, l),
4751                                 parameters, attrs)
4752                 { }
4753
4754                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4755                 {
4756                         if (a.Type == TypeManager.conditional_attribute_type) {
4757                                 Error_ConditionalAttributeIsNotValid ();
4758                                 return;
4759                         }
4760
4761                         base.ApplyAttributeBuilder (a, cb);
4762                 }
4763
4764                 public override string GetSignatureForError ()
4765                 {
4766                         return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
4767                 }
4768
4769                 public override string[] ValidAttributeTargets {
4770                         get {
4771                                 return attribute_targets;
4772                         }
4773                 }
4774         }
4775         
4776         abstract public class MemberBase : MemberCore {
4777                 public Expression Type;
4778
4779                 public MethodAttributes flags;
4780                         
4781                 protected readonly int explicit_mod_flags;
4782
4783                 //
4784                 // The "short" name of this property / indexer / event.  This is the
4785                 // name without the explicit interface.
4786                 //
4787                 public string ShortName {
4788                         get { return MemberName.Name; }
4789                         set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
4790                 }
4791
4792                 public TypeContainer ParentContainer {
4793                         get { return ((TypeContainer) Parent).PartialContainer; }
4794                 }
4795
4796                 //
4797                 // The type of this property / indexer / event
4798                 //
4799                 Type member_type;
4800                 public Type MemberType {
4801                         get {
4802                                 if (member_type == null && Type != null) {
4803                                         Type = Type.ResolveAsTypeTerminal (ResolveContext, false);
4804                                         if (Type != null) {
4805                                                 member_type = Type.Type;
4806                                         }
4807                                 }
4808                                 return member_type;
4809                         }
4810                 }
4811
4812                 //
4813                 // Whether this is an interface member.
4814                 //
4815                 public bool IsInterface;
4816
4817                 //
4818                 // If true, this is an explicit interface implementation
4819                 //
4820                 public bool IsExplicitImpl;
4821
4822                 //
4823                 // The interface type we are explicitly implementing
4824                 //
4825                 public Type InterfaceType = null;
4826
4827                 //
4828                 // The constructor is only exposed to our children
4829                 //
4830                 protected MemberBase (DeclSpace parent, Expression type, int mod,
4831                                       int allowed_mod, int def_mod, MemberName name,
4832                                       Attributes attrs)
4833                         : base (parent, name, attrs)
4834                 {
4835                         explicit_mod_flags = mod;
4836                         Type = type;
4837                         ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, Location);
4838                         IsExplicitImpl = (MemberName.Left != null);
4839                 }
4840
4841                 protected virtual bool CheckBase ()
4842                 {
4843                         if ((ModFlags & Modifiers.PROTECTED) != 0 && ParentContainer.Kind == Kind.Struct) {
4844                                 Report.Error (666, Location, "`{0}': new protected member declared in struct", GetSignatureForError ());
4845                                 return false;
4846                         }
4847    
4848                         if ((RootContext.WarningLevel >= 4) &&
4849                             ((Parent.ModFlags & Modifiers.SEALED) != 0) &&
4850                             ((ModFlags & Modifiers.PROTECTED) != 0) &&
4851                             ((ModFlags & Modifiers.OVERRIDE) == 0) && (Name != "Finalize")) {
4852                                 Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", GetSignatureForError ());
4853                         }
4854                         return true;
4855         }
4856
4857                 protected virtual bool DoDefine ()
4858                 {
4859                         if (Name == null)
4860                                 throw new InternalErrorException ();
4861
4862                         if (IsInterface) {
4863                                 ModFlags = Modifiers.PUBLIC |
4864                                         Modifiers.ABSTRACT |
4865                                         Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE) | (ModFlags & Modifiers.NEW);
4866
4867                                 flags = MethodAttributes.Public |
4868                                         MethodAttributes.Abstract |
4869                                         MethodAttributes.HideBySig |
4870                                         MethodAttributes.NewSlot |
4871                                         MethodAttributes.Virtual;
4872                         } else {
4873                                 if (!ParentContainer.MethodModifiersValid (this))
4874                                         return false;
4875
4876                                 flags = Modifiers.MethodAttr (ModFlags);
4877                         }
4878
4879                         if (MemberType == null)
4880                                 return false;
4881
4882                         if ((Parent.ModFlags & Modifiers.SEALED) != 0 && 
4883                                 (ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0) {
4884                                         Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
4885                                                 GetSignatureForError (), Parent.GetSignatureForError ());
4886                                         return false;
4887                         }
4888                         
4889                         // verify accessibility
4890                         if (!Parent.AsAccessible (MemberType, ModFlags)) {
4891                                 Report.SymbolRelatedToPreviousError (MemberType);
4892                                 if (this is Property)
4893                                         Report.Error (53, Location,
4894                                                       "Inconsistent accessibility: property type `" +
4895                                                       TypeManager.CSharpName (MemberType) + "' is less " +
4896                                                       "accessible than property `" + GetSignatureForError () + "'");
4897                                 else if (this is Indexer)
4898                                         Report.Error (54, Location,
4899                                                       "Inconsistent accessibility: indexer return type `" +
4900                                                       TypeManager.CSharpName (MemberType) + "' is less " +
4901                                                       "accessible than indexer `" + GetSignatureForError () + "'");
4902                                 else if (this is MethodCore) {
4903                                         if (this is Operator)
4904                                                 Report.Error (56, Location,
4905                                                               "Inconsistent accessibility: return type `" +
4906                                                               TypeManager.CSharpName (MemberType) + "' is less " +
4907                                                               "accessible than operator `" + GetSignatureForError () + "'");
4908                                         else
4909                                                 Report.Error (50, Location,
4910                                                               "Inconsistent accessibility: return type `" +
4911                                                               TypeManager.CSharpName (MemberType) + "' is less " +
4912                                                               "accessible than method `" + GetSignatureForError () + "'");
4913                                 } else {
4914                                         Report.Error (52, Location,
4915                                                       "Inconsistent accessibility: field type `" +
4916                                                       TypeManager.CSharpName (MemberType) + "' is less " +
4917                                                       "accessible than field `" + GetSignatureForError () + "'");
4918                                 }
4919                                 return false;
4920                         }
4921
4922                         if (IsExplicitImpl) {
4923                                 Expression expr = MemberName.Left.GetTypeExpression ();
4924                                 TypeExpr texpr = expr.ResolveAsTypeTerminal (ResolveContext, false);
4925                                 if (texpr == null)
4926                                         return false;
4927
4928                                 InterfaceType = texpr.Type;
4929
4930                                 if (!InterfaceType.IsInterface) {
4931                                         Report.Error (538, Location, "`{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
4932                                         return false;
4933                                 }
4934                                 
4935                                 if (!ParentContainer.VerifyImplements (this))
4936                                         return false;
4937                                 
4938                                 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4939                                 
4940                         }
4941                         return true;
4942                 }
4943
4944                 protected bool IsTypePermitted ()
4945                 {
4946                         if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
4947                                 Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
4948                                 return false;
4949                         }
4950                         return true;
4951                 }
4952
4953                 protected override bool VerifyClsCompliance()
4954                 {
4955                         if (base.VerifyClsCompliance ()) {
4956                                 return true;
4957                         }
4958
4959                         if (IsInterface && HasClsCompliantAttribute && Parent.IsClsComplianceRequired ()) {
4960                                 Report.Error (3010, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
4961                         }
4962                         return false;
4963                 }
4964
4965         }
4966
4967         //
4968         // Fields and Events both generate FieldBuilders, we use this to share 
4969         // their common bits.  This is also used to flag usage of the field
4970         //
4971         abstract public class FieldBase : MemberBase {
4972                 public FieldBuilder  FieldBuilder;
4973                 public Status status;
4974                 protected Expression initializer;
4975                 ExpressionStatement initializerStatement;
4976
4977                 [Flags]
4978                 public enum Status : byte {
4979                         HAS_OFFSET = 4          // Used by FieldMember.
4980                 }
4981
4982                 static string[] attribute_targets = new string [] { "field" };
4983
4984                 /// <summary>
4985                 ///  Symbol with same name in base class/struct
4986                 /// </summary>
4987                 public MemberInfo conflict_symbol;
4988
4989                 protected FieldBase (DeclSpace parent, Expression type, int mod,
4990                                      int allowed_mod, MemberName name, Attributes attrs)
4991                         : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE,
4992                                 name, attrs)
4993                 {
4994                 }
4995
4996                 public override AttributeTargets AttributeTargets {
4997                         get {
4998                                 return AttributeTargets.Field;
4999                         }
5000                 }
5001
5002                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5003                 {
5004                         if (a.Type == TypeManager.marshal_as_attr_type) {
5005                                 UnmanagedMarshal marshal = a.GetMarshal (this);
5006                                 if (marshal != null) {
5007                                         FieldBuilder.SetMarshal (marshal);
5008                                 }
5009                                 return;
5010                         }
5011
5012                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
5013                                 a.Error_InvalidSecurityParent ();
5014                                 return;
5015                         }
5016
5017                         FieldBuilder.SetCustomAttribute (cb);
5018                 }
5019
5020                 public void EmitInitializer (EmitContext ec)
5021                 {
5022                         initializerStatement.EmitStatement (ec);
5023                 }
5024
5025                 protected override bool CheckBase ()
5026                 {
5027                         if (!base.CheckBase ())
5028                                 return false;
5029  
5030                         // TODO: Implement
5031                         if (IsInterface)
5032                                 return true;
5033  
5034                         conflict_symbol = ParentContainer.FindBaseMemberWithSameName (Name, false);
5035                         if (conflict_symbol == null) {
5036                                 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
5037                                         Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
5038                                 }
5039                                 return true;
5040                         }
5041  
5042                         if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
5043                                 Report.SymbolRelatedToPreviousError (conflict_symbol);
5044                                 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
5045                                         GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
5046                         }
5047  
5048                         return true;
5049                 }
5050
5051                 public Expression Initializer {
5052                         set {
5053                                 if (value != null) {
5054                                         this.initializer = value;
5055                                         ParentContainer.RegisterFieldForInitialization (this);
5056                                 }
5057                         }
5058                 }
5059
5060                 protected virtual bool IsFieldClsCompliant {
5061                         get {
5062                                 if (FieldBuilder == null)
5063                                         return true;
5064
5065                                 return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
5066                         }
5067                 }
5068
5069                 public Expression ResolveInitializer ()
5070                 {
5071                         // TODO: again it's too heavy-weight
5072                         EmitContext ec = new EmitContext (this, Parent, Location, null, null, ModFlags);
5073                         ec.IsFieldInitializer = true;
5074                         initializer = initializer.Resolve (ec);
5075                         if (initializer == null)
5076                                 return null;
5077
5078                         FieldExpr fe = new FieldExpr (FieldBuilder, Location, true);
5079                         if ((ModFlags & Modifiers.STATIC) == 0) 
5080                         {
5081                                 fe.InstanceExpression = CompilerGeneratedThis.Instance;
5082                         }
5083
5084                         initializerStatement = new Assign (fe, initializer, Location).ResolveStatement (ec);
5085                         return initializer;
5086                 }
5087
5088                 public bool HasDefaultInitializer
5089                 {
5090                         get
5091                         {
5092                                 Constant c = initializer as Constant;
5093                                 if (c == null)
5094                                         return false;
5095
5096                                 return c.IsDefaultInitializer (MemberType);
5097                         }
5098                 }
5099
5100                 public override string[] ValidAttributeTargets 
5101                 {
5102                         get {
5103                                 return attribute_targets;
5104                         }
5105                 }
5106
5107                 protected override bool VerifyClsCompliance ()
5108                 {
5109                         if (!base.VerifyClsCompliance ())
5110                                 return false;
5111
5112                         if (!IsFieldClsCompliant) {
5113                                 Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant", GetSignatureForError ());
5114                         }
5115                         return true;
5116                 }
5117
5118
5119                 public void SetAssigned ()
5120                 {
5121                         caching_flags |= Flags.IsAssigned;
5122                 }
5123         }
5124
5125         public abstract class FieldMember : FieldBase
5126         {
5127                 protected FieldMember (DeclSpace parent, Expression type, int mod,
5128                         int allowed_mod, MemberName name, Attributes attrs)
5129                         : base (parent, type, mod, allowed_mod | Modifiers.ABSTRACT, name, attrs)
5130                 {
5131                         if ((mod & Modifiers.ABSTRACT) != 0)
5132                                 Report.Error (681, Location, "The modifier 'abstract' is not valid on fields. Try using a property instead");
5133                 }
5134
5135                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5136                 {
5137                         if (a.Type == TypeManager.field_offset_attribute_type)
5138                         {
5139                                 status |= Status.HAS_OFFSET;
5140
5141                                 if (!ParentContainer.HasExplicitLayout) {
5142                                         Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
5143                                         return;
5144                                 }
5145
5146                                 if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
5147                                         Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
5148                                         return;
5149                                 }
5150                         }
5151
5152 #if NET_2_0
5153                         if (a.Type == TypeManager.fixed_buffer_attr_type) {
5154                                 Report.Error (1716, Location, "Do not use 'System.Runtime.CompilerServices.FixedBuffer' attribute. Use the 'fixed' field modifier instead");
5155                                 return;
5156                         }
5157 #endif
5158
5159                         base.ApplyAttributeBuilder (a, cb);
5160                 }
5161
5162                 public override bool Define()
5163                 {
5164                         if (MemberType == null || Type == null)
5165                                 return false;
5166
5167                         if (MemberType == TypeManager.void_type) {
5168                                 Report.Error (1547, Location, "Keyword 'void' cannot be used in this context");
5169                                 return false;
5170                         }
5171
5172                         if (!CheckBase ())
5173                                 return false;
5174                         
5175                         if (!Parent.AsAccessible (MemberType, ModFlags)) {
5176                                 Report.Error (52, Location,
5177                                         "Inconsistent accessibility: field type `" +
5178                                         TypeManager.CSharpName (MemberType) + "' is less " +
5179                                         "accessible than field `" + GetSignatureForError () + "'");
5180                                 return false;
5181                         }
5182
5183                         if (!IsTypePermitted ())
5184                                 return false;
5185
5186                         return true;
5187                 }
5188
5189                 public override void Emit ()
5190                 {
5191                         if (OptAttributes != null) {
5192                                 OptAttributes.Emit ();
5193                         }
5194
5195                         if (((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0 && ParentContainer.HasExplicitLayout) {
5196                                 Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
5197                         }
5198
5199                         base.Emit ();
5200                 }
5201
5202                 //
5203                 //   Represents header string for documentation comment.
5204                 //
5205                 public override string DocCommentHeader {
5206                         get { return "F:"; }
5207                 }
5208         }
5209
5210         interface IFixedBuffer
5211         {
5212                 FieldInfo Element { get; }
5213                 Type ElementType { get; }
5214         }
5215
5216         public class FixedFieldExternal: IFixedBuffer
5217         {
5218                 FieldInfo element_field;
5219
5220                 public FixedFieldExternal (FieldInfo fi)
5221                 {
5222                         element_field = fi.FieldType.GetField (FixedField.FixedElementName);
5223                 }
5224
5225                 #region IFixedField Members
5226
5227                 public FieldInfo Element {
5228                         get {
5229                                 return element_field;
5230                         }
5231                 }
5232
5233                 public Type ElementType {
5234                         get {
5235                                 return element_field.FieldType;
5236                         }
5237                 }
5238
5239                 #endregion
5240         }
5241
5242         /// <summary>
5243         /// Fixed buffer implementation
5244         /// </summary>
5245         public class FixedField : FieldMember, IFixedBuffer
5246         {
5247                 public const string FixedElementName = "FixedElementField";
5248                 static int GlobalCounter = 0;
5249                 static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
5250                 static FieldInfo[] fi;
5251
5252                 TypeBuilder fixed_buffer_type;
5253                 FieldBuilder element;
5254                 Expression size_expr;
5255                 int buffer_size;
5256
5257                 const int AllowedModifiers =
5258                         Modifiers.NEW |
5259                         Modifiers.PUBLIC |
5260                         Modifiers.PROTECTED |
5261                         Modifiers.INTERNAL |
5262                         Modifiers.PRIVATE;
5263
5264                 public FixedField (DeclSpace parent, Expression type, int mod, string name,
5265                         Expression size_expr, Attributes attrs, Location loc):
5266                         base (parent, type, mod, AllowedModifiers, new MemberName (name, loc), attrs)
5267                 {
5268                         if (RootContext.Version == LanguageVersion.ISO_1)
5269                                 Report.FeatureIsNotStandardized (loc, "fixed size buffers");
5270
5271                         this.size_expr = size_expr;
5272                 }
5273
5274                 public override bool Define()
5275                 {
5276 #if !NET_2_0
5277                         if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) != 0)
5278                                 Report.Warning (-23, 1, Location, "Only private or internal fixed sized buffers are supported by .NET 1.x");
5279 #endif
5280
5281                         if (ParentContainer.Kind != Kind.Struct) {
5282                                 Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs",
5283                                         GetSignatureForError ());
5284                                 return false;
5285                         }
5286
5287                         if (!base.Define ())
5288                                 return false;
5289
5290                         if (!TypeManager.IsPrimitiveType (MemberType)) {
5291                                 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",
5292                                         GetSignatureForError ());
5293                                 return false;
5294                         }
5295
5296                         EmitContext ec = new EmitContext (this, Parent, Location, null, null, ModFlags);
5297                         Constant c = size_expr.ResolveAsConstant (ec, this);
5298                         if (c == null)
5299                                 return false;
5300
5301                         IntConstant buffer_size_const = c.ToInt (Location);
5302                         if (buffer_size_const == null)
5303                                 return false;
5304
5305                         buffer_size = buffer_size_const.Value;
5306
5307                         if (buffer_size <= 0) {
5308                                 Report.Error (1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError ());
5309                                 return false;
5310                         }
5311
5312                         int type_size = Expression.GetTypeSize (MemberType);
5313
5314                         if (buffer_size > int.MaxValue / type_size) {
5315                                 Report.Error (1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit",
5316                                         GetSignatureForError (), buffer_size.ToString (), TypeManager.CSharpName (MemberType));
5317                                 return false;
5318                         }
5319
5320                         buffer_size *= type_size;
5321
5322                         // Define nested
5323                         string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
5324
5325                         fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
5326                                 TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
5327                         element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
5328                         RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
5329
5330                         FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
5331                         TypeManager.RegisterFieldBase (FieldBuilder, this);
5332
5333                         return true;
5334                 }
5335
5336                 public override void Emit()
5337                 {
5338                         if (fi == null)
5339                                 fi = new FieldInfo [] { TypeManager.struct_layout_attribute_type.GetField ("Size") };
5340
5341                         object[] fi_val = new object[1];
5342                         fi_val [0] = buffer_size;
5343
5344                         CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.struct_layout_attribute_ctor, 
5345                                 ctor_args, fi, fi_val);
5346                         fixed_buffer_type.SetCustomAttribute (cab);
5347
5348 #if NET_2_0
5349                         cab = new CustomAttributeBuilder (TypeManager.fixed_buffer_attr_ctor, new object[] { MemberType, buffer_size } );
5350                         FieldBuilder.SetCustomAttribute (cab);
5351 #endif
5352                         base.Emit ();
5353                 }
5354
5355                 protected override bool IsFieldClsCompliant {
5356                         get {
5357                                 return false;
5358                         }
5359                 }
5360
5361                 #region IFixedField Members
5362
5363                 public FieldInfo Element {
5364                         get {
5365                                 return element;
5366                         }
5367                 }
5368
5369                 public Type ElementType {
5370                         get {
5371                                 return MemberType;
5372                         }
5373                 }
5374
5375                 #endregion
5376         }
5377
5378         //
5379         // The Field class is used to represents class/struct fields during parsing.
5380         //
5381         public class Field : FieldMember {
5382                 // <summary>
5383                 //   Modifiers allowed in a class declaration
5384                 // </summary>
5385                 const int AllowedModifiers =
5386                         Modifiers.NEW |
5387                         Modifiers.PUBLIC |
5388                         Modifiers.PROTECTED |
5389                         Modifiers.INTERNAL |
5390                         Modifiers.PRIVATE |
5391                         Modifiers.STATIC |
5392                         Modifiers.VOLATILE |
5393                         Modifiers.UNSAFE |
5394                         Modifiers.READONLY;
5395
5396                 public Field (DeclSpace parent, Expression type, int mod, string name,
5397                               Attributes attrs, Location loc)
5398                         : base (parent, type, mod, AllowedModifiers, new MemberName (name, loc),
5399                                 attrs)
5400                 {
5401                 }
5402
5403                 public override bool Define ()
5404                 {
5405                         if (!base.Define ())
5406                                 return false;
5407
5408                         if (RootContext.WarningLevel > 1){
5409                                 Type ptype = Parent.TypeBuilder.BaseType;
5410
5411                                 // ptype is only null for System.Object while compiling corlib.
5412                                 if (ptype != null){
5413                                         TypeContainer.FindMembers (
5414                                                 ptype, MemberTypes.Method,
5415                                                 BindingFlags.Public |
5416                                                 BindingFlags.Static | BindingFlags.Instance,
5417                                                 System.Type.FilterName, Name);
5418                                 }
5419                         }
5420
5421                         if ((ModFlags & Modifiers.VOLATILE) != 0){
5422                                 if (!MemberType.IsClass){
5423                                         Type vt = MemberType;
5424                                         
5425                                         if (TypeManager.IsEnumType (vt))
5426                                                 vt = TypeManager.EnumToUnderlying (MemberType);
5427
5428                                         if (!((vt == TypeManager.bool_type) ||
5429                                               (vt == TypeManager.sbyte_type) ||
5430                                               (vt == TypeManager.byte_type) ||
5431                                               (vt == TypeManager.short_type) ||
5432                                               (vt == TypeManager.ushort_type) ||
5433                                               (vt == TypeManager.int32_type) ||
5434                                               (vt == TypeManager.uint32_type) ||    
5435                                               (vt == TypeManager.char_type) ||
5436                                               (vt == TypeManager.float_type) ||
5437                                               (!vt.IsValueType))){
5438                                                 Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'",
5439                                                         GetSignatureForError (), TypeManager.CSharpName (vt));
5440                                                 return false;
5441                                         }
5442                                 }
5443
5444                                 if ((ModFlags & Modifiers.READONLY) != 0){
5445                                         Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly",
5446                                                 GetSignatureForError ());
5447                                         return false;
5448                                 }
5449                         }
5450
5451                         FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
5452
5453                         if (ParentContainer.Kind == Kind.Struct && 
5454                             ((fa & FieldAttributes.Static) == 0) &&
5455                             MemberType == Parent.TypeBuilder &&
5456                             !TypeManager.IsBuiltinType (MemberType)){
5457                                 Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name + 
5458                                               "' causes a cycle in the structure layout");
5459                                 return false;
5460                         }
5461
5462                         try {
5463                                 FieldBuilder = Parent.TypeBuilder.DefineField (
5464                                         Name, MemberType, Modifiers.FieldAttr (ModFlags));
5465
5466                                 TypeManager.RegisterFieldBase (FieldBuilder, this);
5467                         }
5468                         catch (ArgumentException) {
5469                                 Report.Warning (-24, 1, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
5470                                 return false;
5471                         }
5472
5473                         return true;
5474                 }
5475
5476                 protected override bool VerifyClsCompliance ()
5477                 {
5478                         if (!base.VerifyClsCompliance ())
5479                                 return false;
5480
5481                         if ((ModFlags & Modifiers.VOLATILE) != 0) {
5482                                 Report.Warning (3026, 1, Location, "CLS-compliant field `{0}' cannot be volatile", GetSignatureForError ());
5483                         }
5484
5485                         return true;
5486                 }
5487         }
5488
5489         //
5490         // `set' and `get' accessors are represented with an Accessor.
5491         // 
5492         public class Accessor : IIteratorContainer {
5493                 //
5494                 // Null if the accessor is empty, or a Block if not
5495                 //
5496                 public const int AllowedModifiers = 
5497                         Modifiers.PUBLIC |
5498                         Modifiers.PROTECTED |
5499                         Modifiers.INTERNAL |
5500                         Modifiers.PRIVATE;
5501                 
5502                 public ToplevelBlock Block;
5503                 public Attributes Attributes;
5504                 public Location Location;
5505                 public int ModFlags;
5506                 public bool Yields;
5507                 
5508                 public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
5509                 {
5510                         Block = b;
5511                         Attributes = attrs;
5512                         Location = loc;
5513                         ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
5514                 }
5515
5516                 public void SetYields ()
5517                 {
5518                         Yields = true;
5519                 }
5520         }
5521
5522         // Ooouh Martin, templates are missing here.
5523         // When it will be possible move here a lot of child code and template method type.
5524         public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
5525                 protected MethodData method_data;
5526                 protected ToplevelBlock block;
5527                 protected ListDictionary declarative_security;
5528
5529                 // The accessor are created event if they are not wanted.
5530                 // But we need them because their names are reserved.
5531                 // Field says whether accessor will be emited or not
5532                 public readonly bool IsDummy;
5533
5534                 protected readonly string prefix;
5535
5536                 ReturnParameter return_attributes;
5537
5538                 public AbstractPropertyEventMethod (MemberBase member, string prefix)
5539                         : base (member.Parent, SetupName (prefix, member, member.Location), null)
5540                 {
5541                         this.prefix = prefix;
5542                         IsDummy = true;
5543                 }
5544
5545                 public AbstractPropertyEventMethod (MemberBase member, Accessor accessor,
5546                                                     string prefix)
5547                         : base (member.Parent, SetupName (prefix, member, accessor.Location),
5548                                 accessor.Attributes)
5549                 {
5550                         this.prefix = prefix;
5551                         this.block = accessor.Block;
5552                 }
5553
5554                 static MemberName SetupName (string prefix, MemberBase member, Location loc)
5555                 {
5556                         return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
5557                 }
5558
5559                 public void UpdateName (MemberBase member)
5560                 {
5561                         SetMemberName (SetupName (prefix, member, Location));
5562                 }
5563
5564                 #region IMethodData Members
5565
5566                 public ToplevelBlock Block {
5567                         get {
5568                                 return block;
5569                         }
5570
5571                         set {
5572                                 block = value;
5573                         }
5574                 }
5575
5576                 public CallingConventions CallingConventions {
5577                         get {
5578                                 return CallingConventions.Standard;
5579                         }
5580                 }
5581
5582                 public bool IsExcluded ()
5583                 {
5584                         return false;
5585                 }
5586
5587                 public MemberName MethodName {
5588                         get {
5589                                 return MemberName;
5590                         }
5591                 }
5592
5593                 public Type[] ParameterTypes { 
5594                         get {
5595                                 return ParameterInfo.Types;
5596                         }
5597                 }
5598
5599                 public abstract Parameters ParameterInfo { get ; }
5600                 public abstract Type ReturnType { get; }
5601                 public abstract EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
5602
5603                 #endregion
5604
5605                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5606                 {
5607                         if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
5608                                         a.Type == TypeManager.conditional_attribute_type) {
5609                                 Report.Error (1667, a.Location,
5610                                         "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
5611                                         TypeManager.CSharpName (a.Type), a.GetValidTargets ());
5612                                 return;
5613                         }
5614
5615                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
5616                                 if (declarative_security == null)
5617                                         declarative_security = new ListDictionary ();
5618                                 a.ExtractSecurityPermissionSet (declarative_security);
5619                                 return;
5620                         }
5621
5622                         if (a.Target == AttributeTargets.Method) {
5623                                 method_data.MethodBuilder.SetCustomAttribute (cb);
5624                                 return;
5625                         }
5626
5627                         if (a.Target == AttributeTargets.ReturnValue) {
5628                                 if (return_attributes == null)
5629                                         return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5630
5631                                 return_attributes.ApplyAttributeBuilder (a, cb);
5632                                 return;
5633                         }
5634
5635                         ApplyToExtraTarget (a, cb);
5636                 }
5637
5638                 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
5639                 {
5640                         System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
5641                 }
5642
5643                 public override bool Define()
5644                 {
5645                         throw new NotSupportedException ();
5646                 }
5647
5648                 public void Emit (DeclSpace parent)
5649                 {
5650                         EmitMethod (parent);
5651
5652                         if (OptAttributes != null)
5653                                 OptAttributes.Emit ();
5654
5655                         if (declarative_security != null) {
5656                                 foreach (DictionaryEntry de in declarative_security) {
5657                                         method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
5658                                 }
5659                         }
5660
5661                         block = null;
5662                 }
5663
5664                 protected virtual void EmitMethod (DeclSpace parent)
5665                 {
5666                         method_data.Emit (parent);
5667                 }
5668
5669                 public override bool IsClsComplianceRequired()
5670                 {
5671                         return false;
5672                 }
5673
5674                 public bool IsDuplicateImplementation (MethodCore method)
5675                 {
5676                         if (!MemberName.Equals (method.MemberName))
5677                                 return false;
5678
5679                         Type[] param_types = method.ParameterTypes;
5680
5681                         if (param_types.Length != ParameterTypes.Length)
5682                                 return false;
5683
5684                         for (int i = 0; i < param_types.Length; i++)
5685                                 if (param_types [i] != ParameterTypes [i])
5686                                         return false;
5687
5688                         Report.SymbolRelatedToPreviousError (method);
5689                         Report.Error (111, Location, TypeContainer.Error111, method.GetSignatureForError ());
5690                         return true;
5691                 }
5692
5693                 public override bool IsUsed
5694                 {
5695                         get {
5696                                 if (IsDummy)
5697                                         return false;
5698
5699                                 return base.IsUsed;
5700                         }
5701                 }
5702
5703                 public new Location Location { 
5704                         get {
5705                                 return base.Location;
5706                         }
5707                 }
5708
5709                 //
5710                 //   Represents header string for documentation comment.
5711                 //
5712                 public override string DocCommentHeader {
5713                         get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
5714                 }
5715
5716         }
5717
5718         //
5719         // Properties and Indexers both generate PropertyBuilders, we use this to share 
5720         // their common bits.
5721         //
5722         abstract public class PropertyBase : MethodCore {
5723
5724                 public class GetMethod : PropertyMethod
5725                 {
5726                         static string[] attribute_targets = new string [] { "method", "return" };
5727
5728                         public GetMethod (MethodCore method):
5729                                 base (method, "get_")
5730                         {
5731                         }
5732
5733                         public GetMethod (MethodCore method, Accessor accessor):
5734                                 base (method, accessor, "get_")
5735                         {
5736                         }
5737
5738                         public override MethodBuilder Define (DeclSpace parent)
5739                         {
5740                                 base.Define (parent);
5741                                 
5742                                 method_data = new MethodData (method, ModFlags, flags, this);
5743
5744                                 if (!method_data.Define (parent))
5745                                         return null;
5746
5747                                 return method_data.MethodBuilder;
5748                         }
5749
5750                         public override Type ReturnType {
5751                                 get {
5752                                         return method.MemberType;
5753                                 }
5754                         }
5755
5756                         public override Parameters ParameterInfo {
5757                                 get {
5758                                         return Parameters.EmptyReadOnlyParameters;
5759                                 }
5760                         }
5761
5762                         public override string[] ValidAttributeTargets {
5763                                 get {
5764                                         return attribute_targets;
5765                                 }
5766                         }
5767                 }
5768
5769                 public class SetMethod : PropertyMethod {
5770
5771                         static string[] attribute_targets = new string [] { "method", "param", "return" };
5772                         ImplicitParameter param_attr;
5773                         protected Parameters parameters;
5774
5775                         public SetMethod (MethodCore method):
5776                                 base (method, "set_")
5777                         {
5778                         }
5779
5780                         public SetMethod (MethodCore method, Accessor accessor):
5781                                 base (method, accessor, "set_")
5782                         {
5783                         }
5784
5785                         protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
5786                         {
5787                                 if (a.Target == AttributeTargets.Parameter) {
5788                                         if (param_attr == null)
5789                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5790
5791                                         param_attr.ApplyAttributeBuilder (a, cb);
5792                                         return;
5793                                 }
5794
5795                                 base.ApplyAttributeBuilder (a, cb);
5796                         }
5797
5798                         public override Parameters ParameterInfo {
5799                                 get {
5800                                         return parameters;
5801                                 }
5802                         }
5803
5804                         protected virtual void DefineParameters ()
5805                         {
5806                                 parameters = new Parameters (
5807                                         new Parameter[] { new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, Location) },
5808                                         new Type[] { method.MemberType });
5809                         }
5810
5811                         public override MethodBuilder Define (DeclSpace parent)
5812                         {
5813                                 DefineParameters ();
5814                                 if (IsDummy)
5815                                         return null;
5816
5817                                 base.Define (parent);
5818
5819                                 method_data = new MethodData (method, ModFlags, flags, this);
5820
5821                                 if (!method_data.Define (parent))
5822                                         return null;
5823
5824                                 return method_data.MethodBuilder;
5825                         }
5826
5827                         public override Type ReturnType {
5828                                 get {
5829                                         return TypeManager.void_type;
5830                                 }
5831                         }
5832
5833                         public override string[] ValidAttributeTargets {
5834                                 get {
5835                                         return attribute_targets;
5836                                 }
5837                         }
5838                 }
5839
5840                 static string[] attribute_targets = new string [] { "property" };
5841
5842                 public abstract class PropertyMethod : AbstractPropertyEventMethod
5843                 {
5844                         protected readonly MethodCore method;
5845                         protected MethodAttributes flags;
5846                         bool yields;
5847
5848                         public PropertyMethod (MethodCore method, string prefix)
5849                                 : base (method, prefix)
5850                         {
5851                                 this.method = method;
5852                         }
5853
5854                         public PropertyMethod (MethodCore method, Accessor accessor,
5855                                                string prefix)
5856                                 : base (method, accessor, prefix)
5857                         {
5858                                 this.method = method;
5859                                 this.ModFlags = accessor.ModFlags;
5860                                 yields = accessor.Yields;
5861
5862                                 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
5863                                         Report.FeatureIsNotStandardized (Location, "access modifiers on properties");
5864                                 }
5865                         }
5866
5867                         public override AttributeTargets AttributeTargets {
5868                                 get {
5869                                         return AttributeTargets.Method;
5870                                 }
5871                         }
5872
5873                         public override bool IsClsComplianceRequired()
5874                         {
5875                                 return method.IsClsComplianceRequired ();
5876                         }
5877
5878                         public virtual MethodBuilder Define (DeclSpace parent)
5879                         {
5880                                 if (!method.CheckAbstractAndExtern (block != null))
5881                                         return null;
5882
5883                                 TypeContainer container = ((TypeContainer) parent).PartialContainer;
5884
5885                                 //
5886                                 // Check for custom access modifier
5887                                 //
5888                                 if (ModFlags == 0) {
5889                                         ModFlags = method.ModFlags;
5890                                         flags = method.flags;
5891                                 } else {
5892                                         if (container.Kind == Kind.Interface)
5893                                                 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
5894                                                         GetSignatureForError ());
5895
5896                                         if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
5897                                                 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
5898                                         }
5899
5900                                         CheckModifiers (ModFlags);
5901                                         ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
5902                                         ModFlags |= Modifiers.PROPERTY_CUSTOM;
5903                                         flags = Modifiers.MethodAttr (ModFlags);
5904                                         flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
5905                                 }
5906
5907                                 //
5908                                 // Setup iterator if we are one
5909                                 //
5910                                 if (yields) {
5911                                         Iterator iterator = new Iterator (this, Parent as TypeContainer, ModFlags);
5912                                         
5913                                         if (!iterator.DefineIterator ())
5914                                                 return null;
5915                                 }
5916
5917                                 return null;
5918                         }
5919
5920                         public bool HasCustomAccessModifier
5921                         {
5922                                 get {
5923                                         return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
5924                                 }
5925                         }
5926
5927                         public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
5928                         {
5929                                 return new EmitContext (method,
5930                                         ds, method.Parent, method.Location, ig, ReturnType,
5931                                         method.ModFlags, false);
5932                         }
5933
5934                         public override ObsoleteAttribute GetObsoleteAttribute ()
5935                         {
5936                                 return method.GetObsoleteAttribute ();
5937                         }
5938
5939                         public override string GetSignatureForError()
5940                         {
5941                                 return method.GetSignatureForError () + '.' + prefix.Substring (0, 3);
5942                         }
5943                         
5944                         void CheckModifiers (int modflags)
5945                         {
5946                                 int flags = 0;
5947                                 int mflags = method.ModFlags & Modifiers.Accessibility;
5948
5949                                 if ((mflags & Modifiers.PUBLIC) != 0) {
5950                                         flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
5951                                 }
5952                                 else if ((mflags & Modifiers.PROTECTED) != 0) {
5953                                         if ((mflags & Modifiers.INTERNAL) != 0)
5954                                                 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
5955
5956                                         flags |= Modifiers.PRIVATE;
5957                                 }
5958                                 else if ((mflags & Modifiers.INTERNAL) != 0)
5959                                         flags |= Modifiers.PRIVATE;
5960
5961                                 if ((mflags == modflags) || (modflags & (~flags)) != 0) {
5962                                         Report.Error (273, Location,
5963                                                 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
5964                                                 GetSignatureForError (), method.GetSignatureForError ());
5965                                 }
5966                         }
5967
5968                         public override bool MarkForDuplicationCheck ()
5969                         {
5970                                 caching_flags |= Flags.TestMethodDuplication;
5971                                 return true;
5972                         }
5973                 }
5974
5975                 public PropertyMethod Get, Set;
5976                 public PropertyBuilder PropertyBuilder;
5977                 public MethodBuilder GetBuilder, SetBuilder;
5978
5979                 protected EmitContext ec;
5980
5981                 public PropertyBase (DeclSpace parent, Expression type, int mod_flags,
5982                                      int allowed_mod, bool is_iface, MemberName name,
5983                                      Parameters parameters, Attributes attrs)
5984                         : base (parent, type, mod_flags, allowed_mod, is_iface, name,
5985                                 attrs, parameters)
5986                 {
5987                 }
5988
5989                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5990                 {
5991                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
5992                                 a.Error_InvalidSecurityParent ();
5993                                 return;
5994                         }
5995
5996                         PropertyBuilder.SetCustomAttribute (cb);
5997                 }
5998
5999                 public override AttributeTargets AttributeTargets {
6000                         get {
6001                                 return AttributeTargets.Property;
6002                         }
6003                 }
6004
6005                 public override bool Define ()
6006                 {
6007                         if (!DoDefine ())
6008                                 return false;
6009
6010                         if (!IsTypePermitted ())
6011                                 return false;
6012
6013                         return true;
6014                 }
6015
6016                 protected override bool DoDefine ()
6017                 {
6018                         if (!base.DoDefine ())
6019                                 return false;
6020
6021                         //
6022                         // Accessors modifiers check
6023                         //
6024                         if (Get.ModFlags != 0 && Set.ModFlags != 0) {
6025                                 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
6026                                                 GetSignatureForError ());
6027                                 return false;
6028                         }
6029
6030                         if ((Get.IsDummy || Set.IsDummy)
6031                                         && (Get.ModFlags != 0 || Set.ModFlags != 0) && (ModFlags & Modifiers.OVERRIDE) == 0) {
6032                                 Report.Error (276, Location, 
6033                                         "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
6034                                         GetSignatureForError ());
6035                                 return false;
6036                         }
6037
6038                         if (MemberType.IsAbstract && MemberType.IsSealed) {
6039                                 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
6040                                 return false;
6041                         }
6042
6043                         return true;
6044                 }
6045
6046                 protected override bool CheckForDuplications ()
6047                 {
6048                         ArrayList ar = ParentContainer.Indexers;
6049                         if (ar != null) {
6050                                 int arLen = ar.Count;
6051                                         
6052                                 for (int i = 0; i < arLen; i++) {
6053                                         Indexer m = (Indexer) ar [i];
6054                                         if (IsDuplicateImplementation (m))
6055                                                 return false;
6056                                 }
6057                         }
6058
6059                         ar = ParentContainer.Properties;
6060                         if (ar != null) {
6061                                 int arLen = ar.Count;
6062                                         
6063                                 for (int i = 0; i < arLen; i++) {
6064                                         Property m = (Property) ar [i];
6065                                         if (IsDuplicateImplementation (m))
6066                                                 return false;
6067                                 }
6068                         }
6069
6070                         return true;
6071                 }
6072
6073                 // TODO: rename to Resolve......
6074                 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
6075                 {
6076                         PropertyInfo base_property = ParentContainer.BaseCache.FindMemberToOverride (
6077                                 Parent.TypeBuilder, Name, ParameterTypes, true) as PropertyInfo;
6078   
6079                         if (base_property == null)
6080                                 return null;
6081   
6082                         base_ret_type = base_property.PropertyType;
6083                         MethodInfo get_accessor = base_property.GetGetMethod (true);
6084                         MethodInfo set_accessor = base_property.GetSetMethod (true);
6085                         MethodAttributes get_accessor_access, set_accessor_access;
6086
6087                         if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6088                                 if (Get != null && !Get.IsDummy && get_accessor == null) {
6089                                         Report.SymbolRelatedToPreviousError (base_property);
6090                                         Report.Error (545, Location, "`{0}.get': cannot override because `{1}' does not have an overridable get accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6091                                 }
6092
6093                                 if (Set != null && !Set.IsDummy && set_accessor == null) {
6094                                         Report.SymbolRelatedToPreviousError (base_property);
6095                                         Report.Error (546, Location, "`{0}.set': cannot override because `{1}' does not have an overridable set accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6096                                 }
6097                         }
6098                         
6099                         //
6100                         // Check base class accessors access
6101                         //
6102
6103                         // TODO: rewrite to reuse Get|Set.CheckAccessModifiers and share code there
6104                         get_accessor_access = set_accessor_access = 0;
6105                         if ((ModFlags & Modifiers.NEW) == 0) {
6106                                 if (get_accessor != null) {
6107                                         MethodAttributes get_flags = Modifiers.MethodAttr (Get.ModFlags != 0 ? Get.ModFlags : ModFlags);
6108                                         get_accessor_access = (get_accessor.Attributes & MethodAttributes.MemberAccessMask);
6109
6110                                         if (!Get.IsDummy && !CheckAccessModifiers (get_flags & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
6111                                                 Error_CannotChangeAccessModifiers (get_accessor, get_accessor_access,  ".get");
6112                                 }
6113
6114                                 if (set_accessor != null)  {
6115                                         MethodAttributes set_flags = Modifiers.MethodAttr (Set.ModFlags != 0 ? Set.ModFlags : ModFlags);
6116                                         set_accessor_access = (set_accessor.Attributes & MethodAttributes.MemberAccessMask);
6117
6118                                         if (!Set.IsDummy && !CheckAccessModifiers (set_flags & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6119                                                 Error_CannotChangeAccessModifiers (set_accessor, set_accessor_access, ".set");
6120                                 }
6121                         }
6122
6123                         //
6124                         // Get the less restrictive access
6125                         //
6126                         return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6127                 }
6128
6129                 public override void Emit ()
6130                 {
6131                         //
6132                         // The PropertyBuilder can be null for explicit implementations, in that
6133                         // case, we do not actually emit the ".property", so there is nowhere to
6134                         // put the attribute
6135                         //
6136                         if (PropertyBuilder != null && OptAttributes != null)
6137                                 OptAttributes.Emit ();
6138
6139                         if (!Get.IsDummy)
6140                                 Get.Emit (Parent);
6141
6142                         if (!Set.IsDummy)
6143                                 Set.Emit (Parent);
6144
6145                         base.Emit ();
6146                 }
6147
6148                 /// <summary>
6149                 /// Tests whether accessors are not in collision with some method (CS0111)
6150                 /// </summary>
6151                 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6152                 {
6153                         return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6154                 }
6155
6156                 public override bool IsUsed
6157                 {
6158                         get {
6159                                 if (IsExplicitImpl)
6160                                         return true;
6161
6162                                 return Get.IsUsed | Set.IsUsed;
6163                         }
6164                 }
6165
6166                 protected override void SetMemberName (MemberName new_name)
6167                 {
6168                         base.SetMemberName (new_name);
6169
6170                         Get.UpdateName (this);
6171                         Set.UpdateName (this);
6172                 }
6173
6174                 public override string[] ValidAttributeTargets {
6175                         get {
6176                                 return attribute_targets;
6177                         }
6178                 }
6179
6180                 //
6181                 //   Represents header string for documentation comment.
6182                 //
6183                 public override string DocCommentHeader {
6184                         get { return "P:"; }
6185                 }
6186         }
6187                         
6188         public class Property : PropertyBase {
6189                 const int AllowedModifiers =
6190                         Modifiers.NEW |
6191                         Modifiers.PUBLIC |
6192                         Modifiers.PROTECTED |
6193                         Modifiers.INTERNAL |
6194                         Modifiers.PRIVATE |
6195                         Modifiers.STATIC |
6196                         Modifiers.SEALED |
6197                         Modifiers.OVERRIDE |
6198                         Modifiers.ABSTRACT |
6199                         Modifiers.UNSAFE |
6200                         Modifiers.EXTERN |
6201                         Modifiers.METHOD_YIELDS |
6202                         Modifiers.VIRTUAL;
6203
6204                 const int AllowedInterfaceModifiers =
6205                         Modifiers.NEW;
6206
6207                 public Property (DeclSpace parent, Expression type, int mod, bool is_iface,
6208                                  MemberName name, Attributes attrs, Accessor get_block,
6209                                  Accessor set_block)
6210                         : base (parent, type, mod,
6211                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6212                                 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs)
6213                 {
6214                         if (get_block == null)
6215                                 Get = new GetMethod (this);
6216                         else
6217                                 Get = new GetMethod (this, get_block);
6218
6219                         if (set_block == null)
6220                                 Set = new SetMethod (this);
6221                         else
6222                                 Set = new SetMethod (this, set_block);
6223                 }
6224
6225                 public override bool Define ()
6226                 {
6227                         if (!base.Define ())
6228                                 return false;
6229
6230                         if (!CheckBase ())
6231                                 return false;
6232
6233                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6234
6235                         if (!Get.IsDummy) {
6236                                 GetBuilder = Get.Define (Parent);
6237                                 if (GetBuilder == null)
6238                                         return false;
6239                         }
6240
6241                         SetBuilder = Set.Define (Parent);
6242                         if (!Set.IsDummy) {
6243                                 if (SetBuilder == null)
6244                                         return false;
6245                         }
6246
6247                         // FIXME - PropertyAttributes.HasDefault ?
6248
6249                         PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6250                              Name, PropertyAttributes.None, MemberType, null);
6251                         
6252                         if (!Get.IsDummy)
6253                                 PropertyBuilder.SetGetMethod (GetBuilder);
6254                                 
6255                         if (!Set.IsDummy)
6256                                 PropertyBuilder.SetSetMethod (SetBuilder);
6257                         
6258                         TypeManager.RegisterProperty (PropertyBuilder, this);
6259                         return true;
6260                 }
6261         }
6262
6263         /// </summary>
6264         ///  Gigantic workaround  for lameness in SRE follows :
6265         ///  This class derives from EventInfo and attempts to basically
6266         ///  wrap around the EventBuilder so that FindMembers can quickly
6267         ///  return this in it search for members
6268         /// </summary>
6269         public class MyEventBuilder : EventInfo {
6270                 
6271                 //
6272                 // We use this to "point" to our Builder which is
6273                 // not really a MemberInfo
6274                 //
6275                 EventBuilder MyBuilder;
6276                 
6277                 //
6278                 // We "catch" and wrap these methods
6279                 //
6280                 MethodInfo raise, remove, add;
6281
6282                 EventAttributes attributes;
6283                 Type declaring_type, reflected_type, event_type;
6284                 string name;
6285
6286                 Event my_event;
6287
6288                 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6289                 {
6290                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6291
6292                         // And now store the values in our own fields.
6293                         
6294                         declaring_type = type_builder;
6295
6296                         reflected_type = type_builder;
6297                         
6298                         attributes = event_attr;
6299                         this.name = name;
6300                         my_event = ev;
6301                         this.event_type = event_type;
6302                 }
6303                 
6304                 //
6305                 // Methods that you have to override.  Note that you only need 
6306                 // to "implement" the variants that take the argument (those are
6307                 // the "abstract" methods, the others (GetAddMethod()) are 
6308                 // regular.
6309                 //
6310                 public override MethodInfo GetAddMethod (bool nonPublic)
6311                 {
6312                         return add;
6313                 }
6314                 
6315                 public override MethodInfo GetRemoveMethod (bool nonPublic)
6316                 {
6317                         return remove;
6318                 }
6319                 
6320                 public override MethodInfo GetRaiseMethod (bool nonPublic)
6321                 {
6322                         return raise;
6323                 }
6324                 
6325                 //
6326                 // These methods make "MyEventInfo" look like a Builder
6327                 //
6328                 public void SetRaiseMethod (MethodBuilder raiseMethod)
6329                 {
6330                         raise = raiseMethod;
6331                         MyBuilder.SetRaiseMethod (raiseMethod);
6332                 }
6333
6334                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
6335                 {
6336                         remove = removeMethod;
6337                         MyBuilder.SetRemoveOnMethod (removeMethod);
6338                 }
6339
6340                 public void SetAddOnMethod (MethodBuilder addMethod)
6341                 {
6342                         add = addMethod;
6343                         MyBuilder.SetAddOnMethod (addMethod);
6344                 }
6345
6346                 public void SetCustomAttribute (CustomAttributeBuilder cb)
6347                 {
6348                         MyBuilder.SetCustomAttribute (cb);
6349                 }
6350                 
6351                 public override object [] GetCustomAttributes (bool inherit)
6352                 {
6353                         // FIXME : There's nothing which can be seemingly done here because
6354                         // we have no way of getting at the custom attribute objects of the
6355                         // EventBuilder !
6356                         return null;
6357                 }
6358
6359                 public override object [] GetCustomAttributes (Type t, bool inherit)
6360                 {
6361                         // FIXME : Same here !
6362                         return null;
6363                 }
6364
6365                 public override bool IsDefined (Type t, bool b)
6366                 {
6367                         return true;
6368                 }
6369
6370                 public override EventAttributes Attributes {
6371                         get {
6372                                 return attributes;
6373                         }
6374                 }
6375
6376                 public override string Name {
6377                         get {
6378                                 return name;
6379                         }
6380                 }
6381
6382                 public override Type DeclaringType {
6383                         get {
6384                                 return declaring_type;
6385                         }
6386                 }
6387
6388                 public override Type ReflectedType {
6389                         get {
6390                                 return reflected_type;
6391                         }
6392                 }
6393
6394                 public Type EventType {
6395                         get {
6396                                 return event_type;
6397                         }
6398                 }
6399                 
6400                 public void SetUsed ()
6401                 {
6402                         if (my_event != null) {
6403                                 my_event.SetAssigned ();
6404                                 my_event.SetMemberIsUsed ();
6405                         }
6406                 }
6407         }
6408         
6409         /// <summary>
6410         /// For case when event is declared like property (with add and remove accessors).
6411         /// </summary>
6412         public class EventProperty: Event {
6413
6414                 static string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
6415
6416                 public EventProperty (DeclSpace parent, Expression type, int mod_flags,
6417                                       bool is_iface, MemberName name,
6418                                       Attributes attrs, Accessor add, Accessor remove)
6419                         : base (parent, type, mod_flags, is_iface, name, attrs)
6420                 {
6421                         Add = new AddDelegateMethod (this, add);
6422                         Remove = new RemoveDelegateMethod (this, remove);
6423
6424                         // For this event syntax we don't report error CS0067
6425                         // because it is hard to do it.
6426                         SetAssigned ();
6427                 }
6428
6429                 public override string[] ValidAttributeTargets {
6430                         get {
6431                                 return attribute_targets;
6432                         }
6433                 }
6434         }
6435
6436         /// <summary>
6437         /// Event is declared like field.
6438         /// </summary>
6439         public class EventField : Event {
6440
6441                 static string[] attribute_targets = new string [] { "event", "field", "method" };
6442                 static string[] attribute_targets_interface = new string[] { "event", "method" };
6443
6444                 public EventField (DeclSpace parent, Expression type, int mod_flags,
6445                                    bool is_iface, MemberName name,
6446                                    Attributes attrs)
6447                         : base (parent, type, mod_flags, is_iface, name, attrs)
6448                 {
6449                         Add = new AddDelegateMethod (this);
6450                         Remove = new RemoveDelegateMethod (this);
6451                 }
6452
6453                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6454                 {
6455                         if (a.Target == AttributeTargets.Field) {
6456                                 FieldBuilder.SetCustomAttribute (cb);
6457                                 return;
6458                         }
6459
6460                         if (a.Target == AttributeTargets.Method) {
6461                                 Add.ApplyAttributeBuilder (a, cb);
6462                                 Remove.ApplyAttributeBuilder (a, cb);
6463                                 return;
6464                         }
6465
6466                         base.ApplyAttributeBuilder (a, cb);
6467                 }
6468
6469                 public override bool Define()
6470                 {
6471                         if (!base.Define ())
6472                                 return false;
6473
6474                         if (initializer != null) {
6475                                 if (((ModFlags & Modifiers.ABSTRACT) != 0)) {
6476                                         Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
6477                                                 GetSignatureForError ());
6478                                         return false;
6479                                 }
6480                         }
6481
6482                         return true;
6483                 }
6484
6485                 public override string[] ValidAttributeTargets {
6486                         get {
6487                                 return IsInterface ? attribute_targets_interface : attribute_targets;
6488                         }
6489                 }
6490         }
6491
6492         public abstract class Event : FieldBase {
6493
6494                 protected sealed class AddDelegateMethod: DelegateMethod
6495                 {
6496
6497                         public AddDelegateMethod (Event method):
6498                                 base (method, "add_")
6499                         {
6500                         }
6501
6502                         public AddDelegateMethod (Event method, Accessor accessor):
6503                                 base (method, accessor, "add_")
6504                         {
6505                         }
6506
6507                         protected override MethodInfo DelegateMethodInfo {
6508                                 get {
6509                                         return TypeManager.delegate_combine_delegate_delegate;
6510                                 }
6511                         }
6512
6513                 }
6514
6515                 protected sealed class RemoveDelegateMethod: DelegateMethod
6516                 {
6517                         public RemoveDelegateMethod (Event method):
6518                                 base (method, "remove_")
6519                         {
6520                         }
6521
6522                         public RemoveDelegateMethod (Event method, Accessor accessor):
6523                                 base (method, accessor, "remove_")
6524                         {
6525                         }
6526
6527                         protected override MethodInfo DelegateMethodInfo {
6528                                 get {
6529                                         return TypeManager.delegate_remove_delegate_delegate;
6530                                 }
6531                         }
6532
6533                 }
6534
6535                 public abstract class DelegateMethod : AbstractPropertyEventMethod
6536                 {
6537                         protected readonly Event method;
6538                         ImplicitParameter param_attr;
6539
6540                         static string[] attribute_targets = new string [] { "method", "param", "return" };
6541
6542                         public DelegateMethod (Event method, string prefix)
6543                                 : base (method, prefix)
6544                         {
6545                                 this.method = method;
6546                         }
6547
6548                         public DelegateMethod (Event method, Accessor accessor, string prefix)
6549                                 : base (method, accessor, prefix)
6550                         {
6551                                 this.method = method;
6552                         }
6553
6554                         protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6555                         {
6556                                 if (a.Target == AttributeTargets.Parameter) {
6557                                         if (param_attr == null)
6558                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6559
6560                                         param_attr.ApplyAttributeBuilder (a, cb);
6561                                         return;
6562                                 }
6563
6564                                 base.ApplyAttributeBuilder (a, cb);
6565                         }
6566
6567                         public override AttributeTargets AttributeTargets {
6568                                 get {
6569                                         return AttributeTargets.Method;
6570                                 }
6571                         }
6572
6573                         public override bool IsClsComplianceRequired ()
6574                         {
6575                                 return method.IsClsComplianceRequired ();
6576                         }
6577
6578                         public MethodBuilder Define (DeclSpace parent)
6579                         {
6580                                 method_data = new MethodData (method, method.ModFlags,
6581                                         method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
6582
6583                                 if (!method_data.Define (parent))
6584                                         return null;
6585
6586                                 MethodBuilder mb = method_data.MethodBuilder;
6587                                 ParameterInfo.ApplyAttributes (mb);
6588                                 return mb;
6589                         }
6590
6591
6592                         protected override void EmitMethod (DeclSpace parent)
6593                         {
6594                                 if (block != null) {
6595                                         base.EmitMethod (parent);
6596                                         return;
6597                                 }
6598
6599                                 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
6600                                         return;
6601
6602                                 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
6603                                 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
6604
6605                                 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
6606                                 if ((method.ModFlags & Modifiers.STATIC) != 0) {
6607                                         ig.Emit (OpCodes.Ldsfld, field_info);
6608                                         ig.Emit (OpCodes.Ldarg_0);
6609                                         ig.Emit (OpCodes.Call, DelegateMethodInfo);
6610                                         ig.Emit (OpCodes.Castclass, method.MemberType);
6611                                         ig.Emit (OpCodes.Stsfld, field_info);
6612                                 } else {
6613                                         ig.Emit (OpCodes.Ldarg_0);
6614                                         ig.Emit (OpCodes.Ldarg_0);
6615                                         ig.Emit (OpCodes.Ldfld, field_info);
6616                                         ig.Emit (OpCodes.Ldarg_1);
6617                                         ig.Emit (OpCodes.Call, DelegateMethodInfo);
6618                                         ig.Emit (OpCodes.Castclass, method.MemberType);
6619                                         ig.Emit (OpCodes.Stfld, field_info);
6620                                 }
6621                                 ig.Emit (OpCodes.Ret);
6622                         }
6623
6624                         protected abstract MethodInfo DelegateMethodInfo { get; }
6625
6626                         public override Type ReturnType {
6627                                 get {
6628                                         return TypeManager.void_type;
6629                                 }
6630                         }
6631
6632                         public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
6633                         {
6634                                 return new EmitContext (method,
6635                                         ds, method.Parent, Location, ig, ReturnType,
6636                                         method.ModFlags, false);
6637                         }
6638
6639                         public override ObsoleteAttribute GetObsoleteAttribute ()
6640                         {
6641                                 return method.GetObsoleteAttribute ();
6642                         }
6643
6644                         public override string[] ValidAttributeTargets {
6645                                 get {
6646                                         return attribute_targets;
6647                                 }
6648                         }
6649
6650                         public override Parameters ParameterInfo {
6651                                 get {
6652                                         return method.parameters;
6653                                 }
6654                         }
6655
6656                 }
6657
6658
6659                 const int AllowedModifiers =
6660                         Modifiers.NEW |
6661                         Modifiers.PUBLIC |
6662                         Modifiers.PROTECTED |
6663                         Modifiers.INTERNAL |
6664                         Modifiers.PRIVATE |
6665                         Modifiers.STATIC |
6666                         Modifiers.VIRTUAL |
6667                         Modifiers.SEALED |
6668                         Modifiers.OVERRIDE |
6669                         Modifiers.UNSAFE |
6670                         Modifiers.ABSTRACT;
6671
6672                 const int AllowedInterfaceModifiers =
6673                         Modifiers.NEW;
6674
6675                 public DelegateMethod Add, Remove;
6676                 public MyEventBuilder     EventBuilder;
6677                 public MethodBuilder AddBuilder, RemoveBuilder;
6678                 Parameters parameters;
6679
6680                 protected Event (DeclSpace parent, Expression type, int mod_flags,
6681                               bool is_iface, MemberName name, Attributes attrs)
6682                         : base (parent, type, mod_flags,
6683                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6684                                 name, attrs)
6685                 {
6686                         IsInterface = is_iface;
6687                 }
6688
6689                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6690                 {
6691                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
6692                                 a.Error_InvalidSecurityParent ();
6693                                 return;
6694                         }
6695                         
6696                         EventBuilder.SetCustomAttribute (cb);
6697                 }
6698
6699                 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6700                 {
6701                         return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
6702                 }
6703
6704                 public override AttributeTargets AttributeTargets {
6705                         get {
6706                                 return AttributeTargets.Event;
6707                         }
6708                 }
6709
6710                 public override bool Define ()
6711                 {
6712                         EventAttributes e_attr;
6713                         e_attr = EventAttributes.None;
6714
6715                         if (!DoDefine ())
6716                                 return false;
6717
6718                         if (!TypeManager.IsDelegateType (MemberType)) {
6719                                 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
6720                                 return false;
6721                         }
6722
6723                         parameters = new Parameters (
6724                                 new Parameter[] { new Parameter (MemberType, "value", Parameter.Modifier.NONE, null, Location) },
6725                                 new Type[] { MemberType } );
6726
6727                         if (!CheckBase ())
6728                                 return false;
6729
6730                         //
6731                         // Now define the accessors
6732                         //
6733
6734                         AddBuilder = Add.Define (Parent);
6735                         if (AddBuilder == null)
6736                                 return false;
6737
6738                         RemoveBuilder = Remove.Define (Parent);
6739                         if (RemoveBuilder == null)
6740                                 return false;
6741
6742                         EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, e_attr, MemberType);
6743                         
6744                         if (Add.Block == null && Remove.Block == null && !IsInterface) {
6745                                 FieldBuilder = Parent.TypeBuilder.DefineField (
6746                                         Name, MemberType,
6747                                         FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
6748                                 TypeManager.RegisterPrivateFieldOfEvent (
6749                                         (EventInfo) EventBuilder, FieldBuilder);
6750                                 TypeManager.RegisterFieldBase (FieldBuilder, this);
6751                         }
6752                         
6753                         EventBuilder.SetAddOnMethod (AddBuilder);
6754                         EventBuilder.SetRemoveOnMethod (RemoveBuilder);
6755
6756                         TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder);
6757                         return true;
6758                 }
6759
6760                 protected override bool CheckBase ()
6761                 {
6762                         if (!base.CheckBase ())
6763                                 return false;
6764  
6765                         if (conflict_symbol != null && (ModFlags & Modifiers.NEW) == 0) {
6766                                 if (!(conflict_symbol is EventInfo)) {
6767                                         Report.SymbolRelatedToPreviousError (conflict_symbol);
6768                                         Report.Error (72, Location, "Event `{0}' can override only event", GetSignatureForError ());
6769                                         return false;
6770                                 }
6771                         }
6772  
6773                         return true;
6774                 }
6775
6776                 public override void Emit ()
6777                 {
6778                         if (OptAttributes != null) {
6779                                 OptAttributes.Emit ();
6780                         }
6781
6782                         Add.Emit (Parent);
6783                         Remove.Emit (Parent);
6784
6785                         base.Emit ();
6786                 }
6787
6788                 public override string GetSignatureForError ()
6789                 {
6790                         return base.GetSignatureForError ();
6791                 }
6792
6793                 //
6794                 //   Represents header string for documentation comment.
6795                 //
6796                 public override string DocCommentHeader {
6797                         get { return "E:"; }
6798                 }
6799         }
6800
6801
6802         public class Indexer : PropertyBase {
6803
6804                 class GetIndexerMethod : GetMethod
6805                 {
6806                         public GetIndexerMethod (MethodCore method):
6807                                 base (method)
6808                         {
6809                         }
6810
6811                         public GetIndexerMethod (MethodCore method, Accessor accessor):
6812                                 base (method, accessor)
6813                         {
6814                         }
6815
6816                         public override Parameters ParameterInfo {
6817                                 get {
6818                                         return method.ParameterInfo;
6819                                 }
6820                         }
6821                 }
6822
6823                 class SetIndexerMethod: SetMethod
6824                 {
6825                         public SetIndexerMethod (MethodCore method):
6826                                 base (method)
6827                         {
6828                         }
6829
6830                         public SetIndexerMethod (MethodCore method, Accessor accessor):
6831                                 base (method, accessor)
6832                         {
6833                         }
6834
6835                         protected override void DefineParameters ()
6836                         {
6837                                 parameters = Parameters.MergeGenerated (method.Parameters,
6838                                         new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, method.Location));
6839                         }
6840                 }
6841
6842                 const int AllowedModifiers =
6843                         Modifiers.NEW |
6844                         Modifiers.PUBLIC |
6845                         Modifiers.PROTECTED |
6846                         Modifiers.INTERNAL |
6847                         Modifiers.PRIVATE |
6848                         Modifiers.VIRTUAL |
6849                         Modifiers.SEALED |
6850                         Modifiers.OVERRIDE |
6851                         Modifiers.UNSAFE |
6852                         Modifiers.EXTERN |
6853                         Modifiers.ABSTRACT;
6854
6855                 const int AllowedInterfaceModifiers =
6856                         Modifiers.NEW;
6857
6858
6859                 public Indexer (DeclSpace parent, Expression type, MemberName name, int mod,
6860                                 bool is_iface, Parameters parameters, Attributes attrs,
6861                                 Accessor get_block, Accessor set_block)
6862                         : base (parent, type, mod,
6863                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6864                                 is_iface, name, parameters, attrs)
6865                 {
6866                         if (get_block == null)
6867                                 Get = new GetIndexerMethod (this);
6868                         else
6869                                 Get = new GetIndexerMethod (this, get_block);
6870
6871                         if (set_block == null)
6872                                 Set = new SetIndexerMethod (this);
6873                         else
6874                                 Set = new SetIndexerMethod (this, set_block);
6875                 }
6876                        
6877                 public override bool Define ()
6878                 {
6879                         if (!base.Define ())
6880                                 return false;
6881
6882                         if (MemberType == TypeManager.void_type) {
6883                                 Report.Error (620, Location, "Indexers cannot have void type");
6884                                 return false;
6885                         }
6886
6887                         if (OptAttributes != null) {
6888                                 Attribute indexer_attr = OptAttributes.Search (TypeManager.indexer_name_type);
6889                                 if (indexer_attr != null) {
6890                                         // Remove the attribute from the list because it is not emitted
6891                                         OptAttributes.Attrs.Remove (indexer_attr);
6892
6893                                         string name = indexer_attr.GetIndexerAttributeValue ();
6894                                         if (name == null)
6895                                                 return false;
6896
6897                                         ShortName = name;
6898
6899                                         if (IsExplicitImpl) {
6900                                                 Report.Error (415, indexer_attr.Location,
6901                                                               "The `IndexerName' attribute is valid only on an " +
6902                                                               "indexer that is not an explicit interface member declaration");
6903                                                 return false;
6904                                         }
6905
6906                                         if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6907                                                 Report.Error (609, indexer_attr.Location,
6908                                                               "Cannot set the `IndexerName' attribute on an indexer marked override");
6909                                                 return false;
6910                                         }
6911                                 }
6912                         }
6913
6914                         if (InterfaceType != null) {
6915                                 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
6916                                 if (base_IndexerName != Name)
6917                                         ShortName = base_IndexerName;
6918                         }
6919
6920                         if (!ParentContainer.AddToMemberContainer (this) ||
6921                                 !ParentContainer.AddToMemberContainer (Get) || !ParentContainer.AddToMemberContainer (Set))
6922                                 return false;
6923
6924                         if (!CheckBase ())
6925                                 return false;
6926
6927                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6928                         if (!Get.IsDummy){
6929                                 GetBuilder = Get.Define (Parent);
6930                                 if (GetBuilder == null)
6931                                         return false;
6932                         }
6933                         
6934                         SetBuilder = Set.Define (Parent);
6935                         if (!Set.IsDummy){
6936                                 if (SetBuilder == null)
6937                                         return false;
6938                         }
6939
6940                         //
6941                         // Now name the parameters
6942                         //
6943                         Parameter [] p = Parameters.FixedParameters;
6944                         if (p != null) {
6945                                 // TODO: should be done in parser and it needs to do cycle
6946                                 if ((p [0].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
6947                                         Report.Error (631, Location, "ref and out are not valid in this context");
6948                                         return false;
6949                                 }
6950                         }
6951
6952                         PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6953                                 Name, PropertyAttributes.None, MemberType, ParameterTypes);
6954                         
6955                         if (!Get.IsDummy)
6956                                 PropertyBuilder.SetGetMethod (GetBuilder);
6957
6958                         if (!Set.IsDummy)
6959                                 PropertyBuilder.SetSetMethod (SetBuilder);
6960                                 
6961                         TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, ParameterTypes);
6962
6963                         return true;
6964                 }
6965
6966                 public override string GetSignatureForError ()
6967                 {
6968                         StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
6969                         if (MemberName.Left != null) {
6970                                 sb.Append ('.');
6971                                 sb.Append (MemberName.Left);
6972                         }
6973
6974                         sb.Append (".this");
6975                         sb.Append (Parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
6976                         return sb.ToString ();
6977                 }
6978
6979                 public override bool MarkForDuplicationCheck ()
6980                 {
6981                         caching_flags |= Flags.TestMethodDuplication;
6982                         return true;
6983                 }
6984         }
6985
6986         public class Operator : MethodOrOperator, IIteratorContainer {
6987
6988                 const int AllowedModifiers =
6989                         Modifiers.PUBLIC |
6990                         Modifiers.UNSAFE |
6991                         Modifiers.EXTERN |
6992                         Modifiers.STATIC;
6993
6994                 public enum OpType : byte {
6995
6996                         // Unary operators
6997                         LogicalNot,
6998                         OnesComplement,
6999                         Increment,
7000                         Decrement,
7001                         True,
7002                         False,
7003
7004                         // Unary and Binary operators
7005                         Addition,
7006                         Subtraction,
7007
7008                         UnaryPlus,
7009                         UnaryNegation,
7010                         
7011                         // Binary operators
7012                         Multiply,
7013                         Division,
7014                         Modulus,
7015                         BitwiseAnd,
7016                         BitwiseOr,
7017                         ExclusiveOr,
7018                         LeftShift,
7019                         RightShift,
7020                         Equality,
7021                         Inequality,
7022                         GreaterThan,
7023                         LessThan,
7024                         GreaterThanOrEqual,
7025                         LessThanOrEqual,
7026
7027                         // Implicit and Explicit
7028                         Implicit,
7029                         Explicit,
7030
7031                         // Just because of enum
7032                         TOP
7033                 };
7034
7035                 public readonly OpType OperatorType;
7036                 
7037                 public Operator (DeclSpace parent, OpType type, Expression ret_type,
7038                                  int mod_flags, Parameters parameters,
7039                                  ToplevelBlock block, Attributes attrs, Location loc)
7040                         : base (parent, ret_type, mod_flags, AllowedModifiers, false,
7041                                 new MemberName ("op_" + type, loc), attrs, parameters)
7042                 {
7043                         OperatorType = type;
7044                         Block = block;
7045                 }
7046
7047                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) 
7048                 {
7049                         if (a.Type == TypeManager.conditional_attribute_type) {
7050                                 Error_ConditionalAttributeIsNotValid ();
7051                                 return;
7052                         }
7053
7054                         base.ApplyAttributeBuilder (a, cb);
7055                 }
7056                 
7057                 protected override bool CheckForDuplications ()
7058                 {
7059                         ArrayList ar = ParentContainer.Operators;
7060                         if (ar != null) {
7061                                 int arLen = ar.Count;
7062                                         
7063                                 for (int i = 0; i < arLen; i++) {
7064                                         Operator o = (Operator) ar [i];
7065                                         if (IsDuplicateImplementation (o))
7066                                                 return false;
7067                                 }
7068                         }
7069
7070                         ar = ParentContainer.Methods;
7071                         if (ar != null) {
7072                                 int arLen = ar.Count;
7073                                         
7074                                 for (int i = 0; i < arLen; i++) {
7075                                         Method m = (Method) ar [i];
7076                                         if (IsDuplicateImplementation (m))
7077                                                 return false;
7078                                 }
7079                         }
7080
7081                         return true;
7082                 }
7083
7084                 public override bool Define ()
7085                 {
7086                         const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
7087                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
7088                                 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
7089                                 return false;
7090                         }
7091
7092                         if (!base.Define ())
7093                                 return false;
7094
7095                         if (MemberType == TypeManager.void_type) {
7096                                 Report.Error (590, Location, "User-defined operators cannot return void");
7097                                 return false;
7098                         }
7099
7100                         Type declaring_type = MethodBuilder.DeclaringType;
7101                         Type return_type = MemberType;
7102                         Type first_arg_type = ParameterTypes [0];
7103
7104                         // Rules for conversion operators
7105                         
7106                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7107                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
7108                                         Report.Error (555, Location,
7109                                                 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
7110                                         return false;
7111                                 }
7112                                 
7113                                 if (first_arg_type != declaring_type && return_type != declaring_type){
7114                                         Report.Error (
7115                                                 556, Location, 
7116                                                 "User-defined conversion must convert to or from the " +
7117                                                 "enclosing type");
7118                                         return false;
7119                                 }
7120
7121                                 if (first_arg_type.IsInterface || return_type.IsInterface){
7122                                         Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
7123                                                 GetSignatureForError ());
7124                                         return false;
7125                                 }
7126                                 
7127                                 if (first_arg_type.IsSubclassOf (return_type) || return_type.IsSubclassOf (first_arg_type)) {
7128                                         if (declaring_type.IsSubclassOf (return_type) || declaring_type.IsSubclassOf (first_arg_type)) {
7129                                                 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from base class",
7130                                                         GetSignatureForError ());
7131                                                 return false;
7132                                         }
7133                                         Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from derived class",
7134                                                 GetSignatureForError ());
7135                                         return false;
7136                                 }
7137                         } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
7138                                 if (first_arg_type != declaring_type || ParameterTypes [1] != TypeManager.int32_type) {
7139                                         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");
7140                                         return false;
7141                                 }
7142                         } else if (Parameters.Count == 1) {
7143                                 // Checks for Unary operators
7144
7145                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7146                                         if (return_type != declaring_type && !return_type.IsSubclassOf (declaring_type)) {
7147                                                 Report.Error (448, Location,
7148                                                         "The return type for ++ or -- operator must be the containing type or derived from the containing type");
7149                                                 return false;
7150                                         }
7151                                         if (first_arg_type != declaring_type) {
7152                                                 Report.Error (
7153                                                         559, Location, "The parameter type for ++ or -- operator must be the containing type");
7154                                                 return false;
7155                                         }
7156                                 }
7157                                 
7158                                 if (first_arg_type != declaring_type){
7159                                         Report.Error (
7160                                                 562, Location,
7161                                                 "The parameter of a unary operator must be the " +
7162                                                 "containing type");
7163                                         return false;
7164                                 }
7165                                 
7166                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7167                                         if (return_type != TypeManager.bool_type){
7168                                                 Report.Error (
7169                                                         215, Location,
7170                                                         "The return type of operator True or False " +
7171                                                         "must be bool");
7172                                                 return false;
7173                                         }
7174                                 }
7175                                 
7176                         } else {
7177                                 // Checks for Binary operators
7178                                 
7179                                 if (first_arg_type != declaring_type &&
7180                                     ParameterTypes [1] != declaring_type){
7181                                         Report.Error (
7182                                                 563, Location,
7183                                                 "One of the parameters of a binary operator must " +
7184                                                 "be the containing type");
7185                                         return false;
7186                                 }
7187                         }
7188
7189                         return true;
7190                 }
7191
7192                 protected override bool DoDefine ()
7193                 {
7194                         if (!base.DoDefine ())
7195                                 return false;
7196
7197                         flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
7198                         return true;
7199                 }
7200                 
7201                 public override void Emit ()
7202                 {
7203                         base.Emit ();
7204
7205                         Parameters.ApplyAttributes (MethodBuilder);
7206
7207                         //
7208                         // abstract or extern methods have no bodies
7209                         //
7210                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
7211                                 return;
7212                         
7213                         EmitContext ec;
7214                         if ((flags & MethodAttributes.PinvokeImpl) == 0)
7215                                 ec = CreateEmitContext (Parent, MethodBuilder.GetILGenerator ());
7216                         else
7217                                 ec = CreateEmitContext (Parent, null);
7218                         
7219                         SourceMethod source = SourceMethod.Create (Parent, MethodBuilder, Block);
7220                         ec.EmitTopBlock (this, Block);
7221
7222                         if (source != null)
7223                                 source.CloseMethod ();
7224
7225                         Block = null;
7226                 }
7227
7228                 // Operator cannot be override
7229                 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
7230                 {
7231                         return null;
7232                 }
7233
7234                 public static string GetName (OpType ot)
7235                 {
7236                         switch (ot){
7237                         case OpType.LogicalNot:
7238                                 return "!";
7239                         case OpType.OnesComplement:
7240                                 return "~";
7241                         case OpType.Increment:
7242                                 return "++";
7243                         case OpType.Decrement:
7244                                 return "--";
7245                         case OpType.True:
7246                                 return "true";
7247                         case OpType.False:
7248                                 return "false";
7249                         case OpType.Addition:
7250                                 return "+";
7251                         case OpType.Subtraction:
7252                                 return "-";
7253                         case OpType.UnaryPlus:
7254                                 return "+";
7255                         case OpType.UnaryNegation:
7256                                 return "-";
7257                         case OpType.Multiply:
7258                                 return "*";
7259                         case OpType.Division:
7260                                 return "/";
7261                         case OpType.Modulus:
7262                                 return "%";
7263                         case OpType.BitwiseAnd:
7264                                 return "&";
7265                         case OpType.BitwiseOr:
7266                                 return "|";
7267                         case OpType.ExclusiveOr:
7268                                 return "^";
7269                         case OpType.LeftShift:
7270                                 return "<<";
7271                         case OpType.RightShift:
7272                                 return ">>";
7273                         case OpType.Equality:
7274                                 return "==";
7275                         case OpType.Inequality:
7276                                 return "!=";
7277                         case OpType.GreaterThan:
7278                                 return ">";
7279                         case OpType.LessThan:
7280                                 return "<";
7281                         case OpType.GreaterThanOrEqual:
7282                                 return ">=";
7283                         case OpType.LessThanOrEqual:
7284                                 return "<=";
7285                         case OpType.Implicit:
7286                                 return "implicit";
7287                         case OpType.Explicit:
7288                                 return "explicit";
7289                         default: return "";
7290                         }
7291                 }
7292
7293                 public static OpType GetOperatorType (string name)
7294                 {
7295                         if (name.StartsWith ("op_")){
7296                                 for (int i = 0; i < Unary.oper_names.Length; ++i) {
7297                                         if (Unary.oper_names [i] == name)
7298                                                 return (OpType)i;
7299                                 }
7300
7301                                 for (int i = 0; i < Binary.oper_names.Length; ++i) {
7302                                         if (Binary.oper_names [i] == name)
7303                                                 return (OpType)i;
7304                                 }
7305                         }
7306                         return OpType.TOP;
7307                 }
7308
7309                 public override string GetSignatureForError ()
7310                 {
7311                         StringBuilder sb = new StringBuilder ();
7312                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7313                                 sb.AppendFormat ("{0}.{1} operator {2}", Parent.GetSignatureForError (), GetName (OperatorType), Type.Type == null ? Type.ToString () : TypeManager.CSharpName (Type.Type));
7314                         }
7315                         else {
7316                                 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
7317                         }
7318
7319                         sb.Append (Parameters.GetSignatureForError ());
7320                         return sb.ToString ();
7321                 }
7322         }
7323
7324         //
7325         // This is used to compare method signatures
7326         //
7327         struct MethodSignature {
7328                 public string Name;
7329                 public Type RetType;
7330                 public Type [] Parameters;
7331                 
7332                 /// <summary>
7333                 ///    This delegate is used to extract methods which have the
7334                 ///    same signature as the argument
7335                 /// </summary>
7336                 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
7337                 
7338                 public MethodSignature (string name, Type ret_type, Type [] parameters)
7339                 {
7340                         Name = name;
7341                         RetType = ret_type;
7342
7343                         if (parameters == null)
7344                                 Parameters = Type.EmptyTypes;
7345                         else
7346                                 Parameters = parameters;
7347                 }
7348
7349                 public override string ToString ()
7350                 {
7351                         string pars = "";
7352                         if (Parameters.Length != 0){
7353                                 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
7354                                 for (int i = 0; i < Parameters.Length; i++){
7355                                         sb.Append (Parameters [i]);
7356                                         if (i+1 < Parameters.Length)
7357                                                 sb.Append (", ");
7358                                 }
7359                                 pars = sb.ToString ();
7360                         }
7361
7362                         return String.Format ("{0} {1} ({2})", RetType, Name, pars);
7363                 }
7364                 
7365                 public override int GetHashCode ()
7366                 {
7367                         return Name.GetHashCode ();
7368                 }
7369
7370                 public override bool Equals (Object o)
7371                 {
7372                         MethodSignature other = (MethodSignature) o;
7373
7374                         if (other.Name != Name)
7375                                 return false;
7376
7377                         if (other.RetType != RetType)
7378                                 return false;
7379                         
7380                         if (Parameters == null){
7381                                 if (other.Parameters == null)
7382                                         return true;
7383                                 return false;
7384                         }
7385
7386                         if (other.Parameters == null)
7387                                 return false;
7388                         
7389                         int c = Parameters.Length;
7390                         if (other.Parameters.Length != c)
7391                                 return false;
7392
7393                         for (int i = 0; i < c; i++)
7394                                 if (other.Parameters [i] != Parameters [i])
7395                                         return false;
7396
7397                         return true;
7398                 }
7399
7400                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
7401                 {
7402                         MethodSignature sig = (MethodSignature) filter_criteria;
7403
7404                         if (m.Name != sig.Name)
7405                                 return false;
7406
7407                         Type ReturnType;
7408                         MethodInfo mi = m as MethodInfo;
7409                         PropertyInfo pi = m as PropertyInfo;
7410
7411                         if (mi != null)
7412                                 ReturnType = mi.ReturnType;
7413                         else if (pi != null)
7414                                 ReturnType = pi.PropertyType;
7415                         else
7416                                 return false;
7417                         
7418                         //
7419                         // we use sig.RetType == null to mean `do not check the
7420                         // method return value.  
7421                         //
7422                         if (sig.RetType != null)
7423                                 if (ReturnType != sig.RetType)
7424                                         return false;
7425
7426                         Type [] args;
7427                         if (mi != null)
7428                                 args = TypeManager.GetParameterData (mi).Types;
7429                         else
7430                                 args = TypeManager.GetArgumentTypes (pi);
7431                         Type [] sigp = sig.Parameters;
7432
7433                         if (args.Length != sigp.Length)
7434                                 return false;
7435
7436                         for (int i = args.Length; i > 0; ){
7437                                 i--;
7438                                 if (args [i] != sigp [i])
7439                                         return false;
7440                         }
7441                         return true;
7442                 }
7443         }
7444 }