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