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