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