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