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