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