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