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