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