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