2005-06-08 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                         EmitContext parent_ec = Parent.EmitContext;
5252
5253                         bool old_is_static = parent_ec.IsStatic;
5254                         parent_ec.IsStatic = ec.IsStatic;
5255                         parent_ec.IsFieldInitializer = true;
5256                         e = e.DoResolve (parent_ec);
5257                         parent_ec.IsFieldInitializer = false;
5258                         parent_ec.IsStatic = old_is_static;
5259
5260                         init_expr = e;
5261                         init_expr_initialized = true;
5262
5263                         return init_expr;
5264                 }
5265
5266                 protected override bool CheckBase ()
5267                 {
5268                         if (!base.CheckBase ())
5269                                 return false;
5270  
5271                         // TODO: Implement
5272                         if (IsInterface)
5273                                 return true;
5274  
5275                         conflict_symbol = Parent.FindBaseMemberWithSameName (Name, false);
5276                         if (conflict_symbol == null) {
5277                                 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
5278                                         Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
5279                                 }
5280                                 return true;
5281                         }
5282  
5283                         if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
5284                                 Report.SymbolRelatedToPreviousError (conflict_symbol);
5285                                 Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
5286                         }
5287  
5288                         return true;
5289                 }
5290
5291                 public override string GetSignatureForError ()
5292                 {
5293                         if (FieldBuilder == null) {
5294                                 return base.GetSignatureForError (Parent);
5295                         }
5296                         return TypeManager.GetFullNameSignature (FieldBuilder);
5297                 }
5298
5299                 protected virtual bool IsFieldClsCompliant {
5300                         get {
5301                                 if (FieldBuilder == null)
5302                                         return true;
5303
5304                                 return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
5305                         }
5306                 }
5307
5308                 public override string[] ValidAttributeTargets {
5309                         get {
5310                                 return attribute_targets;
5311                         }
5312                 }
5313
5314                 protected override bool VerifyClsCompliance (DeclSpace ds)
5315                 {
5316                         if (!base.VerifyClsCompliance (ds))
5317                                 return false;
5318
5319                         if (!IsFieldClsCompliant) {
5320                                 Report.Error (3003, Location, "Type of '{0}' is not CLS-compliant", GetSignatureForError ());
5321                         }
5322                         return true;
5323                 }
5324
5325
5326                 public void SetAssigned ()
5327                 {
5328                         status |= Status.ASSIGNED;
5329                 }
5330         }
5331
5332         public abstract class FieldMember: FieldBase
5333         {
5334                 protected FieldMember (TypeContainer parent, Expression type, int mod,
5335                         int allowed_mod, MemberName name, object init, Attributes attrs, Location loc)
5336                         : base (parent, type, mod, allowed_mod | Modifiers.ABSTRACT, name, init, attrs, loc)
5337                 {
5338                         if ((mod & Modifiers.ABSTRACT) != 0)
5339                                 Report.Error (681, loc, "The modifier 'abstract' is not valid on fields. Try using a property instead");
5340                 }
5341
5342                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5343                 {
5344                         if (a.Type == TypeManager.field_offset_attribute_type)
5345                         {
5346                                 status |= Status.HAS_OFFSET;
5347
5348                                 if (!Parent.HasExplicitLayout) {
5349                                         Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
5350                                         return;
5351                                 }
5352
5353                                 if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
5354                                         Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
5355                                         return;
5356                                 }
5357                         }
5358
5359 #if NET_2_0
5360                         if (a.Type == TypeManager.fixed_buffer_attr_type) {
5361                                 Report.Error (1716, Location, "Do not use 'System.Runtime.CompilerServices.FixedBuffer' attribute. Use the 'fixed' field modifier instead");
5362                                 return;
5363                         }
5364 #endif
5365
5366                         base.ApplyAttributeBuilder (a, cb);
5367                 }
5368
5369
5370                 public override bool Define()
5371                 {
5372                         EmitContext ec = Parent.EmitContext;
5373                         if (ec == null)
5374                                 throw new InternalErrorException ("FieldMember.Define called too early");
5375
5376                         if (MemberType == null)
5377                                 return false;
5378
5379                         if (MemberType == TypeManager.void_type) {
5380                                 Report.Error (1547, Location, "Keyword 'void' cannot be used in this context");
5381                                 return false;
5382                         }
5383
5384                         if (!CheckBase ())
5385                                 return false;
5386                         
5387                         if (!Parent.AsAccessible (MemberType, ModFlags)) {
5388                                 Report.Error (52, Location,
5389                                         "Inconsistent accessibility: field type `" +
5390                                         TypeManager.CSharpName (MemberType) + "' is less " +
5391                                         "accessible than field `" + Name + "'");
5392                                 return false;
5393                         }
5394
5395                         if (!IsTypePermitted ())
5396                                 return false;
5397
5398                         if (MemberType.IsPointer && !UnsafeOK (Parent))
5399                                 return false;
5400
5401                         return true;
5402                 }
5403
5404                 public override void Emit ()
5405                 {
5406                         if (OptAttributes != null) {
5407                                 EmitContext ec = new EmitContext (Parent, Location, null, FieldBuilder.FieldType, ModFlags);
5408                                 OptAttributes.Emit (ec, this);
5409                         }
5410
5411                         if (Parent.HasExplicitLayout && ((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0) {
5412                                 Report.Error (625, Location, "'{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
5413                         }
5414
5415                         base.Emit ();
5416                 }
5417
5418                 //
5419                 //   Represents header string for documentation comment.
5420                 //
5421                 public override string DocCommentHeader {
5422                         get { return "F:"; }
5423                 }
5424         }
5425
5426         interface IFixedBuffer
5427         {
5428                 FieldInfo Element { get; }
5429                 Type ElementType { get; }
5430         }
5431
5432         public class FixedFieldExternal: IFixedBuffer
5433         {
5434                 FieldInfo element_field;
5435
5436                 public FixedFieldExternal (FieldInfo fi)
5437                 {
5438                         element_field = fi.FieldType.GetField (FixedField.FixedElementName);
5439                 }
5440
5441                 #region IFixedField Members
5442
5443                 public FieldInfo Element {
5444                         get {
5445                                 return element_field;
5446                         }
5447                 }
5448
5449                 public Type ElementType {
5450                         get {
5451                                 return element_field.FieldType;
5452                         }
5453                 }
5454
5455                 #endregion
5456         }
5457
5458         /// <summary>
5459         /// Fixed buffer implementation
5460         /// </summary>
5461         public class FixedField: FieldMember, IFixedBuffer
5462         {
5463                 public const string FixedElementName = "FixedElementField";
5464                 static int GlobalCounter = 0;
5465                 static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
5466                 static FieldInfo[] fi;
5467
5468                 TypeBuilder fixed_buffer_type;
5469                 FieldBuilder element;
5470                 Expression size_expr;
5471                 int buffer_size;
5472
5473                 const int AllowedModifiers =
5474                         Modifiers.NEW |
5475                         Modifiers.PUBLIC |
5476                         Modifiers.PROTECTED |
5477                         Modifiers.INTERNAL |
5478                         Modifiers.PRIVATE;
5479
5480                 public FixedField (TypeContainer parent, Expression type, int mod, string name,
5481                         Expression size_expr, Attributes attrs, Location loc):
5482                         base (parent, type, mod, AllowedModifiers, new MemberName (name), null, attrs, loc)
5483                 {
5484                         if (RootContext.Version == LanguageVersion.ISO_1)
5485                                 Report.FeatureIsNotStandardized (loc, "fixed sized buffers");
5486
5487                         this.size_expr = size_expr;
5488                 }
5489
5490                 public override bool Define()
5491                 {
5492 #if !NET_2_0
5493                         if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) != 0)
5494                                 Report.Warning (-23, Location, "Only private or internal fixed sized buffers are supported by .NET 1.x");
5495 #endif
5496
5497                         if (Parent.Kind != Kind.Struct) {
5498                                 Report.Error (1642, Location, "Fixed buffer fields may only be members of structs");
5499                                 return false;
5500                         }
5501
5502                         if (!base.Define ())
5503                                 return false;
5504
5505                         if (!TypeManager.IsPrimitiveType (MemberType)) {
5506                                 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");
5507                                 return false;
5508                         }
5509
5510                         Expression e = size_expr.Resolve (Parent.EmitContext);
5511                         if (e == null)
5512                                 return false;
5513
5514                         Constant c = e as Constant;
5515                         if (c == null) {
5516                                 Report.Error (133, Location, "The expression being assigned to '{0}' must be constant", GetSignatureForError ());
5517                                 return false;
5518                         }
5519
5520                         IntConstant buffer_size_const = c.ToInt (Location);
5521                         if (buffer_size_const == null)
5522                                 return false;
5523
5524                         buffer_size = buffer_size_const.Value;
5525
5526                         if (buffer_size <= 0) {
5527                                 Report.Error (1665, Location, "Fixed sized buffer '{0}' must have a length greater than zero", GetSignatureForError ());
5528                                 return false;
5529                         }
5530
5531                         int type_size = Expression.GetTypeSize (MemberType);
5532
5533                         if (buffer_size > int.MaxValue / type_size) {
5534                                 Report.Error (1664, Location, "Fixed sized buffer of length '{0}' and type '{1}' exceeded 2^31 limit",
5535                                         buffer_size.ToString (), TypeManager.CSharpName (MemberType));
5536                                 return false;
5537                         }
5538
5539                         buffer_size *= type_size;
5540
5541                         // Define nested
5542                         string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
5543
5544                         fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
5545                                 TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
5546                         element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
5547                         RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
5548
5549                         FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
5550                         TypeManager.RegisterFieldBase (FieldBuilder, this);
5551
5552                         return true;
5553                 }
5554
5555                 public override void Emit()
5556                 {
5557                         if (fi == null)
5558                                 fi = new FieldInfo [] { TypeManager.struct_layout_attribute_type.GetField ("Size") };
5559
5560                         object[] fi_val = new object[1];
5561                         fi_val [0] = buffer_size;
5562
5563                         CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.struct_layout_attribute_ctor, 
5564                                 ctor_args, fi, fi_val);
5565                         fixed_buffer_type.SetCustomAttribute (cab);
5566
5567 #if NET_2_0
5568                         cab = new CustomAttributeBuilder (TypeManager.fixed_buffer_attr_ctor, new object[] { MemberType, buffer_size } );
5569                         FieldBuilder.SetCustomAttribute (cab);
5570 #endif
5571                         base.Emit ();
5572                 }
5573
5574                 protected override bool IsFieldClsCompliant {
5575                         get {
5576                                 return false;
5577                         }
5578                 }
5579
5580                 #region IFixedField Members
5581
5582                 public FieldInfo Element {
5583                         get {
5584                                 return element;
5585                         }
5586                 }
5587
5588                 public Type ElementType {
5589                         get {
5590                                 return MemberType;
5591                         }
5592                 }
5593
5594                 #endregion
5595         }
5596
5597         //
5598         // The Field class is used to represents class/struct fields during parsing.
5599         //
5600         public class Field : FieldMember {
5601                 // <summary>
5602                 //   Modifiers allowed in a class declaration
5603                 // </summary>
5604                 const int AllowedModifiers =
5605                         Modifiers.NEW |
5606                         Modifiers.PUBLIC |
5607                         Modifiers.PROTECTED |
5608                         Modifiers.INTERNAL |
5609                         Modifiers.PRIVATE |
5610                         Modifiers.STATIC |
5611                         Modifiers.VOLATILE |
5612                         Modifiers.UNSAFE |
5613                         Modifiers.READONLY;
5614
5615                 public Field (TypeContainer parent, Expression type, int mod, string name,
5616                               Object expr_or_array_init, Attributes attrs, Location loc)
5617                         : base (parent, type, mod, AllowedModifiers, new MemberName (name),
5618                                 expr_or_array_init, attrs, loc)
5619                 {
5620                 }
5621
5622                 public override bool Define ()
5623                 {
5624                         if (!base.Define ())
5625                                 return false;
5626
5627                         if (RootContext.WarningLevel > 1){
5628                                 Type ptype = Parent.TypeBuilder.BaseType;
5629
5630                                 // ptype is only null for System.Object while compiling corlib.
5631                                 if (ptype != null){
5632                                         TypeContainer.FindMembers (
5633                                                 ptype, MemberTypes.Method,
5634                                                 BindingFlags.Public |
5635                                                 BindingFlags.Static | BindingFlags.Instance,
5636                                                 System.Type.FilterName, Name);
5637                                 }
5638                         }
5639
5640                         if ((ModFlags & Modifiers.VOLATILE) != 0){
5641                                 if (!MemberType.IsClass){
5642                                         Type vt = MemberType;
5643                                         
5644                                         if (TypeManager.IsEnumType (vt))
5645                                                 vt = TypeManager.EnumToUnderlying (MemberType);
5646
5647                                         if (!((vt == TypeManager.bool_type) ||
5648                                               (vt == TypeManager.sbyte_type) ||
5649                                               (vt == TypeManager.byte_type) ||
5650                                               (vt == TypeManager.short_type) ||
5651                                               (vt == TypeManager.ushort_type) ||
5652                                               (vt == TypeManager.int32_type) ||
5653                                               (vt == TypeManager.uint32_type) ||    
5654                                               (vt == TypeManager.char_type) ||
5655                                               (vt == TypeManager.float_type) ||
5656                                               (!vt.IsValueType))){
5657                                                 Report.Error (
5658                                                         677, Location, Parent.MakeName (Name) +
5659                                                         " A volatile field can not be of type `" +
5660                                                         TypeManager.CSharpName (vt) + "'");
5661                                                 return false;
5662                                         }
5663                                 }
5664
5665                                 if ((ModFlags & Modifiers.READONLY) != 0){
5666                                         Report.Error (
5667                                                       678, Location,
5668                                                       "A field can not be both volatile and readonly");
5669                                         return false;
5670                                 }
5671                         }
5672
5673                         FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
5674
5675                         if (Parent.Kind == Kind.Struct && 
5676                             ((fa & FieldAttributes.Static) == 0) &&
5677                             MemberType == Parent.TypeBuilder &&
5678                             !TypeManager.IsBuiltinType (MemberType)){
5679                                 Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name + 
5680                                               "' causes a cycle in the structure layout");
5681                                 return false;
5682                         }
5683
5684                         try {
5685                                 FieldBuilder = Parent.TypeBuilder.DefineField (
5686                                         Name, MemberType, Modifiers.FieldAttr (ModFlags));
5687
5688                                 TypeManager.RegisterFieldBase (FieldBuilder, this);
5689                         }
5690                         catch (ArgumentException) {
5691                                 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
5692                                 return false;
5693                         }
5694
5695                         return true;
5696                 }
5697
5698                 protected override bool VerifyClsCompliance (DeclSpace ds)
5699                 {
5700                         if (!base.VerifyClsCompliance (ds))
5701                                 return false;
5702
5703                         if ((ModFlags & Modifiers.VOLATILE) != 0) {
5704                                 Report.Warning (3026, 1, Location, "CLS-compliant field '{0}' cannot be volatile", GetSignatureForError ());
5705                         }
5706
5707                         return true;
5708                 }
5709         }
5710
5711         //
5712         // `set' and `get' accessors are represented with an Accessor.
5713         // 
5714         public class Accessor {
5715                 //
5716                 // Null if the accessor is empty, or a Block if not
5717                 //
5718                 public const int AllowedModifiers = 
5719                         Modifiers.PUBLIC |
5720                         Modifiers.PROTECTED |
5721                         Modifiers.INTERNAL |
5722                         Modifiers.PRIVATE;
5723                 
5724                 public ToplevelBlock Block;
5725                 public Attributes Attributes;
5726                 public Location Location;
5727                 public int ModFlags;
5728                 
5729                 public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
5730                 {
5731                         Block = b;
5732                         Attributes = attrs;
5733                         Location = loc;
5734                         ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
5735                 }
5736         }
5737
5738
5739         // Ooouh Martin, templates are missing here.
5740         // When it will be possible move here a lot of child code and template method type.
5741         public abstract class AbstractPropertyEventMethod: MemberCore, IMethodData {
5742                 protected MethodData method_data;
5743                 protected ToplevelBlock block;
5744                 protected ListDictionary declarative_security;
5745
5746                 // The accessor are created event if they are not wanted.
5747                 // But we need them because their names are reserved.
5748                 // Field says whether accessor will be emited or not
5749                 public readonly bool IsDummy;
5750
5751                 protected readonly string prefix;
5752
5753                 ReturnParameter return_attributes;
5754
5755                 public AbstractPropertyEventMethod (MemberBase member, string prefix)
5756                         : base (null, SetupName (prefix, member), null, member.Location)
5757                 {
5758                         this.prefix = prefix;
5759                         IsDummy = true;
5760                 }
5761
5762                 public AbstractPropertyEventMethod (MemberBase member, Accessor accessor,
5763                                                     string prefix)
5764                         : base (null, SetupName (prefix, member),
5765                                 accessor.Attributes, accessor.Location)
5766                 {
5767                         this.prefix = prefix;
5768                         this.block = accessor.Block;
5769                 }
5770
5771                 static MemberName SetupName (string prefix, MemberBase member)
5772                 {
5773                         return new MemberName (member.MemberName.Left, prefix + member.ShortName);
5774                 }
5775
5776                 public void UpdateName (MemberBase member)
5777                 {
5778                         SetMemberName (SetupName (prefix, member));
5779                 }
5780
5781                 #region IMethodData Members
5782
5783                 public ToplevelBlock Block {
5784                         get {
5785                                 return block;
5786                         }
5787
5788                         set {
5789                                 block = value;
5790                         }
5791                 }
5792
5793                 public CallingConventions CallingConventions {
5794                         get {
5795                                 return CallingConventions.Standard;
5796                         }
5797                 }
5798
5799                 public bool IsExcluded (EmitContext ec)
5800                 {
5801                         return false;
5802                 }
5803
5804                 public MemberName MethodName {
5805                         get {
5806                                 return MemberName;
5807                         }
5808                 }
5809
5810                 public abstract ObsoleteAttribute GetObsoleteAttribute ();
5811                 public abstract Type[] ParameterTypes { get; }
5812                 public abstract Type ReturnType { get; }
5813                 public abstract EmitContext CreateEmitContext(TypeContainer tc, ILGenerator ig);
5814
5815                 #endregion
5816
5817                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5818                 {
5819                         if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
5820                                         a.Type == TypeManager.conditional_attribute_type) {
5821                                 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 ());
5822                                 return;
5823                         }
5824
5825                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
5826                                 if (declarative_security == null)
5827                                         declarative_security = new ListDictionary ();
5828                                 a.ExtractSecurityPermissionSet (declarative_security);
5829                                 return;
5830                         }
5831
5832                         if (a.Target == AttributeTargets.Method) {
5833                                 method_data.MethodBuilder.SetCustomAttribute (cb);
5834                                 return;
5835                         }
5836
5837                         if (a.Target == AttributeTargets.ReturnValue) {
5838                                 if (return_attributes == null)
5839                                         return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5840
5841                                 return_attributes.ApplyAttributeBuilder (a, cb);
5842                                 return;
5843                         }
5844
5845                         ApplyToExtraTarget (a, cb);
5846                 }
5847
5848                 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
5849                 {
5850                         System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
5851                 }
5852
5853                 public override bool Define()
5854                 {
5855                         throw new NotSupportedException ();
5856                 }
5857
5858                 public virtual void Emit (TypeContainer container)
5859                 {
5860                         EmitMethod (container);
5861
5862                         if (declarative_security != null) {
5863                                 foreach (DictionaryEntry de in declarative_security) {
5864                                         method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
5865                                 }
5866                         }
5867
5868                         block = null;
5869                 }
5870
5871                 protected virtual void EmitMethod (TypeContainer container)
5872                 {
5873                         method_data.Emit (container, this);
5874                 }
5875
5876                 public override bool IsClsCompliaceRequired(DeclSpace ds)
5877                 {
5878                         return false;
5879                 }
5880
5881                 public bool IsDuplicateImplementation (MethodCore method)
5882                 {
5883                         if (Name != method.Name)
5884                                 return false;
5885
5886                         Type[] param_types = method.ParameterTypes;
5887
5888                         if (param_types.Length != ParameterTypes.Length)
5889                                 return false;
5890
5891                         for (int i = 0; i < param_types.Length; i++)
5892                                 if (param_types [i] != ParameterTypes [i])
5893                                         return false;
5894
5895                         Report.SymbolRelatedToPreviousError (method);
5896                         Report.Error (111, Location, TypeContainer.Error111, method.Parent.GetSignatureForError (), Name);
5897                         return true;
5898                 }
5899
5900                 public override bool IsUsed
5901                 {
5902                         get {
5903                                 if (IsDummy)
5904                                         return false;
5905
5906                                 return base.IsUsed;
5907                         }
5908                 }
5909
5910                 public new Location Location { 
5911                         get {
5912                                 return base.Location;
5913                         }
5914                 }
5915
5916                 //
5917                 //   Represents header string for documentation comment.
5918                 //
5919                 public override string DocCommentHeader {
5920                         get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
5921                 }
5922
5923                 protected override void VerifyObsoleteAttribute()
5924                 {
5925                 }
5926
5927         }
5928
5929         //
5930         // Properties and Indexers both generate PropertyBuilders, we use this to share 
5931         // their common bits.
5932         //
5933         abstract public class PropertyBase : MethodCore {
5934
5935                 public class GetMethod: PropertyMethod
5936                 {
5937                         static string[] attribute_targets = new string [] { "method", "return" };
5938
5939                         public GetMethod (MethodCore method):
5940                                 base (method, "get_")
5941                         {
5942                         }
5943
5944                         public GetMethod (MethodCore method, Accessor accessor):
5945                                 base (method, accessor, "get_")
5946                         {
5947                         }
5948
5949                         public override MethodBuilder Define(TypeContainer container)
5950                         {
5951                                 base.Define (container);
5952                                 
5953                                 method_data = new MethodData (method, method.ParameterInfo, ModFlags, flags, this);
5954
5955                                 if (!method_data.Define (container))
5956                                         return null;
5957
5958                                 return method_data.MethodBuilder;
5959                         }
5960
5961                         public override string GetSignatureForError (TypeContainer tc)
5962                         {
5963                                 return String.Concat (base.GetSignatureForError (tc), ".get");
5964                         }
5965
5966                         public override Type ReturnType {
5967                                 get {
5968                                         return method.MemberType;
5969                                 }
5970                         }
5971
5972                         public override string[] ValidAttributeTargets {
5973                                 get {
5974                                         return attribute_targets;
5975                                 }
5976                         }
5977                 }
5978
5979                 public class SetMethod: PropertyMethod {
5980
5981                         static string[] attribute_targets = new string [] { "method", "param", "return" };
5982                         ImplicitParameter param_attr;
5983
5984                         public SetMethod (MethodCore method):
5985                                 base (method, "set_")
5986                         {
5987                         }
5988
5989                         public SetMethod (MethodCore method, Accessor accessor):
5990                                 base (method, accessor, "set_")
5991                         {
5992                         }
5993
5994                         protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
5995                         {
5996                                 if (a.Target == AttributeTargets.Parameter) {
5997                                         if (param_attr == null)
5998                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder, method.Location);
5999
6000                                         param_attr.ApplyAttributeBuilder (a, cb);
6001                                         return;
6002                                 }
6003
6004                                 base.ApplyAttributeBuilder (a, cb);
6005                         }
6006
6007                         protected virtual InternalParameters GetParameterInfo (EmitContext ec)
6008                         {
6009                                 Parameter [] parms = new Parameter [1];
6010                                 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null, method.Location);
6011                                 Parameters parameters = new Parameters (parms, null);
6012
6013                                 bool old_unsafe = ec.InUnsafe;
6014                                 ec.InUnsafe = InUnsafe;
6015                                 Type [] types = parameters.GetParameterInfo (ec);
6016                                 ec.InUnsafe = old_unsafe;
6017
6018                                 return new InternalParameters (types, parameters);
6019                         }
6020
6021                         public override MethodBuilder Define (TypeContainer container)
6022                         {
6023                                 if (container.EmitContext == null)
6024                                         throw new InternalErrorException ("SetMethod.Define called too early");
6025                                         
6026                                 base.Define (container);
6027                                 
6028                                 method_data = new MethodData (method, GetParameterInfo (container.EmitContext), ModFlags, flags, this);
6029
6030                                 if (!method_data.Define (container))
6031                                         return null;
6032
6033                                 return method_data.MethodBuilder;
6034                         }
6035
6036                         public override string GetSignatureForError (TypeContainer tc)
6037                         {
6038                                 return String.Concat (base.GetSignatureForError (tc), ".set");
6039                         }
6040
6041                         public override Type[] ParameterTypes {
6042                                 get {
6043                                         return new Type[] { method.MemberType };
6044                                 }
6045                         }
6046
6047                         public override Type ReturnType {
6048                                 get {
6049                                         return TypeManager.void_type;
6050                                 }
6051                         }
6052
6053                         public override string[] ValidAttributeTargets {
6054                                 get {
6055                                         return attribute_targets;
6056                                 }
6057                         }
6058                 }
6059
6060                 static string[] attribute_targets = new string [] { "property" };
6061
6062                 public abstract class PropertyMethod: AbstractPropertyEventMethod
6063                 {
6064                         protected readonly MethodCore method;
6065                         protected MethodAttributes flags;
6066
6067                         public PropertyMethod (MethodCore method, string prefix)
6068                                 : base (method, prefix)
6069                         {
6070                                 this.method = method;
6071                                 Parent = method.Parent;
6072                         }
6073
6074                         public PropertyMethod (MethodCore method, Accessor accessor,
6075                                                string prefix)
6076                                 : base (method, accessor, prefix)
6077                         {
6078                                 this.method = method;
6079                                 Parent = method.Parent;
6080                                 this.ModFlags = accessor.ModFlags;
6081
6082                                 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
6083                                         Report.FeatureIsNotStandardized (Location, "accessor modifiers");
6084                                 }
6085                         }
6086
6087                         public override AttributeTargets AttributeTargets {
6088                                 get {
6089                                         return AttributeTargets.Method;
6090                                 }
6091                         }
6092
6093                         public override bool IsClsCompliaceRequired(DeclSpace ds)
6094                         {
6095                                 return method.IsClsCompliaceRequired (ds);
6096                         }
6097
6098                         public InternalParameters ParameterInfo 
6099                         {
6100                                 get {
6101                                         return method_data.ParameterInfo;
6102                                 }
6103                         }
6104
6105                         public virtual MethodBuilder Define (TypeContainer container)
6106                         {
6107                                 //
6108                                 // Check for custom access modifier
6109                                 //
6110                                 if (ModFlags == 0) {
6111                                         ModFlags = method.ModFlags;
6112                                         flags = method.flags;
6113                                 } else {
6114                                         if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
6115                                                 Report.Error (442, Location, "{0}': abstract properties cannot have private accessors", GetSignatureForError (container));
6116                                         }
6117
6118                                         CheckModifiers (container, ModFlags);
6119                                         ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
6120                                         ModFlags |= Modifiers.PROPERTY_CUSTOM;
6121                                         flags = Modifiers.MethodAttr (ModFlags);
6122                                         flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
6123                                 }
6124
6125                                 return null;
6126
6127                         }
6128
6129                         public bool HasCustomAccessModifier
6130                         {
6131                                 get {
6132                                         return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
6133                                 }
6134                         }
6135
6136                         public override Type[] ParameterTypes {
6137                                 get {
6138                                         return TypeManager.NoTypes;
6139                                 }
6140                         }
6141
6142                         public override EmitContext CreateEmitContext (TypeContainer tc,
6143                                                                        ILGenerator ig)
6144                         {
6145                                 return new EmitContext (
6146                                         tc, method.Parent, method.Location, ig, ReturnType,
6147                                         method.ModFlags, false);
6148                         }
6149
6150                         public override ObsoleteAttribute GetObsoleteAttribute ()
6151                         {
6152                                 return method.GetObsoleteAttribute (method.Parent);
6153                         }
6154
6155                         public override string GetSignatureForError (TypeContainer tc)
6156                         {
6157                                 return String.Concat (tc.Name, '.', method.Name);
6158                         }
6159                         
6160                         void CheckModifiers (TypeContainer container, int modflags)
6161                         {
6162                                 int flags = 0;
6163                                 int mflags = method.ModFlags & Modifiers.Accessibility;
6164
6165                                 if ((mflags & Modifiers.PUBLIC) != 0) {
6166                                         flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
6167                                 }
6168                                 else if ((mflags & Modifiers.PROTECTED) != 0) {
6169                                         if ((mflags & Modifiers.INTERNAL) != 0)
6170                                                 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
6171
6172                                         flags |= Modifiers.PRIVATE;
6173                                 }
6174                                 else if ((mflags & Modifiers.INTERNAL) != 0)
6175                                         flags |= Modifiers.PRIVATE;
6176
6177                                 if ((mflags == modflags) || (modflags & (~flags)) != 0)
6178                                         Report.Error (273, Location, "{0}: accessibility modifier must be more restrictive than the property or indexer",
6179                                                 GetSignatureForError (container));
6180                         }
6181
6182                         public override bool MarkForDuplicationCheck ()
6183                         {
6184                                 caching_flags |= Flags.TestMethodDuplication;
6185                                 return true;
6186                         }
6187                 }
6188
6189
6190                 public PropertyMethod Get, Set;
6191                 public PropertyBuilder PropertyBuilder;
6192                 public MethodBuilder GetBuilder, SetBuilder;
6193
6194                 protected EmitContext ec;
6195
6196                 public PropertyBase (TypeContainer ds, Expression type, int mod_flags,
6197                                      int allowed_mod, bool is_iface, MemberName name,
6198                                      Parameters parameters, Attributes attrs,
6199                                      Location loc)
6200                         : base (ds, type, mod_flags, allowed_mod, is_iface, name,
6201                                 attrs, parameters, loc)
6202                 {
6203                 }
6204
6205                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6206                 {
6207                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
6208                                 a.Error_InvalidSecurityParent ();
6209                                 return;
6210                         }
6211
6212                         PropertyBuilder.SetCustomAttribute (cb);
6213                 }
6214
6215                 public override AttributeTargets AttributeTargets {
6216                         get {
6217                                 return AttributeTargets.Property;
6218                         }
6219                 }
6220
6221                 public override bool Define ()
6222                 {
6223                         if (!DoDefine ())
6224                                 return false;
6225
6226                         if (!IsTypePermitted ())
6227                                 return false;
6228
6229                         return true;
6230                 }
6231
6232                 protected override bool DoDefine ()
6233                 {
6234                         if (!base.DoDefine ())
6235                                 return false;
6236
6237                         //
6238                         // Accessors modifiers check
6239                         //
6240                         if (Get.ModFlags != 0 && Set.ModFlags != 0) {
6241                                 Report.Error (274, Location, "'{0}': cannot specify accessibility modifiers for both accessors of the property or indexer.",
6242                                                 GetSignatureForError ());
6243                                 return false;
6244                         }
6245
6246                         if ((Get.IsDummy || Set.IsDummy)
6247                                         && (Get.ModFlags != 0 || Set.ModFlags != 0) && (ModFlags & Modifiers.OVERRIDE) == 0) {
6248                                 Report.Error (276, Location, 
6249                                         "'{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor.",
6250                                         GetSignatureForError ());
6251                                 return false;
6252                         }
6253
6254                         if (MemberType.IsAbstract && MemberType.IsSealed) {
6255                                 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
6256                                 return false;
6257                         }
6258
6259                         ec = new EmitContext (Parent, Location, null, MemberType, ModFlags);
6260                         return true;
6261                 }
6262
6263                 public override string GetSignatureForError()
6264                 {
6265                         if (PropertyBuilder == null)
6266                                 return GetSignatureForError (Parent);
6267
6268                         return TypeManager.CSharpSignature (PropertyBuilder, false);
6269                 }
6270
6271                 protected override bool CheckForDuplications ()
6272                 {
6273                         ArrayList ar = Parent.Indexers;
6274                         if (ar != null) {
6275                                 int arLen = ar.Count;
6276                                         
6277                                 for (int i = 0; i < arLen; i++) {
6278                                         Indexer m = (Indexer) ar [i];
6279                                         if (IsDuplicateImplementation (m))
6280                                                 return false;
6281                                 }
6282                         }
6283
6284                         ar = Parent.Properties;
6285                         if (ar != null) {
6286                                 int arLen = ar.Count;
6287                                         
6288                                 for (int i = 0; i < arLen; i++) {
6289                                         Property m = (Property) ar [i];
6290                                         if (IsDuplicateImplementation (m))
6291                                                 return false;
6292                                 }
6293                         }
6294
6295                         return true;
6296                 }
6297
6298                 // TODO: rename to Resolve......
6299                 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
6300                 {
6301                         PropertyInfo base_property = container.BaseCache.FindMemberToOverride (
6302                                 container.TypeBuilder, Name, ParameterTypes, true) as PropertyInfo;
6303   
6304                         if (base_property == null)
6305                                 return null;
6306   
6307                         base_ret_type = base_property.PropertyType;
6308                         MethodInfo get_accessor = base_property.GetGetMethod (true);
6309                         MethodInfo set_accessor = base_property.GetSetMethod (true);
6310                         MethodAttributes get_accessor_access, set_accessor_access;
6311
6312                         if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6313                                 if (Get != null && !Get.IsDummy && get_accessor == null) {
6314                                         Report.SymbolRelatedToPreviousError (base_property);
6315                                         Report.Error (545, Location, "'{0}': cannot override because '{1}' does not have an overridable get accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6316                                 }
6317
6318                                 if (Set != null && !Set.IsDummy && set_accessor == null) {
6319                                         Report.SymbolRelatedToPreviousError (base_property);
6320                                         Report.Error (546, Location, "'{0}': cannot override because '{1}' does not have an overridable set accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6321                                 }
6322                         }
6323                         
6324                         //
6325                         // Check base class accessors access
6326                         //
6327                         get_accessor_access = set_accessor_access = 0;
6328                         if ((ModFlags & Modifiers.NEW) == 0) {
6329                                 if (get_accessor != null) {
6330                                         MethodAttributes get_flags = Modifiers.MethodAttr (Get.ModFlags != 0 ? Get.ModFlags : ModFlags);
6331                                         get_accessor_access = (get_accessor.Attributes & MethodAttributes.MemberAccessMask);
6332
6333                                         if (!Get.IsDummy && !CheckAccessModifiers (get_flags & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
6334                                                 Report.Error (507, Location, "'{0}' can't change the access modifiers when overriding inherited member '{1}'",
6335                                                                 GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6336                                 }
6337
6338                                 if (set_accessor != null)  {
6339                                         MethodAttributes set_flags = Modifiers.MethodAttr (Set.ModFlags != 0 ? Set.ModFlags : ModFlags);
6340                                         set_accessor_access = (set_accessor.Attributes & MethodAttributes.MemberAccessMask);
6341
6342                                         if (!Set.IsDummy && !CheckAccessModifiers (set_flags & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6343                                                 Report.Error (507, Location, "'{0}' can't change the access modifiers when overriding inherited member '{1}'",
6344                                                                 GetSignatureForError (container), TypeManager.GetFullNameSignature (base_property));
6345                                 }
6346                         }
6347
6348                         //
6349                         // Get the less restrictive access
6350                         //
6351                         return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6352                 }
6353
6354                 public override void Emit ()
6355                 {
6356                         //
6357                         // The PropertyBuilder can be null for explicit implementations, in that
6358                         // case, we do not actually emit the ".property", so there is nowhere to
6359                         // put the attribute
6360                         //
6361                         if (PropertyBuilder != null && OptAttributes != null)
6362                                 OptAttributes.Emit (ec, this);
6363
6364                         if (!Get.IsDummy)
6365                                 Get.Emit (Parent);
6366
6367                         if (!Set.IsDummy)
6368                                 Set.Emit (Parent);
6369
6370                         base.Emit ();
6371                 }
6372
6373                 /// <summary>
6374                 /// Tests whether accessors are not in collision with some method (CS0111)
6375                 /// </summary>
6376                 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6377                 {
6378                         return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6379                 }
6380
6381                 public override bool IsUsed
6382                 {
6383                         get {
6384                                 if (IsExplicitImpl)
6385                                         return true;
6386
6387                                 return Get.IsUsed | Set.IsUsed;
6388                         }
6389                 }
6390
6391                 protected override void SetMemberName (MemberName new_name)
6392                 {
6393                         base.SetMemberName (new_name);
6394
6395                         Get.UpdateName (this);
6396                         Set.UpdateName (this);
6397                 }
6398
6399                 public override string[] ValidAttributeTargets {
6400                         get {
6401                                 return attribute_targets;
6402                         }
6403                 }
6404
6405                 //
6406                 //   Represents header string for documentation comment.
6407                 //
6408                 public override string DocCommentHeader {
6409                         get { return "P:"; }
6410                 }
6411         }
6412                         
6413         public class Property : PropertyBase, IIteratorContainer {
6414                 const int AllowedModifiers =
6415                         Modifiers.NEW |
6416                         Modifiers.PUBLIC |
6417                         Modifiers.PROTECTED |
6418                         Modifiers.INTERNAL |
6419                         Modifiers.PRIVATE |
6420                         Modifiers.STATIC |
6421                         Modifiers.SEALED |
6422                         Modifiers.OVERRIDE |
6423                         Modifiers.ABSTRACT |
6424                         Modifiers.UNSAFE |
6425                         Modifiers.EXTERN |
6426                         Modifiers.METHOD_YIELDS |
6427                         Modifiers.VIRTUAL;
6428
6429                 const int AllowedInterfaceModifiers =
6430                         Modifiers.NEW;
6431
6432                 public Property (TypeContainer ds, Expression type, int mod, bool is_iface,
6433                                  MemberName name, Attributes attrs, Accessor get_block,
6434                                  Accessor set_block, Location loc)
6435                         : base (ds, type, mod,
6436                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6437                                 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
6438                                 loc)
6439                 {
6440                         if (get_block == null)
6441                                 Get = new GetMethod (this);
6442                         else
6443                                 Get = new GetMethod (this, get_block);
6444
6445                         if (set_block == null)
6446                                 Set = new SetMethod (this);
6447                         else
6448                                 Set = new SetMethod (this, set_block);
6449                 }
6450
6451                 public override bool Define ()
6452                 {
6453                         if (!base.Define ())
6454                                 return false;
6455
6456                         if (!CheckBase ())
6457                                 return false;
6458
6459                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6460
6461                         if (!Get.IsDummy) {
6462
6463                                 GetBuilder = Get.Define (Parent);
6464                                 if (GetBuilder == null)
6465                                         return false;
6466
6467                                 //
6468                                 // Setup iterator if we are one
6469                                 //
6470                                 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
6471                                         Iterator iterator = new Iterator (
6472                                                 Parent, "get", MemberType,
6473                                                 Get.ParameterInfo,
6474                                                 ModFlags, Get.Block, Location);
6475                                         
6476                                         if (!iterator.DefineIterator ())
6477                                                 return false;
6478                                         Get.Block = iterator.Block;
6479                                 }
6480                         }
6481
6482                         if (!Set.IsDummy) {
6483                                 SetBuilder = Set.Define (Parent);
6484                                 if (SetBuilder == null)
6485                                         return false;
6486
6487                                 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
6488                         }
6489
6490                         // FIXME - PropertyAttributes.HasDefault ?
6491                         
6492                         PropertyAttributes prop_attr = PropertyAttributes.None;
6493                         if (!IsInterface)
6494                                 prop_attr |= PropertyAttributes.RTSpecialName |
6495                                         PropertyAttributes.SpecialName;
6496
6497                         PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6498                              Name, prop_attr, MemberType, null);
6499                         
6500                         if (!Get.IsDummy)
6501                                 PropertyBuilder.SetGetMethod (GetBuilder);
6502                                 
6503                         if (!Set.IsDummy)
6504                                 PropertyBuilder.SetSetMethod (SetBuilder);
6505                         
6506                         TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
6507                         return true;
6508                 }
6509
6510                 public void SetYields ()
6511                 {
6512                         ModFlags |= Modifiers.METHOD_YIELDS;
6513                 }
6514         }
6515
6516         /// </summary>
6517         ///  Gigantic workaround  for lameness in SRE follows :
6518         ///  This class derives from EventInfo and attempts to basically
6519         ///  wrap around the EventBuilder so that FindMembers can quickly
6520         ///  return this in it search for members
6521         /// </summary>
6522         public class MyEventBuilder : EventInfo {
6523                 
6524                 //
6525                 // We use this to "point" to our Builder which is
6526                 // not really a MemberInfo
6527                 //
6528                 EventBuilder MyBuilder;
6529                 
6530                 //
6531                 // We "catch" and wrap these methods
6532                 //
6533                 MethodInfo raise, remove, add;
6534
6535                 EventAttributes attributes;
6536                 Type declaring_type, reflected_type, event_type;
6537                 string name;
6538
6539                 Event my_event;
6540
6541                 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6542                 {
6543                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6544
6545                         // And now store the values in our own fields.
6546                         
6547                         declaring_type = type_builder;
6548
6549                         reflected_type = type_builder;
6550                         
6551                         attributes = event_attr;
6552                         this.name = name;
6553                         my_event = ev;
6554                         this.event_type = event_type;
6555                 }
6556                 
6557                 //
6558                 // Methods that you have to override.  Note that you only need 
6559                 // to "implement" the variants that take the argument (those are
6560                 // the "abstract" methods, the others (GetAddMethod()) are 
6561                 // regular.
6562                 //
6563                 public override MethodInfo GetAddMethod (bool nonPublic)
6564                 {
6565                         return add;
6566                 }
6567                 
6568                 public override MethodInfo GetRemoveMethod (bool nonPublic)
6569                 {
6570                         return remove;
6571                 }
6572                 
6573                 public override MethodInfo GetRaiseMethod (bool nonPublic)
6574                 {
6575                         return raise;
6576                 }
6577                 
6578                 //
6579                 // These methods make "MyEventInfo" look like a Builder
6580                 //
6581                 public void SetRaiseMethod (MethodBuilder raiseMethod)
6582                 {
6583                         raise = raiseMethod;
6584                         MyBuilder.SetRaiseMethod (raiseMethod);
6585                 }
6586
6587                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
6588                 {
6589                         remove = removeMethod;
6590                         MyBuilder.SetRemoveOnMethod (removeMethod);
6591                 }
6592
6593                 public void SetAddOnMethod (MethodBuilder addMethod)
6594                 {
6595                         add = addMethod;
6596                         MyBuilder.SetAddOnMethod (addMethod);
6597                 }
6598
6599                 public void SetCustomAttribute (CustomAttributeBuilder cb)
6600                 {
6601                         MyBuilder.SetCustomAttribute (cb);
6602                 }
6603                 
6604                 public override object [] GetCustomAttributes (bool inherit)
6605                 {
6606                         // FIXME : There's nothing which can be seemingly done here because
6607                         // we have no way of getting at the custom attribute objects of the
6608                         // EventBuilder !
6609                         return null;
6610                 }
6611
6612                 public override object [] GetCustomAttributes (Type t, bool inherit)
6613                 {
6614                         // FIXME : Same here !
6615                         return null;
6616                 }
6617
6618                 public override bool IsDefined (Type t, bool b)
6619                 {
6620                         return true;
6621                 }
6622
6623                 public override EventAttributes Attributes {
6624                         get {
6625                                 return attributes;
6626                         }
6627                 }
6628
6629                 public override string Name {
6630                         get {
6631                                 return name;
6632                         }
6633                 }
6634
6635                 public override Type DeclaringType {
6636                         get {
6637                                 return declaring_type;
6638                         }
6639                 }
6640
6641                 public override Type ReflectedType {
6642                         get {
6643                                 return reflected_type;
6644                         }
6645                 }
6646
6647                 public Type EventType {
6648                         get {
6649                                 return event_type;
6650                         }
6651                 }
6652                 
6653                 public void SetUsed ()
6654                 {
6655                         if (my_event != null) {
6656                                 my_event.status = FieldBase.Status.ASSIGNED;
6657                                 my_event.SetMemberIsUsed ();
6658                         }
6659                 }
6660         }
6661         
6662         /// <summary>
6663         /// For case when event is declared like property (with add and remove accessors).
6664         /// </summary>
6665         public class EventProperty: Event {
6666
6667                 static string[] attribute_targets = new string [] { "event", "property" };
6668
6669                 public EventProperty (TypeContainer parent, Expression type, int mod_flags,
6670                                       bool is_iface, MemberName name, Object init,
6671                                       Attributes attrs, Accessor add, Accessor remove,
6672                                       Location loc)
6673                         : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
6674                 {
6675                         Add = new AddDelegateMethod (this, add);
6676                         Remove = new RemoveDelegateMethod (this, remove);
6677
6678                         // For this event syntax we don't report error CS0067
6679                         // because it is hard to do it.
6680                         SetAssigned ();
6681                 }
6682
6683                 public override string[] ValidAttributeTargets {
6684                         get {
6685                                 return attribute_targets;
6686                         }
6687                 }
6688         }
6689
6690         /// <summary>
6691         /// Event is declared like field.
6692         /// </summary>
6693         public class EventField: Event {
6694
6695                 static string[] attribute_targets = new string [] { "event", "field", "method" };
6696                 static string[] attribute_targets_interface = new string[] { "event", "method" };
6697
6698                 public EventField (TypeContainer parent, Expression type, int mod_flags,
6699                                    bool is_iface, MemberName name, Object init,
6700                                    Attributes attrs, Location loc)
6701                         : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
6702                 {
6703                         Add = new AddDelegateMethod (this);
6704                         Remove = new RemoveDelegateMethod (this);
6705                 }
6706
6707                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6708                 {
6709                         if (a.Target == AttributeTargets.Field) {
6710                                 FieldBuilder.SetCustomAttribute (cb);
6711                                 return;
6712                         }
6713
6714                         if (a.Target == AttributeTargets.Method) {
6715                                 Add.ApplyAttributeBuilder (a, cb);
6716                                 Remove.ApplyAttributeBuilder (a, cb);
6717                                 return;
6718                         }
6719
6720                         base.ApplyAttributeBuilder (a, cb);
6721                 }
6722
6723                 public override string[] ValidAttributeTargets {
6724                         get {
6725                                 return IsInterface ? attribute_targets_interface : attribute_targets;
6726                         }
6727                 }
6728         }
6729
6730         public abstract class Event : FieldBase {
6731
6732                 protected sealed class AddDelegateMethod: DelegateMethod
6733                 {
6734
6735                         public AddDelegateMethod (Event method):
6736                                 base (method, "add_")
6737                         {
6738                         }
6739
6740                         public AddDelegateMethod (Event method, Accessor accessor):
6741                                 base (method, accessor, "add_")
6742                         {
6743                         }
6744
6745                         protected override MethodInfo DelegateMethodInfo {
6746                                 get {
6747                                         return TypeManager.delegate_combine_delegate_delegate;
6748                                 }
6749                         }
6750
6751                 }
6752
6753                 protected sealed class RemoveDelegateMethod: DelegateMethod
6754                 {
6755                         public RemoveDelegateMethod (Event method):
6756                                 base (method, "remove_")
6757                         {
6758                         }
6759
6760                         public RemoveDelegateMethod (Event method, Accessor accessor):
6761                                 base (method, accessor, "remove_")
6762                         {
6763                         }
6764
6765                         protected override MethodInfo DelegateMethodInfo {
6766                                 get {
6767                                         return TypeManager.delegate_remove_delegate_delegate;
6768                                 }
6769                         }
6770
6771                 }
6772
6773                 public abstract class DelegateMethod: AbstractPropertyEventMethod
6774                 {
6775                         protected readonly Event method;
6776                         ImplicitParameter param_attr;
6777
6778                         static string[] attribute_targets = new string [] { "method", "param", "return" };
6779
6780                         public DelegateMethod (Event method, string prefix)
6781                                 : base (method, prefix)
6782                         {
6783                                 this.method = method;
6784                         }
6785
6786                         public DelegateMethod (Event method, Accessor accessor, string prefix)
6787                                 : base (method, accessor, prefix)
6788                         {
6789                                 this.method = method;
6790                         }
6791
6792                         protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6793                         {
6794                                 if (a.Target == AttributeTargets.Parameter) {
6795                                         if (param_attr == null)
6796                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder, method.Location);
6797
6798                                         param_attr.ApplyAttributeBuilder (a, cb);
6799                                         return;
6800                                 }
6801
6802                                 base.ApplyAttributeBuilder (a, cb);
6803                         }
6804
6805                         public override AttributeTargets AttributeTargets {
6806                                 get {
6807                                         return AttributeTargets.Method;
6808                                 }
6809                         }
6810
6811                         public override bool IsClsCompliaceRequired(DeclSpace ds)
6812                         {
6813                                 return method.IsClsCompliaceRequired (ds);
6814                         }
6815
6816                         public MethodBuilder Define (TypeContainer container, InternalParameters ip)
6817                         {
6818                                 method_data = new MethodData (method, ip, method.ModFlags,
6819                                         method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
6820
6821                                 if (!method_data.Define (container))
6822                                         return null;
6823
6824                                 MethodBuilder mb = method_data.MethodBuilder;
6825                                 mb.DefineParameter (1, ParameterAttributes.None, "value");
6826                                 return mb;
6827                         }
6828
6829
6830                         protected override void EmitMethod (TypeContainer tc)
6831                         {
6832                                 if (block != null) {
6833                                         base.EmitMethod (tc);
6834                                         return;
6835                                 }
6836
6837                                 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
6838                                         return;
6839
6840                                 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
6841                                 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
6842
6843                                 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
6844                                 if ((method.ModFlags & Modifiers.STATIC) != 0) {
6845                                         ig.Emit (OpCodes.Ldsfld, field_info);
6846                                         ig.Emit (OpCodes.Ldarg_0);
6847                                         ig.Emit (OpCodes.Call, DelegateMethodInfo);
6848                                         ig.Emit (OpCodes.Castclass, method.MemberType);
6849                                         ig.Emit (OpCodes.Stsfld, field_info);
6850                                 } else {
6851                                         ig.Emit (OpCodes.Ldarg_0);
6852                                         ig.Emit (OpCodes.Ldarg_0);
6853                                         ig.Emit (OpCodes.Ldfld, field_info);
6854                                         ig.Emit (OpCodes.Ldarg_1);
6855                                         ig.Emit (OpCodes.Call, DelegateMethodInfo);
6856                                         ig.Emit (OpCodes.Castclass, method.MemberType);
6857                                         ig.Emit (OpCodes.Stfld, field_info);
6858                                 }
6859                                 ig.Emit (OpCodes.Ret);
6860                         }
6861
6862                         protected abstract MethodInfo DelegateMethodInfo { get; }
6863
6864                         public override Type[] ParameterTypes {
6865                                 get {
6866                                         return new Type[] { method.MemberType };
6867                                 }
6868                         }
6869
6870                         public override Type ReturnType {
6871                                 get {
6872                                         return TypeManager.void_type;
6873                                 }
6874                         }
6875
6876                         public override EmitContext CreateEmitContext (TypeContainer tc,
6877                                                                        ILGenerator ig)
6878                         {
6879                                 return new EmitContext (
6880                                         tc, method.Parent, Location, ig, ReturnType,
6881                                         method.ModFlags, false);
6882                         }
6883
6884                         public override string GetSignatureForError (TypeContainer tc)
6885                         {
6886                                 return String.Concat (tc.Name, '.', method.Name);
6887                         }
6888
6889                         public override ObsoleteAttribute GetObsoleteAttribute ()
6890                         {
6891                                 return method.GetObsoleteAttribute (method.Parent);
6892                         }
6893
6894                         public override string[] ValidAttributeTargets {
6895                                 get {
6896                                         return attribute_targets;
6897                                 }
6898                         }
6899                 }
6900
6901
6902                 const int AllowedModifiers =
6903                         Modifiers.NEW |
6904                         Modifiers.PUBLIC |
6905                         Modifiers.PROTECTED |
6906                         Modifiers.INTERNAL |
6907                         Modifiers.PRIVATE |
6908                         Modifiers.STATIC |
6909                         Modifiers.VIRTUAL |
6910                         Modifiers.SEALED |
6911                         Modifiers.OVERRIDE |
6912                         Modifiers.UNSAFE |
6913                         Modifiers.ABSTRACT;
6914
6915                 const int AllowedInterfaceModifiers =
6916                         Modifiers.NEW;
6917
6918                 public DelegateMethod Add, Remove;
6919                 public MyEventBuilder     EventBuilder;
6920                 public MethodBuilder AddBuilder, RemoveBuilder;
6921
6922                 public Event (TypeContainer parent, Expression type, int mod_flags,
6923                               bool is_iface, MemberName name, Object init, Attributes attrs,
6924                               Location loc)
6925                         : base (parent, type, mod_flags,
6926                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6927                                 name, init, attrs, loc)
6928                 {
6929                         IsInterface = is_iface;
6930                 }
6931
6932                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6933                 {
6934                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
6935                                 a.Error_InvalidSecurityParent ();
6936                                 return;
6937                         }
6938                         
6939                         EventBuilder.SetCustomAttribute (cb);
6940                 }
6941
6942                 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6943                 {
6944                         return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
6945                 }
6946
6947                 public override AttributeTargets AttributeTargets {
6948                         get {
6949                                 return AttributeTargets.Event;
6950                         }
6951                 }
6952
6953                 public override bool Define ()
6954                 {
6955                         EventAttributes e_attr;
6956                         e_attr = EventAttributes.None;
6957
6958                         if (!DoDefine ())
6959                                 return false;
6960
6961                         if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
6962                                 Report.Error (74, Location, "'" + Parent.Name + "." + Name +
6963                                               "': abstract event can not have an initializer");
6964                                 return false;
6965                         }
6966                         
6967                         if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
6968                                 Report.Error (66, Location, "'" + Parent.Name + "." + Name +
6969                                               "' : event must be of a delegate type");
6970                                 return false;
6971                         }
6972
6973                         EmitContext ec = Parent.EmitContext;
6974                         if (ec == null)
6975                                 throw new InternalErrorException ("Event.Define called too early?");
6976                         bool old_unsafe = ec.InUnsafe;
6977                         ec.InUnsafe = InUnsafe;
6978
6979                         Parameter [] parms = new Parameter [1];
6980                         parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null, Location);
6981                         Parameters parameters = new Parameters (parms, null);
6982                         Type [] types = parameters.GetParameterInfo (ec);
6983                         InternalParameters ip = new InternalParameters (types, parameters);
6984
6985                         ec.InUnsafe = old_unsafe;
6986
6987                         if (!CheckBase ())
6988                                 return false;
6989
6990                         //
6991                         // Now define the accessors
6992                         //
6993
6994                         AddBuilder = Add.Define (Parent, ip);
6995                         if (AddBuilder == null)
6996                                 return false;
6997
6998                         RemoveBuilder = Remove.Define (Parent, ip);
6999                         if (RemoveBuilder == null)
7000                                 return false;
7001
7002                         EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, e_attr, MemberType);
7003                         
7004                         if (Add.Block == null && Remove.Block == null && !IsInterface) {
7005                                 FieldBuilder = Parent.TypeBuilder.DefineField (
7006                                         Name, MemberType,
7007                                         FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
7008                                 TypeManager.RegisterPrivateFieldOfEvent (
7009                                         (EventInfo) EventBuilder, FieldBuilder);
7010                                 TypeManager.RegisterFieldBase (FieldBuilder, this);
7011                         }
7012                         
7013                         EventBuilder.SetAddOnMethod (AddBuilder);
7014                         EventBuilder.SetRemoveOnMethod (RemoveBuilder);
7015
7016                         TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder);
7017                         return true;
7018                 }
7019
7020                 protected override bool CheckBase ()
7021                 {
7022                         if (!base.CheckBase ())
7023                                 return false;
7024  
7025                         if (conflict_symbol != null && (ModFlags & Modifiers.NEW) == 0) {
7026                                 if (!(conflict_symbol is EventInfo)) {
7027                                         Report.SymbolRelatedToPreviousError (conflict_symbol);
7028                                         Report.Error (72, Location, "Event '{0}' can override only event", GetSignatureForError (Parent));
7029                                         return false;
7030                                 }
7031                         }
7032  
7033                         return true;
7034                 }
7035
7036                 public override void Emit ()
7037                 {
7038                         if (OptAttributes != null) {
7039                                 EmitContext ec = new EmitContext (
7040                                         Parent, Location, null, MemberType, ModFlags);
7041                                 OptAttributes.Emit (ec, this);
7042                         }
7043
7044                         Add.Emit (Parent);
7045                         Remove.Emit (Parent);
7046
7047                         base.Emit ();
7048                 }
7049
7050                 public override string GetSignatureForError ()
7051                 {
7052                         if (EventBuilder == null)
7053                                 return base.GetSignatureForError (Parent);
7054
7055                         return TypeManager.GetFullNameSignature (EventBuilder);
7056                 }
7057
7058                 //
7059                 //   Represents header string for documentation comment.
7060                 //
7061                 public override string DocCommentHeader {
7062                         get { return "E:"; }
7063                 }
7064         }
7065
7066
7067         public class Indexer : PropertyBase {
7068
7069                 class GetIndexerMethod: GetMethod
7070                 {
7071                         public GetIndexerMethod (MethodCore method):
7072                                 base (method)
7073                         {
7074                         }
7075
7076                         public GetIndexerMethod (MethodCore method, Accessor accessor):
7077                                 base (method, accessor)
7078                         {
7079                         }
7080
7081                         // TODO: one GetSignatureForError is enough (reuse Parent member)
7082                         public override string GetSignatureForError (TypeContainer tc)
7083                         {
7084                                 string core = base.GetSignatureForError (tc);
7085                                 return core.Replace (TypeContainer.DefaultIndexerName, 
7086                                         String.Format ("this[{0}]", TypeManager.CSharpName (ParameterTypes)));
7087                         }
7088
7089                         public override Type[] ParameterTypes {
7090                                 get {
7091                                         return method.ParameterTypes;
7092                                 }
7093                         }
7094                 }
7095
7096                 class SetIndexerMethod: SetMethod
7097                 {
7098                         readonly Parameters parameters;
7099
7100                         public SetIndexerMethod (MethodCore method):
7101                                 base (method)
7102                         {
7103                         }
7104
7105                         public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
7106                                 base (method, accessor)
7107                         {
7108                                 this.parameters = parameters;
7109                         }
7110
7111                         public override Type[] ParameterTypes {
7112                                 get {
7113                                         int top = method.ParameterTypes.Length;
7114                                         Type [] set_pars = new Type [top + 1];
7115                                         method.ParameterTypes.CopyTo (set_pars, 0);
7116                                         set_pars [top] = method.MemberType;
7117                                         return set_pars;
7118                                 }
7119                         }
7120
7121                         protected override InternalParameters GetParameterInfo (EmitContext ec)
7122                         {
7123                                 Parameter [] fixed_parms = parameters.FixedParameters;
7124
7125                                 if (fixed_parms == null){
7126                                         throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
7127                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7128                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7129                                         //
7130                                         // Here is the problem: the `value' parameter has
7131                                         // to come *after* the array parameter in the declaration
7132                                         // like this:
7133                                         // X (object [] x, Type value)
7134                                         // .param [0]
7135                                         //
7136                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7137                                         // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7138                                         
7139                                 }
7140                                 
7141                                 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
7142
7143                                 fixed_parms.CopyTo (tmp, 0);
7144                                 tmp [fixed_parms.Length] = new Parameter (
7145                                         method.Type, "value", Parameter.Modifier.NONE, null, method.Location);
7146
7147                                 Parameters set_formal_params = new Parameters (tmp, null);
7148                                 Type [] types = set_formal_params.GetParameterInfo (ec);
7149                                 
7150                                 return new InternalParameters (types, set_formal_params);
7151                         }
7152                 }
7153
7154
7155                 const int AllowedModifiers =
7156                         Modifiers.NEW |
7157                         Modifiers.PUBLIC |
7158                         Modifiers.PROTECTED |
7159                         Modifiers.INTERNAL |
7160                         Modifiers.PRIVATE |
7161                         Modifiers.VIRTUAL |
7162                         Modifiers.SEALED |
7163                         Modifiers.OVERRIDE |
7164                         Modifiers.UNSAFE |
7165                         Modifiers.EXTERN |
7166                         Modifiers.ABSTRACT;
7167
7168                 const int AllowedInterfaceModifiers =
7169                         Modifiers.NEW;
7170
7171
7172                 public Indexer (TypeContainer ds, Expression type, MemberName name, int mod,
7173                                 bool is_iface, Parameters parameters, Attributes attrs,
7174                                 Accessor get_block, Accessor set_block, Location loc)
7175                         : base (ds, type, mod,
7176                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
7177                                 is_iface, name, parameters, attrs, loc)
7178                 {
7179                         if (get_block == null)
7180                                 Get = new GetIndexerMethod (this);
7181                         else
7182                                 Get = new GetIndexerMethod (this, get_block);
7183
7184                         if (set_block == null)
7185                                 Set = new SetIndexerMethod (this);
7186                         else
7187                                 Set = new SetIndexerMethod (this, parameters, set_block);
7188                 }
7189                        
7190                 public override bool Define ()
7191                 {
7192                         PropertyAttributes prop_attr =
7193                                 PropertyAttributes.RTSpecialName |
7194                                 PropertyAttributes.SpecialName;
7195                         
7196                         if (!base.Define ())
7197                                 return false;
7198
7199                         if (MemberType == TypeManager.void_type) {
7200                                 Report.Error (620, Location, "Indexers cannot have void type");
7201                                 return false;
7202                         }
7203
7204                         if (OptAttributes != null) {
7205                                 Attribute indexer_attr = OptAttributes.Search (TypeManager.indexer_name_type, ec);
7206                                 if (indexer_attr != null) {
7207                                         // Remove the attribute from the list because it is not emitted
7208                                         OptAttributes.Attrs.Remove (indexer_attr);
7209
7210                                         ShortName = indexer_attr.GetIndexerAttributeValue (ec);
7211
7212                                         if (IsExplicitImpl) {
7213                                                 Report.Error (415, indexer_attr.Location,
7214                                                               "The 'IndexerName' attribute is valid only on an " +
7215                                                               "indexer that is not an explicit interface member declaration");
7216                                                 return false;
7217                                         }
7218
7219                                         if ((ModFlags & Modifiers.OVERRIDE) != 0) {
7220                                                 Report.Error (609, indexer_attr.Location,
7221                                                               "Cannot set the 'IndexerName' attribute on an indexer marked override");
7222                                                 return false;
7223                                         }
7224
7225                                         if (!Tokenizer.IsValidIdentifier (ShortName)) {
7226                                                 Report.Error (633, indexer_attr.Location,
7227                                                               "The argument to the 'IndexerName' attribute must be a valid identifier");
7228                                                 return false;
7229                                         }
7230                                 }
7231                         }
7232
7233                         if (InterfaceType != null) {
7234                                 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
7235                                 if (base_IndexerName != Name)
7236                                         ShortName = base_IndexerName;
7237                         }
7238
7239                         if (!Parent.AddToMemberContainer (this) ||
7240                                 !Parent.AddToMemberContainer (Get) || !Parent.AddToMemberContainer (Set))
7241                                 return false;
7242
7243                         if (!CheckBase ())
7244                                 return false;
7245
7246                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
7247                         if (!Get.IsDummy){
7248                                 GetBuilder = Get.Define (Parent);
7249                                 if (GetBuilder == null)
7250                                         return false;
7251                         }
7252                         
7253                         if (!Set.IsDummy){
7254                                 SetBuilder = Set.Define (Parent);
7255                                 if (SetBuilder == null)
7256                                         return false;
7257                         }
7258
7259                         //
7260                         // Now name the parameters
7261                         //
7262                         Parameter [] p = Parameters.FixedParameters;
7263                         if (p != null) {
7264                                 if ((p [0].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
7265                                         Report.Error (631, Location, "ref and out are not valid in this context");
7266                                         return false;
7267                                 }
7268
7269                                 int i;
7270                                 
7271                                 for (i = 0; i < p.Length; ++i) {
7272                                         if (!Get.IsDummy)
7273                                                 GetBuilder.DefineParameter (
7274                                                         i + 1, p [i].Attributes, p [i].Name);
7275
7276                                         if (!Set.IsDummy)
7277                                                 SetBuilder.DefineParameter (
7278                                                         i + 1, p [i].Attributes, p [i].Name);
7279                                 }
7280
7281                                 if (!Set.IsDummy)
7282                                         SetBuilder.DefineParameter (
7283                                                 i + 1, ParameterAttributes.None, "value");
7284                                         
7285                                 if (i != ParameterTypes.Length) {
7286                                         Parameter array_param = Parameters.ArrayParameter;
7287
7288                                         SetBuilder.DefineParameter (
7289                                                 i + 1, array_param.Attributes, array_param.Name);
7290                                 }
7291                         }
7292
7293                         PropertyBuilder = Parent.TypeBuilder.DefineProperty (
7294                                 Name, prop_attr, MemberType, ParameterTypes);
7295                         
7296                         if (!Get.IsDummy)
7297                                 PropertyBuilder.SetGetMethod (GetBuilder);
7298
7299                         if (!Set.IsDummy)
7300                                 PropertyBuilder.SetSetMethod (SetBuilder);
7301                                 
7302                         TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, ParameterTypes);
7303
7304                         return true;
7305                 }
7306
7307                 public override string GetSignatureForError ()
7308                 {
7309                         if (PropertyBuilder == null)
7310                                 return GetSignatureForError (Parent);
7311
7312                         return TypeManager.CSharpSignature (PropertyBuilder, true);
7313                 }
7314
7315                 public override string GetSignatureForError(TypeContainer tc)
7316                 {
7317                         return String.Concat (tc.Name, ".this[", Parameters.FixedParameters [0].TypeName.ToString (), ']');
7318                 }
7319
7320                 public override bool MarkForDuplicationCheck ()
7321                 {
7322                         caching_flags |= Flags.TestMethodDuplication;
7323                         return true;
7324                 }
7325
7326         }
7327
7328         public class Operator : MethodCore, IIteratorContainer {
7329
7330                 const int AllowedModifiers =
7331                         Modifiers.PUBLIC |
7332                         Modifiers.UNSAFE |
7333                         Modifiers.EXTERN |
7334                         Modifiers.STATIC;
7335
7336                 public enum OpType : byte {
7337
7338                         // Unary operators
7339                         LogicalNot,
7340                         OnesComplement,
7341                         Increment,
7342                         Decrement,
7343                         True,
7344                         False,
7345
7346                         // Unary and Binary operators
7347                         Addition,
7348                         Subtraction,
7349
7350                         UnaryPlus,
7351                         UnaryNegation,
7352                         
7353                         // Binary operators
7354                         Multiply,
7355                         Division,
7356                         Modulus,
7357                         BitwiseAnd,
7358                         BitwiseOr,
7359                         ExclusiveOr,
7360                         LeftShift,
7361                         RightShift,
7362                         Equality,
7363                         Inequality,
7364                         GreaterThan,
7365                         LessThan,
7366                         GreaterThanOrEqual,
7367                         LessThanOrEqual,
7368
7369                         // Implicit and Explicit
7370                         Implicit,
7371                         Explicit
7372                 };
7373
7374                 public readonly OpType OperatorType;
7375                 public MethodBuilder   OperatorMethodBuilder;
7376                 
7377                 public Method OperatorMethod;
7378
7379                 static string[] attribute_targets = new string [] { "method", "return" };
7380
7381                 public Operator (TypeContainer parent, OpType type, Expression ret_type,
7382                                  int mod_flags, Parameters parameters,
7383                                  ToplevelBlock block, Attributes attrs, Location loc)
7384                         : base (parent, ret_type, mod_flags, AllowedModifiers, false,
7385                                 new MemberName ("op_" + type), attrs, parameters, loc)
7386                 {
7387                         OperatorType = type;
7388                         Block = block;
7389                 }
7390
7391                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) 
7392                 {
7393                         OperatorMethod.ApplyAttributeBuilder (a, cb);
7394                 }
7395
7396                 public override AttributeTargets AttributeTargets {
7397                         get {
7398                                 return AttributeTargets.Method; 
7399                         }
7400                 }
7401                 
7402                 protected override bool CheckForDuplications()
7403                 {
7404                         ArrayList ar = Parent.Operators;
7405                         if (ar != null) {
7406                                 int arLen = ar.Count;
7407                                         
7408                                 for (int i = 0; i < arLen; i++) {
7409                                         Operator o = (Operator) ar [i];
7410                                         if (IsDuplicateImplementation (o))
7411                                                 return false;
7412                                 }
7413                         }
7414
7415                         ar = Parent.Methods;
7416                         if (ar != null) {
7417                                 int arLen = ar.Count;
7418                                         
7419                                 for (int i = 0; i < arLen; i++) {
7420                                         Method m = (Method) ar [i];
7421                                         if (IsDuplicateImplementation (m))
7422                                                 return false;
7423                                 }
7424                         }
7425
7426                         return true;
7427                 }
7428
7429                 public override bool Define ()
7430                 {
7431
7432                         const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
7433                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
7434                                 Report.Error (558, Location, "User defined operators '{0}' must be declared static and public", GetSignatureForError (Parent));
7435                                 return false;
7436                         }
7437
7438                         if (!DoDefine ())
7439                                 return false;
7440
7441                         if (MemberType == TypeManager.void_type) {
7442                                 Report.Error (590, Location, "User-defined operators cannot return void");
7443                                 return false;
7444                         }
7445
7446                         OperatorMethod = new Method (
7447                                 Parent, Type, ModFlags, false, MemberName,
7448                                 Parameters, OptAttributes, Location);
7449
7450                         OperatorMethod.Block = Block;
7451                         OperatorMethod.IsOperator = true;                       
7452                         OperatorMethod.flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
7453                         OperatorMethod.Define ();
7454
7455                         if (OperatorMethod.MethodBuilder == null)
7456                                 return false;
7457
7458                         OperatorMethodBuilder = OperatorMethod.MethodBuilder;
7459
7460                         parameter_types = OperatorMethod.ParameterTypes;
7461                         Type declaring_type = OperatorMethodBuilder.DeclaringType;
7462                         Type return_type = OperatorMethod.ReturnType;
7463                         Type first_arg_type = parameter_types [0];
7464
7465                         if (!CheckBase ())
7466                                 return false;
7467
7468                         // Rules for conversion operators
7469                         
7470                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7471                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
7472                                         Report.Error (
7473                                                 555, Location,
7474                                                 "User-defined conversion cannot take an object of the " +
7475                                                 "enclosing type and convert to an object of the enclosing" +
7476                                                 " type");
7477                                         return false;
7478                                 }
7479                                 
7480                                 if (first_arg_type != declaring_type && return_type != declaring_type){
7481                                         Report.Error (
7482                                                 556, Location, 
7483                                                 "User-defined conversion must convert to or from the " +
7484                                                 "enclosing type");
7485                                         return false;
7486                                 }
7487                                 
7488                                 if (first_arg_type == TypeManager.object_type ||
7489                                         return_type == TypeManager.object_type){
7490                                         Report.Error (
7491                                                 -8, Location,
7492                                                 "User-defined conversion cannot convert to or from " +
7493                                                 "object type");
7494                                         return false;
7495                                 }
7496
7497                                 if (first_arg_type.IsInterface || return_type.IsInterface){
7498                                         Report.Error (
7499                                                 552, Location,
7500                                                 "User-defined conversion cannot convert to or from an " +
7501                                                 "interface type");
7502                                         return false;
7503                                 }
7504                                 
7505                                 if (first_arg_type.IsSubclassOf (return_type)
7506                                         || return_type.IsSubclassOf (first_arg_type)){
7507                                         if (declaring_type.IsSubclassOf (return_type)) {
7508                                                 Report.Error (553, Location, "'{0}' : user defined conversion to/from base class", GetSignatureForError ());
7509                                                 return false;
7510                                         }
7511                                         Report.Error (554, Location, "'{0}' : user defined conversion to/from derived class", GetSignatureForError ());
7512                                         return false;
7513                                 }
7514                         } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
7515                                 if (first_arg_type != declaring_type || parameter_types [1] != TypeManager.int32_type) {
7516                                         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");
7517                                         return false;
7518                                 }
7519                         } else if (Parameters.FixedParameters.Length == 1) {
7520                                 // Checks for Unary operators
7521
7522                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7523                                         if (return_type != declaring_type && !return_type.IsSubclassOf (declaring_type)) {
7524                                                 Report.Error (448, Location,
7525                                                         "The return type for ++ or -- operator must be the containing type or derived from the containing type");
7526                                                 return false;
7527                                         }
7528                                         if (first_arg_type != declaring_type) {
7529                                                 Report.Error (
7530                                                         559, Location, "The parameter type for ++ or -- operator must be the containing type");
7531                                                 return false;
7532                                         }
7533                                 }
7534                                 
7535                                 if (first_arg_type != declaring_type){
7536                                         Report.Error (
7537                                                 562, Location,
7538                                                 "The parameter of a unary operator must be the " +
7539                                                 "containing type");
7540                                         return false;
7541                                 }
7542                                 
7543                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7544                                         if (return_type != TypeManager.bool_type){
7545                                                 Report.Error (
7546                                                         215, Location,
7547                                                         "The return type of operator True or False " +
7548                                                         "must be bool");
7549                                                 return false;
7550                                         }
7551                                 }
7552                                 
7553                         } else {
7554                                 // Checks for Binary operators
7555                                 
7556                                 if (first_arg_type != declaring_type &&
7557                                     parameter_types [1] != declaring_type){
7558                                         Report.Error (
7559                                                 563, Location,
7560                                                 "One of the parameters of a binary operator must " +
7561                                                 "be the containing type");
7562                                         return false;
7563                                 }
7564                         }
7565
7566                         return true;
7567                 }
7568                 
7569                 public override void Emit ()
7570                 {
7571                         //
7572                         // abstract or extern methods have no bodies
7573                         //
7574                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
7575                                 return;
7576                         
7577                         OperatorMethod.Emit ();
7578                         Block = null;
7579                 }
7580
7581                 // Operator cannot be override
7582                 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
7583                 {
7584                         return null;
7585                 }
7586
7587                 public static string GetName (OpType ot)
7588                 {
7589                         switch (ot){
7590                         case OpType.LogicalNot:
7591                                 return "!";
7592                         case OpType.OnesComplement:
7593                                 return "~";
7594                         case OpType.Increment:
7595                                 return "++";
7596                         case OpType.Decrement:
7597                                 return "--";
7598                         case OpType.True:
7599                                 return "true";
7600                         case OpType.False:
7601                                 return "false";
7602                         case OpType.Addition:
7603                                 return "+";
7604                         case OpType.Subtraction:
7605                                 return "-";
7606                         case OpType.UnaryPlus:
7607                                 return "+";
7608                         case OpType.UnaryNegation:
7609                                 return "-";
7610                         case OpType.Multiply:
7611                                 return "*";
7612                         case OpType.Division:
7613                                 return "/";
7614                         case OpType.Modulus:
7615                                 return "%";
7616                         case OpType.BitwiseAnd:
7617                                 return "&";
7618                         case OpType.BitwiseOr:
7619                                 return "|";
7620                         case OpType.ExclusiveOr:
7621                                 return "^";
7622                         case OpType.LeftShift:
7623                                 return "<<";
7624                         case OpType.RightShift:
7625                                 return ">>";
7626                         case OpType.Equality:
7627                                 return "==";
7628                         case OpType.Inequality:
7629                                 return "!=";
7630                         case OpType.GreaterThan:
7631                                 return ">";
7632                         case OpType.LessThan:
7633                                 return "<";
7634                         case OpType.GreaterThanOrEqual:
7635                                 return ">=";
7636                         case OpType.LessThanOrEqual:
7637                                 return "<=";
7638                         case OpType.Implicit:
7639                                 return "implicit";
7640                         case OpType.Explicit:
7641                                 return "explicit";
7642                         default: return "";
7643                         }
7644                 }
7645
7646                 public override string GetSignatureForError (TypeContainer tc)
7647                 {
7648                         StringBuilder sb = new StringBuilder ();
7649                         sb.AppendFormat ("{0}.operator {1} {2}({3}", tc.Name, GetName (OperatorType), Type.Type == null ? Type.ToString () : TypeManager.CSharpName (Type.Type),
7650                                 Parameters.FixedParameters [0].GetSignatureForError ());
7651                         
7652                         if (Parameters.FixedParameters.Length > 1) {
7653                                 sb.Append (",");
7654                                 sb.Append (Parameters.FixedParameters [1].GetSignatureForError ());
7655                         }
7656                         sb.Append (")");
7657                         return sb.ToString ();
7658                 }
7659
7660                 public override string GetSignatureForError ()
7661                 {
7662                         return ToString ();
7663                 }
7664
7665                 public override bool MarkForDuplicationCheck ()
7666                 {
7667                         caching_flags |= Flags.TestMethodDuplication;
7668                         return true;
7669                 }
7670
7671                 public override string ToString ()
7672                 {
7673                         if (OperatorMethod == null)
7674                                 return Name;
7675
7676                         Type return_type = OperatorMethod.ReturnType;
7677                         Type [] param_types = OperatorMethod.ParameterTypes;
7678                         
7679                         if (Parameters.FixedParameters.Length == 1)
7680                                 return String.Format (
7681                                         "{0} operator {1}({2})",
7682                                         TypeManager.CSharpName (return_type),
7683                                         GetName (OperatorType),
7684                                         param_types [0]);
7685                         else
7686                                 return String.Format (
7687                                         "{0} operator {1}({2}, {3})",
7688                                         TypeManager.CSharpName (return_type),
7689                                         GetName (OperatorType),
7690                                         param_types [0], param_types [1]);
7691                 }
7692
7693                 public override string[] ValidAttributeTargets {
7694                         get {
7695                                 return attribute_targets;
7696                         }
7697                 }
7698
7699                 public void SetYields ()
7700                 {
7701                         ModFlags |= Modifiers.METHOD_YIELDS;
7702                 }
7703         }
7704
7705         //
7706         // This is used to compare method signatures
7707         //
7708         struct MethodSignature {
7709                 public string Name;
7710                 public Type RetType;
7711                 public Type [] Parameters;
7712                 
7713                 /// <summary>
7714                 ///    This delegate is used to extract methods which have the
7715                 ///    same signature as the argument
7716                 /// </summary>
7717                 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
7718                 
7719                 public MethodSignature (string name, Type ret_type, Type [] parameters)
7720                 {
7721                         Name = name;
7722                         RetType = ret_type;
7723
7724                         if (parameters == null)
7725                                 Parameters = TypeManager.NoTypes;
7726                         else
7727                                 Parameters = parameters;
7728                 }
7729
7730                 public override string ToString ()
7731                 {
7732                         string pars = "";
7733                         if (Parameters.Length != 0){
7734                                 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
7735                                 for (int i = 0; i < Parameters.Length; i++){
7736                                         sb.Append (Parameters [i]);
7737                                         if (i+1 < Parameters.Length)
7738                                                 sb.Append (", ");
7739                                 }
7740                                 pars = sb.ToString ();
7741                         }
7742
7743                         return String.Format ("{0} {1} ({2})", RetType, Name, pars);
7744                 }
7745                 
7746                 public override int GetHashCode ()
7747                 {
7748                         return Name.GetHashCode ();
7749                 }
7750
7751                 public override bool Equals (Object o)
7752                 {
7753                         MethodSignature other = (MethodSignature) o;
7754
7755                         if (other.Name != Name)
7756                                 return false;
7757
7758                         if (other.RetType != RetType)
7759                                 return false;
7760                         
7761                         if (Parameters == null){
7762                                 if (other.Parameters == null)
7763                                         return true;
7764                                 return false;
7765                         }
7766
7767                         if (other.Parameters == null)
7768                                 return false;
7769                         
7770                         int c = Parameters.Length;
7771                         if (other.Parameters.Length != c)
7772                                 return false;
7773
7774                         for (int i = 0; i < c; i++)
7775                                 if (other.Parameters [i] != Parameters [i])
7776                                         return false;
7777
7778                         return true;
7779                 }
7780
7781                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
7782                 {
7783                         MethodSignature sig = (MethodSignature) filter_criteria;
7784
7785                         if (m.Name != sig.Name)
7786                                 return false;
7787
7788                         Type ReturnType;
7789                         MethodInfo mi = m as MethodInfo;
7790                         PropertyInfo pi = m as PropertyInfo;
7791
7792                         if (mi != null)
7793                                 ReturnType = mi.ReturnType;
7794                         else if (pi != null)
7795                                 ReturnType = pi.PropertyType;
7796                         else
7797                                 return false;
7798                         
7799                         //
7800                         // we use sig.RetType == null to mean `do not check the
7801                         // method return value.  
7802                         //
7803                         if (sig.RetType != null)
7804                                 if (ReturnType != sig.RetType)
7805                                         return false;
7806
7807                         Type [] args;
7808                         if (mi != null)
7809                                 args = TypeManager.GetArgumentTypes (mi);
7810                         else
7811                                 args = TypeManager.GetArgumentTypes (pi);
7812                         Type [] sigp = sig.Parameters;
7813
7814                         if (args.Length != sigp.Length)
7815                                 return false;
7816
7817                         for (int i = args.Length; i > 0; ){
7818                                 i--;
7819                                 if (args [i] != sigp [i])
7820                                         return false;
7821                         }
7822                         return true;
7823                 }
7824         }
7825 }