2006-08-30 Robert Jordan <robertj@gmx.net>
[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 (!CheckBase ())
5206                                 return false;
5207                         
5208                         if (!Parent.AsAccessible (MemberType, ModFlags)) {
5209                                 Report.Error (52, Location,
5210                                         "Inconsistent accessibility: field type `" +
5211                                         TypeManager.CSharpName (MemberType) + "' is less " +
5212                                         "accessible than field `" + GetSignatureForError () + "'");
5213                                 return false;
5214                         }
5215
5216                         if (!IsTypePermitted ())
5217                                 return false;
5218
5219                         return true;
5220                 }
5221
5222                 public override void Emit ()
5223                 {
5224                         if (OptAttributes != null) {
5225                                 OptAttributes.Emit ();
5226                         }
5227
5228                         if (((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0 && Parent.PartialContainer.HasExplicitLayout) {
5229                                 Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
5230                         }
5231
5232                         base.Emit ();
5233                 }
5234
5235                 //
5236                 //   Represents header string for documentation comment.
5237                 //
5238                 public override string DocCommentHeader {
5239                         get { return "F:"; }
5240                 }
5241         }
5242
5243         interface IFixedBuffer
5244         {
5245                 FieldInfo Element { get; }
5246                 Type ElementType { get; }
5247         }
5248
5249         public class FixedFieldExternal: IFixedBuffer
5250         {
5251                 FieldInfo element_field;
5252
5253                 public FixedFieldExternal (FieldInfo fi)
5254                 {
5255                         element_field = fi.FieldType.GetField (FixedField.FixedElementName);
5256                 }
5257
5258                 #region IFixedField Members
5259
5260                 public FieldInfo Element {
5261                         get {
5262                                 return element_field;
5263                         }
5264                 }
5265
5266                 public Type ElementType {
5267                         get {
5268                                 return element_field.FieldType;
5269                         }
5270                 }
5271
5272                 #endregion
5273         }
5274
5275         /// <summary>
5276         /// Fixed buffer implementation
5277         /// </summary>
5278         public class FixedField : FieldMember, IFixedBuffer
5279         {
5280                 public const string FixedElementName = "FixedElementField";
5281                 static int GlobalCounter = 0;
5282                 static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
5283                 static FieldInfo[] fi;
5284
5285                 TypeBuilder fixed_buffer_type;
5286                 FieldBuilder element;
5287                 Expression size_expr;
5288                 int buffer_size;
5289
5290                 const int AllowedModifiers =
5291                         Modifiers.NEW |
5292                         Modifiers.PUBLIC |
5293                         Modifiers.PROTECTED |
5294                         Modifiers.INTERNAL |
5295                         Modifiers.PRIVATE;
5296
5297                 public FixedField (DeclSpace parent, Expression type, int mod, string name,
5298                         Expression size_expr, Attributes attrs, Location loc):
5299                         base (parent, type, mod, AllowedModifiers, new MemberName (name, loc), attrs)
5300                 {
5301                         if (RootContext.Version == LanguageVersion.ISO_1)
5302                                 Report.FeatureIsNotStandardized (loc, "fixed size buffers");
5303
5304                         this.size_expr = size_expr;
5305                 }
5306
5307                 public override bool Define()
5308                 {
5309 #if !NET_2_0
5310                         if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) != 0)
5311                                 Report.Warning (-23, 1, Location, "Only private or internal fixed sized buffers are supported by .NET 1.x");
5312 #endif
5313
5314                         if (Parent.PartialContainer.Kind != Kind.Struct) {
5315                                 Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs",
5316                                         GetSignatureForError ());
5317                                 return false;
5318                         }
5319
5320                         if (!base.Define ())
5321                                 return false;
5322
5323                         if (!TypeManager.IsPrimitiveType (MemberType)) {
5324                                 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",
5325                                         GetSignatureForError ());
5326                                 return false;
5327                         }
5328
5329                         EmitContext ec = new EmitContext (this, Parent, Location, null, null, ModFlags);
5330                         Constant c = size_expr.ResolveAsConstant (ec, this);
5331                         if (c == null)
5332                                 return false;
5333
5334                         IntConstant buffer_size_const = c.ToInt (Location);
5335                         if (buffer_size_const == null)
5336                                 return false;
5337
5338                         buffer_size = buffer_size_const.Value;
5339
5340                         if (buffer_size <= 0) {
5341                                 Report.Error (1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError ());
5342                                 return false;
5343                         }
5344
5345                         int type_size = Expression.GetTypeSize (MemberType);
5346
5347                         if (buffer_size > int.MaxValue / type_size) {
5348                                 Report.Error (1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit",
5349                                         GetSignatureForError (), buffer_size.ToString (), TypeManager.CSharpName (MemberType));
5350                                 return false;
5351                         }
5352
5353                         buffer_size *= type_size;
5354
5355                         // Define nested
5356                         string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
5357
5358                         fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
5359                                 TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
5360                         element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
5361                         RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
5362
5363                         FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
5364                         TypeManager.RegisterFieldBase (FieldBuilder, this);
5365
5366                         return true;
5367                 }
5368
5369                 public override void Emit()
5370                 {
5371                         if (fi == null)
5372                                 fi = new FieldInfo [] { TypeManager.struct_layout_attribute_type.GetField ("Size") };
5373
5374                         object[] fi_val = new object[1];
5375                         fi_val [0] = buffer_size;
5376
5377                         CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.struct_layout_attribute_ctor, 
5378                                 ctor_args, fi, fi_val);
5379                         fixed_buffer_type.SetCustomAttribute (cab);
5380
5381 #if NET_2_0
5382                         cab = new CustomAttributeBuilder (TypeManager.fixed_buffer_attr_ctor, new object[] { MemberType, buffer_size } );
5383                         FieldBuilder.SetCustomAttribute (cab);
5384 #endif
5385                         base.Emit ();
5386                 }
5387
5388                 protected override bool IsFieldClsCompliant {
5389                         get {
5390                                 return false;
5391                         }
5392                 }
5393
5394                 #region IFixedField Members
5395
5396                 public FieldInfo Element {
5397                         get {
5398                                 return element;
5399                         }
5400                 }
5401
5402                 public Type ElementType {
5403                         get {
5404                                 return MemberType;
5405                         }
5406                 }
5407
5408                 #endregion
5409         }
5410
5411         //
5412         // The Field class is used to represents class/struct fields during parsing.
5413         //
5414         public class Field : FieldMember {
5415                 // <summary>
5416                 //   Modifiers allowed in a class declaration
5417                 // </summary>
5418                 const int AllowedModifiers =
5419                         Modifiers.NEW |
5420                         Modifiers.PUBLIC |
5421                         Modifiers.PROTECTED |
5422                         Modifiers.INTERNAL |
5423                         Modifiers.PRIVATE |
5424                         Modifiers.STATIC |
5425                         Modifiers.VOLATILE |
5426                         Modifiers.UNSAFE |
5427                         Modifiers.READONLY;
5428
5429                 public Field (DeclSpace parent, Expression type, int mod, string name,
5430                               Attributes attrs, Location loc)
5431                         : base (parent, type, mod, AllowedModifiers, new MemberName (name, loc),
5432                                 attrs)
5433                 {
5434                 }
5435
5436                 public override bool Define ()
5437                 {
5438                         if (!base.Define ())
5439                                 return false;
5440
5441                         if (RootContext.WarningLevel > 1){
5442                                 Type ptype = Parent.TypeBuilder.BaseType;
5443
5444                                 // ptype is only null for System.Object while compiling corlib.
5445                                 if (ptype != null){
5446                                         TypeContainer.FindMembers (
5447                                                 ptype, MemberTypes.Method,
5448                                                 BindingFlags.Public |
5449                                                 BindingFlags.Static | BindingFlags.Instance,
5450                                                 System.Type.FilterName, Name);
5451                                 }
5452                         }
5453
5454                         if ((ModFlags & Modifiers.VOLATILE) != 0){
5455                                 if (!MemberType.IsClass){
5456                                         Type vt = MemberType;
5457                                         
5458                                         if (TypeManager.IsEnumType (vt))
5459                                                 vt = TypeManager.EnumToUnderlying (MemberType);
5460
5461                                         if (!((vt == TypeManager.bool_type) ||
5462                                               (vt == TypeManager.sbyte_type) ||
5463                                               (vt == TypeManager.byte_type) ||
5464                                               (vt == TypeManager.short_type) ||
5465                                               (vt == TypeManager.ushort_type) ||
5466                                               (vt == TypeManager.int32_type) ||
5467                                               (vt == TypeManager.uint32_type) ||    
5468                                               (vt == TypeManager.char_type) ||
5469                                               (vt == TypeManager.float_type) ||
5470                                               (!vt.IsValueType))){
5471                                                 Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'",
5472                                                         GetSignatureForError (), TypeManager.CSharpName (vt));
5473                                                 return false;
5474                                         }
5475                                 }
5476
5477                                 if ((ModFlags & Modifiers.READONLY) != 0){
5478                                         Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly",
5479                                                 GetSignatureForError ());
5480                                         return false;
5481                                 }
5482                         }
5483
5484                         FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
5485
5486                         if (Parent.PartialContainer.Kind == Kind.Struct && 
5487                             ((fa & FieldAttributes.Static) == 0) &&
5488                             MemberType == Parent.TypeBuilder &&
5489                             !TypeManager.IsBuiltinType (MemberType)){
5490                                 Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name + 
5491                                               "' causes a cycle in the structure layout");
5492                                 return false;
5493                         }
5494
5495                         try {
5496                                 FieldBuilder = Parent.TypeBuilder.DefineField (
5497                                         Name, MemberType, Modifiers.FieldAttr (ModFlags));
5498
5499                                 TypeManager.RegisterFieldBase (FieldBuilder, this);
5500                         }
5501                         catch (ArgumentException) {
5502                                 Report.Warning (-24, 1, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
5503                                 return false;
5504                         }
5505
5506                         return true;
5507                 }
5508
5509                 protected override bool VerifyClsCompliance ()
5510                 {
5511                         if (!base.VerifyClsCompliance ())
5512                                 return false;
5513
5514                         if ((ModFlags & Modifiers.VOLATILE) != 0) {
5515                                 Report.Warning (3026, 1, Location, "CLS-compliant field `{0}' cannot be volatile", GetSignatureForError ());
5516                         }
5517
5518                         return true;
5519                 }
5520         }
5521
5522         //
5523         // `set' and `get' accessors are represented with an Accessor.
5524         // 
5525         public class Accessor : IIteratorContainer {
5526                 //
5527                 // Null if the accessor is empty, or a Block if not
5528                 //
5529                 public const int AllowedModifiers = 
5530                         Modifiers.PUBLIC |
5531                         Modifiers.PROTECTED |
5532                         Modifiers.INTERNAL |
5533                         Modifiers.PRIVATE;
5534                 
5535                 public ToplevelBlock Block;
5536                 public Attributes Attributes;
5537                 public Location Location;
5538                 public int ModFlags;
5539                 public bool Yields;
5540                 
5541                 public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
5542                 {
5543                         Block = b;
5544                         Attributes = attrs;
5545                         Location = loc;
5546                         ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
5547                 }
5548
5549                 public void SetYields ()
5550                 {
5551                         Yields = true;
5552                 }
5553         }
5554
5555         // Ooouh Martin, templates are missing here.
5556         // When it will be possible move here a lot of child code and template method type.
5557         public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
5558                 protected MethodData method_data;
5559                 protected ToplevelBlock block;
5560                 protected ListDictionary declarative_security;
5561
5562                 // The accessor are created event if they are not wanted.
5563                 // But we need them because their names are reserved.
5564                 // Field says whether accessor will be emited or not
5565                 public readonly bool IsDummy;
5566
5567                 protected readonly string prefix;
5568
5569                 ReturnParameter return_attributes;
5570
5571                 public AbstractPropertyEventMethod (MemberBase member, string prefix)
5572                         : base (member.Parent, SetupName (prefix, member, member.Location), null)
5573                 {
5574                         this.prefix = prefix;
5575                         IsDummy = true;
5576                 }
5577
5578                 public AbstractPropertyEventMethod (MemberBase member, Accessor accessor,
5579                                                     string prefix)
5580                         : base (member.Parent, SetupName (prefix, member, accessor.Location),
5581                                 accessor.Attributes)
5582                 {
5583                         this.prefix = prefix;
5584                         this.block = accessor.Block;
5585                 }
5586
5587                 static MemberName SetupName (string prefix, MemberBase member, Location loc)
5588                 {
5589                         return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
5590                 }
5591
5592                 public void UpdateName (MemberBase member)
5593                 {
5594                         SetMemberName (SetupName (prefix, member, Location));
5595                 }
5596
5597                 #region IMethodData Members
5598
5599                 public ToplevelBlock Block {
5600                         get {
5601                                 return block;
5602                         }
5603
5604                         set {
5605                                 block = value;
5606                         }
5607                 }
5608
5609                 public CallingConventions CallingConventions {
5610                         get {
5611                                 return CallingConventions.Standard;
5612                         }
5613                 }
5614
5615                 public bool IsExcluded ()
5616                 {
5617                         return false;
5618                 }
5619
5620                 public MemberName MethodName {
5621                         get {
5622                                 return MemberName;
5623                         }
5624                 }
5625
5626                 public Type[] ParameterTypes { 
5627                         get {
5628                                 return ParameterInfo.Types;
5629                         }
5630                 }
5631
5632                 public abstract Parameters ParameterInfo { get ; }
5633                 public abstract Type ReturnType { get; }
5634                 public abstract EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
5635
5636                 #endregion
5637
5638                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5639                 {
5640                         if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
5641                                         a.Type == TypeManager.conditional_attribute_type) {
5642                                 Report.Error (1667, a.Location,
5643                                         "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
5644                                         TypeManager.CSharpName (a.Type), a.GetValidTargets ());
5645                                 return;
5646                         }
5647
5648                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
5649                                 if (declarative_security == null)
5650                                         declarative_security = new ListDictionary ();
5651                                 a.ExtractSecurityPermissionSet (declarative_security);
5652                                 return;
5653                         }
5654
5655                         if (a.Target == AttributeTargets.Method) {
5656                                 method_data.MethodBuilder.SetCustomAttribute (cb);
5657                                 return;
5658                         }
5659
5660                         if (a.Target == AttributeTargets.ReturnValue) {
5661                                 if (return_attributes == null)
5662                                         return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5663
5664                                 return_attributes.ApplyAttributeBuilder (a, cb);
5665                                 return;
5666                         }
5667
5668                         ApplyToExtraTarget (a, cb);
5669                 }
5670
5671                 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
5672                 {
5673                         System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
5674                 }
5675
5676                 public override bool Define()
5677                 {
5678                         throw new NotSupportedException ();
5679                 }
5680
5681                 public void Emit (DeclSpace parent)
5682                 {
5683                         EmitMethod (parent);
5684
5685                         if (OptAttributes != null)
5686                                 OptAttributes.Emit ();
5687
5688                         if (declarative_security != null) {
5689                                 foreach (DictionaryEntry de in declarative_security) {
5690                                         method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
5691                                 }
5692                         }
5693
5694                         block = null;
5695                 }
5696
5697                 protected virtual void EmitMethod (DeclSpace parent)
5698                 {
5699                         method_data.Emit (parent);
5700                 }
5701
5702                 public override bool IsClsComplianceRequired()
5703                 {
5704                         return false;
5705                 }
5706
5707                 public bool IsDuplicateImplementation (MethodCore method)
5708                 {
5709                         if (!MemberName.Equals (method.MemberName))
5710                                 return false;
5711
5712                         Type[] param_types = method.ParameterTypes;
5713
5714                         if (param_types.Length != ParameterTypes.Length)
5715                                 return false;
5716
5717                         for (int i = 0; i < param_types.Length; i++)
5718                                 if (param_types [i] != ParameterTypes [i])
5719                                         return false;
5720
5721                         Report.SymbolRelatedToPreviousError (method);
5722                         Report.Error (111, Location, TypeContainer.Error111, method.GetSignatureForError ());
5723                         return true;
5724                 }
5725
5726                 public override bool IsUsed
5727                 {
5728                         get {
5729                                 if (IsDummy)
5730                                         return false;
5731
5732                                 return base.IsUsed;
5733                         }
5734                 }
5735
5736                 public new Location Location { 
5737                         get {
5738                                 return base.Location;
5739                         }
5740                 }
5741
5742                 //
5743                 //   Represents header string for documentation comment.
5744                 //
5745                 public override string DocCommentHeader {
5746                         get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
5747                 }
5748
5749         }
5750
5751         //
5752         // Properties and Indexers both generate PropertyBuilders, we use this to share 
5753         // their common bits.
5754         //
5755         abstract public class PropertyBase : MethodCore {
5756
5757                 public class GetMethod : PropertyMethod
5758                 {
5759                         static string[] attribute_targets = new string [] { "method", "return" };
5760
5761                         public GetMethod (MethodCore method):
5762                                 base (method, "get_")
5763                         {
5764                         }
5765
5766                         public GetMethod (MethodCore method, Accessor accessor):
5767                                 base (method, accessor, "get_")
5768                         {
5769                         }
5770
5771                         public override MethodBuilder Define (DeclSpace parent)
5772                         {
5773                                 base.Define (parent);
5774                                 
5775                                 method_data = new MethodData (method, ModFlags, flags, this);
5776
5777                                 if (!method_data.Define (parent))
5778                                         return null;
5779
5780                                 return method_data.MethodBuilder;
5781                         }
5782
5783                         public override Type ReturnType {
5784                                 get {
5785                                         return method.MemberType;
5786                                 }
5787                         }
5788
5789                         public override Parameters ParameterInfo {
5790                                 get {
5791                                         return Parameters.EmptyReadOnlyParameters;
5792                                 }
5793                         }
5794
5795                         public override string[] ValidAttributeTargets {
5796                                 get {
5797                                         return attribute_targets;
5798                                 }
5799                         }
5800                 }
5801
5802                 public class SetMethod : PropertyMethod {
5803
5804                         static string[] attribute_targets = new string [] { "method", "param", "return" };
5805                         ImplicitParameter param_attr;
5806                         protected Parameters parameters;
5807
5808                         public SetMethod (MethodCore method):
5809                                 base (method, "set_")
5810                         {
5811                         }
5812
5813                         public SetMethod (MethodCore method, Accessor accessor):
5814                                 base (method, accessor, "set_")
5815                         {
5816                         }
5817
5818                         protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
5819                         {
5820                                 if (a.Target == AttributeTargets.Parameter) {
5821                                         if (param_attr == null)
5822                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5823
5824                                         param_attr.ApplyAttributeBuilder (a, cb);
5825                                         return;
5826                                 }
5827
5828                                 base.ApplyAttributeBuilder (a, cb);
5829                         }
5830
5831                         public override Parameters ParameterInfo {
5832                                 get {
5833                                         return parameters;
5834                                 }
5835                         }
5836
5837                         protected virtual void DefineParameters ()
5838                         {
5839                                 parameters = new Parameters (
5840                                         new Parameter[] { new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, Location) },
5841                                         new Type[] { method.MemberType });
5842                         }
5843
5844                         public override MethodBuilder Define (DeclSpace parent)
5845                         {
5846                                 DefineParameters ();
5847                                 if (IsDummy)
5848                                         return null;
5849
5850                                 base.Define (parent);
5851
5852                                 method_data = new MethodData (method, ModFlags, flags, this);
5853
5854                                 if (!method_data.Define (parent))
5855                                         return null;
5856
5857                                 return method_data.MethodBuilder;
5858                         }
5859
5860                         public override Type ReturnType {
5861                                 get {
5862                                         return TypeManager.void_type;
5863                                 }
5864                         }
5865
5866                         public override string[] ValidAttributeTargets {
5867                                 get {
5868                                         return attribute_targets;
5869                                 }
5870                         }
5871                 }
5872
5873                 static string[] attribute_targets = new string [] { "property" };
5874
5875                 public abstract class PropertyMethod : AbstractPropertyEventMethod
5876                 {
5877                         protected readonly MethodCore method;
5878                         protected MethodAttributes flags;
5879                         bool yields;
5880
5881                         public PropertyMethod (MethodCore method, string prefix)
5882                                 : base (method, prefix)
5883                         {
5884                                 this.method = method;
5885                         }
5886
5887                         public PropertyMethod (MethodCore method, Accessor accessor,
5888                                                string prefix)
5889                                 : base (method, accessor, prefix)
5890                         {
5891                                 this.method = method;
5892                                 this.ModFlags = accessor.ModFlags;
5893                                 yields = accessor.Yields;
5894
5895                                 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
5896                                         Report.FeatureIsNotStandardized (Location, "access modifiers on properties");
5897                                 }
5898                         }
5899
5900                         public override AttributeTargets AttributeTargets {
5901                                 get {
5902                                         return AttributeTargets.Method;
5903                                 }
5904                         }
5905
5906                         public override bool IsClsComplianceRequired()
5907                         {
5908                                 return method.IsClsComplianceRequired ();
5909                         }
5910
5911                         public virtual MethodBuilder Define (DeclSpace parent)
5912                         {
5913                                 if (!method.CheckAbstractAndExtern (block != null))
5914                                         return null;
5915
5916                                 TypeContainer container = parent.PartialContainer;
5917
5918                                 //
5919                                 // Check for custom access modifier
5920                                 //
5921                                 if (ModFlags == 0) {
5922                                         ModFlags = method.ModFlags;
5923                                         flags = method.flags;
5924                                 } else {
5925                                         if (container.Kind == Kind.Interface)
5926                                                 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
5927                                                         GetSignatureForError ());
5928
5929                                         if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
5930                                                 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
5931                                         }
5932
5933                                         CheckModifiers (ModFlags);
5934                                         ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
5935                                         ModFlags |= Modifiers.PROPERTY_CUSTOM;
5936                                         flags = Modifiers.MethodAttr (ModFlags);
5937                                         flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
5938                                 }
5939
5940                                 //
5941                                 // Setup iterator if we are one
5942                                 //
5943                                 if (yields) {
5944                                         Iterator iterator = new Iterator (this, Parent as TypeContainer, ModFlags);
5945                                         
5946                                         if (!iterator.DefineIterator ())
5947                                                 return null;
5948                                 }
5949
5950                                 return null;
5951                         }
5952
5953                         public bool HasCustomAccessModifier
5954                         {
5955                                 get {
5956                                         return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
5957                                 }
5958                         }
5959
5960                         public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
5961                         {
5962                                 return new EmitContext (method,
5963                                         ds, method.Parent, method.Location, ig, ReturnType,
5964                                         method.ModFlags, false);
5965                         }
5966
5967                         public override ObsoleteAttribute GetObsoleteAttribute ()
5968                         {
5969                                 return method.GetObsoleteAttribute ();
5970                         }
5971
5972                         public override string GetSignatureForError()
5973                         {
5974                                 return method.GetSignatureForError () + '.' + prefix.Substring (0, 3);
5975                         }
5976                         
5977                         void CheckModifiers (int modflags)
5978                         {
5979                                 int flags = 0;
5980                                 int mflags = method.ModFlags & Modifiers.Accessibility;
5981
5982                                 if ((mflags & Modifiers.PUBLIC) != 0) {
5983                                         flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
5984                                 }
5985                                 else if ((mflags & Modifiers.PROTECTED) != 0) {
5986                                         if ((mflags & Modifiers.INTERNAL) != 0)
5987                                                 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
5988
5989                                         flags |= Modifiers.PRIVATE;
5990                                 }
5991                                 else if ((mflags & Modifiers.INTERNAL) != 0)
5992                                         flags |= Modifiers.PRIVATE;
5993
5994                                 if ((mflags == modflags) || (modflags & (~flags)) != 0) {
5995                                         Report.Error (273, Location,
5996                                                 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
5997                                                 GetSignatureForError (), method.GetSignatureForError ());
5998                                 }
5999                         }
6000
6001                         public override bool MarkForDuplicationCheck ()
6002                         {
6003                                 caching_flags |= Flags.TestMethodDuplication;
6004                                 return true;
6005                         }
6006                 }
6007
6008                 public PropertyMethod Get, Set;
6009                 public PropertyBuilder PropertyBuilder;
6010                 public MethodBuilder GetBuilder, SetBuilder;
6011
6012                 protected EmitContext ec;
6013
6014                 public PropertyBase (DeclSpace parent, Expression type, int mod_flags,
6015                                      int allowed_mod, bool is_iface, MemberName name,
6016                                      Parameters parameters, Attributes attrs)
6017                         : base (parent, type, mod_flags, allowed_mod, is_iface, name,
6018                                 attrs, parameters)
6019                 {
6020                 }
6021
6022                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6023                 {
6024                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
6025                                 a.Error_InvalidSecurityParent ();
6026                                 return;
6027                         }
6028
6029                         PropertyBuilder.SetCustomAttribute (cb);
6030                 }
6031
6032                 public override AttributeTargets AttributeTargets {
6033                         get {
6034                                 return AttributeTargets.Property;
6035                         }
6036                 }
6037
6038                 public override bool Define ()
6039                 {
6040                         if (!DoDefine ())
6041                                 return false;
6042
6043                         if (!IsTypePermitted ())
6044                                 return false;
6045
6046                         return true;
6047                 }
6048
6049                 protected override bool DoDefine ()
6050                 {
6051                         if (!base.DoDefine ())
6052                                 return false;
6053
6054                         //
6055                         // Accessors modifiers check
6056                         //
6057                         if (Get.ModFlags != 0 && Set.ModFlags != 0) {
6058                                 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
6059                                                 GetSignatureForError ());
6060                                 return false;
6061                         }
6062
6063                         if ((Get.IsDummy || Set.IsDummy)
6064                                         && (Get.ModFlags != 0 || Set.ModFlags != 0) && (ModFlags & Modifiers.OVERRIDE) == 0) {
6065                                 Report.Error (276, Location, 
6066                                         "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
6067                                         GetSignatureForError ());
6068                                 return false;
6069                         }
6070
6071                         if (MemberType.IsAbstract && MemberType.IsSealed) {
6072                                 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
6073                                 return false;
6074                         }
6075
6076                         return true;
6077                 }
6078
6079                 protected override bool CheckForDuplications ()
6080                 {
6081                         ArrayList ar = Parent.PartialContainer.Indexers;
6082                         if (ar != null) {
6083                                 int arLen = ar.Count;
6084                                         
6085                                 for (int i = 0; i < arLen; i++) {
6086                                         Indexer m = (Indexer) ar [i];
6087                                         if (IsDuplicateImplementation (m))
6088                                                 return false;
6089                                 }
6090                         }
6091
6092                         ar = Parent.PartialContainer.Properties;
6093                         if (ar != null) {
6094                                 int arLen = ar.Count;
6095                                         
6096                                 for (int i = 0; i < arLen; i++) {
6097                                         Property m = (Property) ar [i];
6098                                         if (IsDuplicateImplementation (m))
6099                                                 return false;
6100                                 }
6101                         }
6102
6103                         return true;
6104                 }
6105
6106                 // TODO: rename to Resolve......
6107                 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
6108                 {
6109                         PropertyInfo base_property = Parent.PartialContainer.BaseCache.FindMemberToOverride (
6110                                 Parent.TypeBuilder, Name, ParameterTypes, true) as PropertyInfo;
6111   
6112                         if (base_property == null)
6113                                 return null;
6114   
6115                         base_ret_type = base_property.PropertyType;
6116                         MethodInfo get_accessor = base_property.GetGetMethod (true);
6117                         MethodInfo set_accessor = base_property.GetSetMethod (true);
6118                         MethodAttributes get_accessor_access, set_accessor_access;
6119
6120                         if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6121                                 if (Get != null && !Get.IsDummy && get_accessor == null) {
6122                                         Report.SymbolRelatedToPreviousError (base_property);
6123                                         Report.Error (545, Location, "`{0}.get': cannot override because `{1}' does not have an overridable get accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6124                                 }
6125
6126                                 if (Set != null && !Set.IsDummy && set_accessor == null) {
6127                                         Report.SymbolRelatedToPreviousError (base_property);
6128                                         Report.Error (546, Location, "`{0}.set': cannot override because `{1}' does not have an overridable set accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6129                                 }
6130                         }
6131                         
6132                         //
6133                         // Check base class accessors access
6134                         //
6135
6136                         // TODO: rewrite to reuse Get|Set.CheckAccessModifiers and share code there
6137                         get_accessor_access = set_accessor_access = 0;
6138                         if ((ModFlags & Modifiers.NEW) == 0) {
6139                                 if (get_accessor != null) {
6140                                         MethodAttributes get_flags = Modifiers.MethodAttr (Get.ModFlags != 0 ? Get.ModFlags : ModFlags);
6141                                         get_accessor_access = (get_accessor.Attributes & MethodAttributes.MemberAccessMask);
6142
6143                                         if (!Get.IsDummy && !CheckAccessModifiers (get_flags & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
6144                                                 Error_CannotChangeAccessModifiers (get_accessor, get_accessor_access,  ".get");
6145                                 }
6146
6147                                 if (set_accessor != null)  {
6148                                         MethodAttributes set_flags = Modifiers.MethodAttr (Set.ModFlags != 0 ? Set.ModFlags : ModFlags);
6149                                         set_accessor_access = (set_accessor.Attributes & MethodAttributes.MemberAccessMask);
6150
6151                                         if (!Set.IsDummy && !CheckAccessModifiers (set_flags & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6152                                                 Error_CannotChangeAccessModifiers (set_accessor, set_accessor_access, ".set");
6153                                 }
6154                         }
6155
6156                         //
6157                         // Get the less restrictive access
6158                         //
6159                         return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6160                 }
6161
6162                 public override void Emit ()
6163                 {
6164                         //
6165                         // The PropertyBuilder can be null for explicit implementations, in that
6166                         // case, we do not actually emit the ".property", so there is nowhere to
6167                         // put the attribute
6168                         //
6169                         if (PropertyBuilder != null && OptAttributes != null)
6170                                 OptAttributes.Emit ();
6171
6172                         if (!Get.IsDummy)
6173                                 Get.Emit (Parent);
6174
6175                         if (!Set.IsDummy)
6176                                 Set.Emit (Parent);
6177
6178                         base.Emit ();
6179                 }
6180
6181                 /// <summary>
6182                 /// Tests whether accessors are not in collision with some method (CS0111)
6183                 /// </summary>
6184                 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6185                 {
6186                         return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6187                 }
6188
6189                 public override bool IsUsed
6190                 {
6191                         get {
6192                                 if (IsExplicitImpl)
6193                                         return true;
6194
6195                                 return Get.IsUsed | Set.IsUsed;
6196                         }
6197                 }
6198
6199                 protected override void SetMemberName (MemberName new_name)
6200                 {
6201                         base.SetMemberName (new_name);
6202
6203                         Get.UpdateName (this);
6204                         Set.UpdateName (this);
6205                 }
6206
6207                 public override string[] ValidAttributeTargets {
6208                         get {
6209                                 return attribute_targets;
6210                         }
6211                 }
6212
6213                 //
6214                 //   Represents header string for documentation comment.
6215                 //
6216                 public override string DocCommentHeader {
6217                         get { return "P:"; }
6218                 }
6219         }
6220                         
6221         public class Property : PropertyBase {
6222                 const int AllowedModifiers =
6223                         Modifiers.NEW |
6224                         Modifiers.PUBLIC |
6225                         Modifiers.PROTECTED |
6226                         Modifiers.INTERNAL |
6227                         Modifiers.PRIVATE |
6228                         Modifiers.STATIC |
6229                         Modifiers.SEALED |
6230                         Modifiers.OVERRIDE |
6231                         Modifiers.ABSTRACT |
6232                         Modifiers.UNSAFE |
6233                         Modifiers.EXTERN |
6234                         Modifiers.METHOD_YIELDS |
6235                         Modifiers.VIRTUAL;
6236
6237                 const int AllowedInterfaceModifiers =
6238                         Modifiers.NEW;
6239
6240                 public Property (DeclSpace parent, Expression type, int mod, bool is_iface,
6241                                  MemberName name, Attributes attrs, Accessor get_block,
6242                                  Accessor set_block)
6243                         : base (parent, type, mod,
6244                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6245                                 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs)
6246                 {
6247                         if (get_block == null)
6248                                 Get = new GetMethod (this);
6249                         else
6250                                 Get = new GetMethod (this, get_block);
6251
6252                         if (set_block == null)
6253                                 Set = new SetMethod (this);
6254                         else
6255                                 Set = new SetMethod (this, set_block);
6256                 }
6257
6258                 public override bool Define ()
6259                 {
6260                         if (!base.Define ())
6261                                 return false;
6262
6263                         if (!CheckBase ())
6264                                 return false;
6265
6266                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6267
6268                         if (!Get.IsDummy) {
6269                                 GetBuilder = Get.Define (Parent);
6270                                 if (GetBuilder == null)
6271                                         return false;
6272                         }
6273
6274                         SetBuilder = Set.Define (Parent);
6275                         if (!Set.IsDummy) {
6276                                 if (SetBuilder == null)
6277                                         return false;
6278                         }
6279
6280                         // FIXME - PropertyAttributes.HasDefault ?
6281
6282                         PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6283                              Name, PropertyAttributes.None, MemberType, null);
6284                         
6285                         if (!Get.IsDummy)
6286                                 PropertyBuilder.SetGetMethod (GetBuilder);
6287                                 
6288                         if (!Set.IsDummy)
6289                                 PropertyBuilder.SetSetMethod (SetBuilder);
6290                         
6291                         TypeManager.RegisterProperty (PropertyBuilder, this);
6292                         return true;
6293                 }
6294         }
6295
6296         /// </summary>
6297         ///  Gigantic workaround  for lameness in SRE follows :
6298         ///  This class derives from EventInfo and attempts to basically
6299         ///  wrap around the EventBuilder so that FindMembers can quickly
6300         ///  return this in it search for members
6301         /// </summary>
6302         public class MyEventBuilder : EventInfo {
6303                 
6304                 //
6305                 // We use this to "point" to our Builder which is
6306                 // not really a MemberInfo
6307                 //
6308                 EventBuilder MyBuilder;
6309                 
6310                 //
6311                 // We "catch" and wrap these methods
6312                 //
6313                 MethodInfo raise, remove, add;
6314
6315                 EventAttributes attributes;
6316                 Type declaring_type, reflected_type, event_type;
6317                 string name;
6318
6319                 Event my_event;
6320
6321                 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6322                 {
6323                         MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6324
6325                         // And now store the values in our own fields.
6326                         
6327                         declaring_type = type_builder;
6328
6329                         reflected_type = type_builder;
6330                         
6331                         attributes = event_attr;
6332                         this.name = name;
6333                         my_event = ev;
6334                         this.event_type = event_type;
6335                 }
6336                 
6337                 //
6338                 // Methods that you have to override.  Note that you only need 
6339                 // to "implement" the variants that take the argument (those are
6340                 // the "abstract" methods, the others (GetAddMethod()) are 
6341                 // regular.
6342                 //
6343                 public override MethodInfo GetAddMethod (bool nonPublic)
6344                 {
6345                         return add;
6346                 }
6347                 
6348                 public override MethodInfo GetRemoveMethod (bool nonPublic)
6349                 {
6350                         return remove;
6351                 }
6352                 
6353                 public override MethodInfo GetRaiseMethod (bool nonPublic)
6354                 {
6355                         return raise;
6356                 }
6357                 
6358                 //
6359                 // These methods make "MyEventInfo" look like a Builder
6360                 //
6361                 public void SetRaiseMethod (MethodBuilder raiseMethod)
6362                 {
6363                         raise = raiseMethod;
6364                         MyBuilder.SetRaiseMethod (raiseMethod);
6365                 }
6366
6367                 public void SetRemoveOnMethod (MethodBuilder removeMethod)
6368                 {
6369                         remove = removeMethod;
6370                         MyBuilder.SetRemoveOnMethod (removeMethod);
6371                 }
6372
6373                 public void SetAddOnMethod (MethodBuilder addMethod)
6374                 {
6375                         add = addMethod;
6376                         MyBuilder.SetAddOnMethod (addMethod);
6377                 }
6378
6379                 public void SetCustomAttribute (CustomAttributeBuilder cb)
6380                 {
6381                         MyBuilder.SetCustomAttribute (cb);
6382                 }
6383                 
6384                 public override object [] GetCustomAttributes (bool inherit)
6385                 {
6386                         // FIXME : There's nothing which can be seemingly done here because
6387                         // we have no way of getting at the custom attribute objects of the
6388                         // EventBuilder !
6389                         return null;
6390                 }
6391
6392                 public override object [] GetCustomAttributes (Type t, bool inherit)
6393                 {
6394                         // FIXME : Same here !
6395                         return null;
6396                 }
6397
6398                 public override bool IsDefined (Type t, bool b)
6399                 {
6400                         return true;
6401                 }
6402
6403                 public override EventAttributes Attributes {
6404                         get {
6405                                 return attributes;
6406                         }
6407                 }
6408
6409                 public override string Name {
6410                         get {
6411                                 return name;
6412                         }
6413                 }
6414
6415                 public override Type DeclaringType {
6416                         get {
6417                                 return declaring_type;
6418                         }
6419                 }
6420
6421                 public override Type ReflectedType {
6422                         get {
6423                                 return reflected_type;
6424                         }
6425                 }
6426
6427                 public Type EventType {
6428                         get {
6429                                 return event_type;
6430                         }
6431                 }
6432                 
6433                 public void SetUsed ()
6434                 {
6435                         if (my_event != null) {
6436                                 my_event.SetAssigned ();
6437                                 my_event.SetMemberIsUsed ();
6438                         }
6439                 }
6440         }
6441         
6442         /// <summary>
6443         /// For case when event is declared like property (with add and remove accessors).
6444         /// </summary>
6445         public class EventProperty: Event {
6446
6447                 static string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
6448
6449                 public EventProperty (DeclSpace parent, Expression type, int mod_flags,
6450                                       bool is_iface, MemberName name,
6451                                       Attributes attrs, Accessor add, Accessor remove)
6452                         : base (parent, type, mod_flags, is_iface, name, attrs)
6453                 {
6454                         Add = new AddDelegateMethod (this, add);
6455                         Remove = new RemoveDelegateMethod (this, remove);
6456
6457                         // For this event syntax we don't report error CS0067
6458                         // because it is hard to do it.
6459                         SetAssigned ();
6460                 }
6461
6462                 public override string[] ValidAttributeTargets {
6463                         get {
6464                                 return attribute_targets;
6465                         }
6466                 }
6467         }
6468
6469         /// <summary>
6470         /// Event is declared like field.
6471         /// </summary>
6472         public class EventField : Event {
6473
6474                 static string[] attribute_targets = new string [] { "event", "field", "method" };
6475                 static string[] attribute_targets_interface = new string[] { "event", "method" };
6476
6477                 public EventField (DeclSpace parent, Expression type, int mod_flags,
6478                                    bool is_iface, MemberName name,
6479                                    Attributes attrs)
6480                         : base (parent, type, mod_flags, is_iface, name, attrs)
6481                 {
6482                         Add = new AddDelegateMethod (this);
6483                         Remove = new RemoveDelegateMethod (this);
6484                 }
6485
6486                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6487                 {
6488                         if (a.Target == AttributeTargets.Field) {
6489                                 FieldBuilder.SetCustomAttribute (cb);
6490                                 return;
6491                         }
6492
6493                         if (a.Target == AttributeTargets.Method) {
6494                                 Add.ApplyAttributeBuilder (a, cb);
6495                                 Remove.ApplyAttributeBuilder (a, cb);
6496                                 return;
6497                         }
6498
6499                         base.ApplyAttributeBuilder (a, cb);
6500                 }
6501
6502                 public override bool Define()
6503                 {
6504                         if (!base.Define ())
6505                                 return false;
6506
6507                         if (initializer != null) {
6508                                 if (((ModFlags & Modifiers.ABSTRACT) != 0)) {
6509                                         Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
6510                                                 GetSignatureForError ());
6511                                         return false;
6512                                 }
6513                         }
6514
6515                         return true;
6516                 }
6517
6518                 public override string[] ValidAttributeTargets {
6519                         get {
6520                                 return IsInterface ? attribute_targets_interface : attribute_targets;
6521                         }
6522                 }
6523         }
6524
6525         public abstract class Event : FieldBase {
6526
6527                 protected sealed class AddDelegateMethod: DelegateMethod
6528                 {
6529
6530                         public AddDelegateMethod (Event method):
6531                                 base (method, "add_")
6532                         {
6533                         }
6534
6535                         public AddDelegateMethod (Event method, Accessor accessor):
6536                                 base (method, accessor, "add_")
6537                         {
6538                         }
6539
6540                         protected override MethodInfo DelegateMethodInfo {
6541                                 get {
6542                                         return TypeManager.delegate_combine_delegate_delegate;
6543                                 }
6544                         }
6545
6546                 }
6547
6548                 protected sealed class RemoveDelegateMethod: DelegateMethod
6549                 {
6550                         public RemoveDelegateMethod (Event method):
6551                                 base (method, "remove_")
6552                         {
6553                         }
6554
6555                         public RemoveDelegateMethod (Event method, Accessor accessor):
6556                                 base (method, accessor, "remove_")
6557                         {
6558                         }
6559
6560                         protected override MethodInfo DelegateMethodInfo {
6561                                 get {
6562                                         return TypeManager.delegate_remove_delegate_delegate;
6563                                 }
6564                         }
6565
6566                 }
6567
6568                 public abstract class DelegateMethod : AbstractPropertyEventMethod
6569                 {
6570                         protected readonly Event method;
6571                         ImplicitParameter param_attr;
6572
6573                         static string[] attribute_targets = new string [] { "method", "param", "return" };
6574
6575                         public DelegateMethod (Event method, string prefix)
6576                                 : base (method, prefix)
6577                         {
6578                                 this.method = method;
6579                         }
6580
6581                         public DelegateMethod (Event method, Accessor accessor, string prefix)
6582                                 : base (method, accessor, prefix)
6583                         {
6584                                 this.method = method;
6585                         }
6586
6587                         protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6588                         {
6589                                 if (a.Target == AttributeTargets.Parameter) {
6590                                         if (param_attr == null)
6591                                                 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6592
6593                                         param_attr.ApplyAttributeBuilder (a, cb);
6594                                         return;
6595                                 }
6596
6597                                 base.ApplyAttributeBuilder (a, cb);
6598                         }
6599
6600                         public override AttributeTargets AttributeTargets {
6601                                 get {
6602                                         return AttributeTargets.Method;
6603                                 }
6604                         }
6605
6606                         public override bool IsClsComplianceRequired ()
6607                         {
6608                                 return method.IsClsComplianceRequired ();
6609                         }
6610
6611                         public MethodBuilder Define (DeclSpace parent)
6612                         {
6613                                 method_data = new MethodData (method, method.ModFlags,
6614                                         method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
6615
6616                                 if (!method_data.Define (parent))
6617                                         return null;
6618
6619                                 MethodBuilder mb = method_data.MethodBuilder;
6620                                 ParameterInfo.ApplyAttributes (mb);
6621                                 return mb;
6622                         }
6623
6624
6625                         protected override void EmitMethod (DeclSpace parent)
6626                         {
6627                                 if (block != null) {
6628                                         base.EmitMethod (parent);
6629                                         return;
6630                                 }
6631
6632                                 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
6633                                         return;
6634
6635                                 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
6636                                 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
6637
6638                                 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
6639                                 if ((method.ModFlags & Modifiers.STATIC) != 0) {
6640                                         ig.Emit (OpCodes.Ldsfld, field_info);
6641                                         ig.Emit (OpCodes.Ldarg_0);
6642                                         ig.Emit (OpCodes.Call, DelegateMethodInfo);
6643                                         ig.Emit (OpCodes.Castclass, method.MemberType);
6644                                         ig.Emit (OpCodes.Stsfld, field_info);
6645                                 } else {
6646                                         ig.Emit (OpCodes.Ldarg_0);
6647                                         ig.Emit (OpCodes.Ldarg_0);
6648                                         ig.Emit (OpCodes.Ldfld, field_info);
6649                                         ig.Emit (OpCodes.Ldarg_1);
6650                                         ig.Emit (OpCodes.Call, DelegateMethodInfo);
6651                                         ig.Emit (OpCodes.Castclass, method.MemberType);
6652                                         ig.Emit (OpCodes.Stfld, field_info);
6653                                 }
6654                                 ig.Emit (OpCodes.Ret);
6655                         }
6656
6657                         protected abstract MethodInfo DelegateMethodInfo { get; }
6658
6659                         public override Type ReturnType {
6660                                 get {
6661                                         return TypeManager.void_type;
6662                                 }
6663                         }
6664
6665                         public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
6666                         {
6667                                 return new EmitContext (method,
6668                                         ds, method.Parent, Location, ig, ReturnType,
6669                                         method.ModFlags, false);
6670                         }
6671
6672                         public override ObsoleteAttribute GetObsoleteAttribute ()
6673                         {
6674                                 return method.GetObsoleteAttribute ();
6675                         }
6676
6677                         public override string[] ValidAttributeTargets {
6678                                 get {
6679                                         return attribute_targets;
6680                                 }
6681                         }
6682
6683                         public override Parameters ParameterInfo {
6684                                 get {
6685                                         return method.parameters;
6686                                 }
6687                         }
6688
6689                 }
6690
6691
6692                 const int AllowedModifiers =
6693                         Modifiers.NEW |
6694                         Modifiers.PUBLIC |
6695                         Modifiers.PROTECTED |
6696                         Modifiers.INTERNAL |
6697                         Modifiers.PRIVATE |
6698                         Modifiers.STATIC |
6699                         Modifiers.VIRTUAL |
6700                         Modifiers.SEALED |
6701                         Modifiers.OVERRIDE |
6702                         Modifiers.UNSAFE |
6703                         Modifiers.ABSTRACT;
6704
6705                 const int AllowedInterfaceModifiers =
6706                         Modifiers.NEW;
6707
6708                 public DelegateMethod Add, Remove;
6709                 public MyEventBuilder     EventBuilder;
6710                 public MethodBuilder AddBuilder, RemoveBuilder;
6711                 Parameters parameters;
6712
6713                 protected Event (DeclSpace parent, Expression type, int mod_flags,
6714                               bool is_iface, MemberName name, Attributes attrs)
6715                         : base (parent, type, mod_flags,
6716                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6717                                 name, attrs)
6718                 {
6719                         IsInterface = is_iface;
6720                 }
6721
6722                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6723                 {
6724                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
6725                                 a.Error_InvalidSecurityParent ();
6726                                 return;
6727                         }
6728                         
6729                         EventBuilder.SetCustomAttribute (cb);
6730                 }
6731
6732                 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6733                 {
6734                         return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
6735                 }
6736
6737                 public override AttributeTargets AttributeTargets {
6738                         get {
6739                                 return AttributeTargets.Event;
6740                         }
6741                 }
6742
6743                 public override bool Define ()
6744                 {
6745                         EventAttributes e_attr;
6746                         e_attr = EventAttributes.None;
6747
6748                         if (!DoDefine ())
6749                                 return false;
6750
6751                         if (!TypeManager.IsDelegateType (MemberType)) {
6752                                 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
6753                                 return false;
6754                         }
6755
6756                         parameters = new Parameters (
6757                                 new Parameter[] { new Parameter (MemberType, "value", Parameter.Modifier.NONE, null, Location) },
6758                                 new Type[] { MemberType } );
6759
6760                         if (!CheckBase ())
6761                                 return false;
6762
6763                         //
6764                         // Now define the accessors
6765                         //
6766
6767                         AddBuilder = Add.Define (Parent);
6768                         if (AddBuilder == null)
6769                                 return false;
6770
6771                         RemoveBuilder = Remove.Define (Parent);
6772                         if (RemoveBuilder == null)
6773                                 return false;
6774
6775                         EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, e_attr, MemberType);
6776                         
6777                         if (Add.Block == null && Remove.Block == null && !IsInterface) {
6778                                 FieldBuilder = Parent.TypeBuilder.DefineField (
6779                                         Name, MemberType,
6780                                         FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
6781                                 TypeManager.RegisterPrivateFieldOfEvent (
6782                                         (EventInfo) EventBuilder, FieldBuilder);
6783                                 TypeManager.RegisterFieldBase (FieldBuilder, this);
6784                         }
6785                         
6786                         EventBuilder.SetAddOnMethod (AddBuilder);
6787                         EventBuilder.SetRemoveOnMethod (RemoveBuilder);
6788
6789                         TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder);
6790                         return true;
6791                 }
6792
6793                 protected override bool CheckBase ()
6794                 {
6795                         if (!base.CheckBase ())
6796                                 return false;
6797  
6798                         if (conflict_symbol != null && (ModFlags & Modifiers.NEW) == 0) {
6799                                 if (!(conflict_symbol is EventInfo)) {
6800                                         Report.SymbolRelatedToPreviousError (conflict_symbol);
6801                                         Report.Error (72, Location, "Event `{0}' can override only event", GetSignatureForError ());
6802                                         return false;
6803                                 }
6804                         }
6805  
6806                         return true;
6807                 }
6808
6809                 public override void Emit ()
6810                 {
6811                         if (OptAttributes != null) {
6812                                 OptAttributes.Emit ();
6813                         }
6814
6815                         Add.Emit (Parent);
6816                         Remove.Emit (Parent);
6817
6818                         base.Emit ();
6819                 }
6820
6821                 public override string GetSignatureForError ()
6822                 {
6823                         return base.GetSignatureForError ();
6824                 }
6825
6826                 //
6827                 //   Represents header string for documentation comment.
6828                 //
6829                 public override string DocCommentHeader {
6830                         get { return "E:"; }
6831                 }
6832         }
6833
6834
6835         public class Indexer : PropertyBase {
6836
6837                 class GetIndexerMethod : GetMethod
6838                 {
6839                         public GetIndexerMethod (MethodCore method):
6840                                 base (method)
6841                         {
6842                         }
6843
6844                         public GetIndexerMethod (MethodCore method, Accessor accessor):
6845                                 base (method, accessor)
6846                         {
6847                         }
6848
6849                         public override Parameters ParameterInfo {
6850                                 get {
6851                                         return method.ParameterInfo;
6852                                 }
6853                         }
6854                 }
6855
6856                 class SetIndexerMethod: SetMethod
6857                 {
6858                         public SetIndexerMethod (MethodCore method):
6859                                 base (method)
6860                         {
6861                         }
6862
6863                         public SetIndexerMethod (MethodCore method, Accessor accessor):
6864                                 base (method, accessor)
6865                         {
6866                         }
6867
6868                         protected override void DefineParameters ()
6869                         {
6870                                 parameters = Parameters.MergeGenerated (method.Parameters,
6871                                         new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, method.Location));
6872                         }
6873                 }
6874
6875                 const int AllowedModifiers =
6876                         Modifiers.NEW |
6877                         Modifiers.PUBLIC |
6878                         Modifiers.PROTECTED |
6879                         Modifiers.INTERNAL |
6880                         Modifiers.PRIVATE |
6881                         Modifiers.VIRTUAL |
6882                         Modifiers.SEALED |
6883                         Modifiers.OVERRIDE |
6884                         Modifiers.UNSAFE |
6885                         Modifiers.EXTERN |
6886                         Modifiers.ABSTRACT;
6887
6888                 const int AllowedInterfaceModifiers =
6889                         Modifiers.NEW;
6890
6891
6892                 public Indexer (DeclSpace parent, Expression type, MemberName name, int mod,
6893                                 bool is_iface, Parameters parameters, Attributes attrs,
6894                                 Accessor get_block, Accessor set_block)
6895                         : base (parent, type, mod,
6896                                 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6897                                 is_iface, name, parameters, attrs)
6898                 {
6899                         if (get_block == null)
6900                                 Get = new GetIndexerMethod (this);
6901                         else
6902                                 Get = new GetIndexerMethod (this, get_block);
6903
6904                         if (set_block == null)
6905                                 Set = new SetIndexerMethod (this);
6906                         else
6907                                 Set = new SetIndexerMethod (this, set_block);
6908                 }
6909                        
6910                 public override bool Define ()
6911                 {
6912                         if (!base.Define ())
6913                                 return false;
6914
6915                         if (MemberType == TypeManager.void_type) {
6916                                 Report.Error (620, Location, "Indexers cannot have void type");
6917                                 return false;
6918                         }
6919
6920                         if (OptAttributes != null) {
6921                                 Attribute indexer_attr = OptAttributes.Search (TypeManager.indexer_name_type);
6922                                 if (indexer_attr != null) {
6923                                         // Remove the attribute from the list because it is not emitted
6924                                         OptAttributes.Attrs.Remove (indexer_attr);
6925
6926                                         string name = indexer_attr.GetIndexerAttributeValue ();
6927                                         if (name == null)
6928                                                 return false;
6929
6930                                         ShortName = name;
6931
6932                                         if (IsExplicitImpl) {
6933                                                 Report.Error (415, indexer_attr.Location,
6934                                                               "The `IndexerName' attribute is valid only on an " +
6935                                                               "indexer that is not an explicit interface member declaration");
6936                                                 return false;
6937                                         }
6938
6939                                         if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6940                                                 Report.Error (609, indexer_attr.Location,
6941                                                               "Cannot set the `IndexerName' attribute on an indexer marked override");
6942                                                 return false;
6943                                         }
6944                                 }
6945                         }
6946
6947                         if (InterfaceType != null) {
6948                                 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
6949                                 if (base_IndexerName != Name)
6950                                         ShortName = base_IndexerName;
6951                         }
6952
6953                         if (!Parent.PartialContainer.AddMember (this) ||
6954                                 !Parent.PartialContainer.AddMember (Get) || !Parent.PartialContainer.AddMember (Set))
6955                                 return false;
6956
6957                         if (!CheckBase ())
6958                                 return false;
6959
6960                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6961                         if (!Get.IsDummy){
6962                                 GetBuilder = Get.Define (Parent);
6963                                 if (GetBuilder == null)
6964                                         return false;
6965                         }
6966                         
6967                         SetBuilder = Set.Define (Parent);
6968                         if (!Set.IsDummy){
6969                                 if (SetBuilder == null)
6970                                         return false;
6971                         }
6972
6973                         //
6974                         // Now name the parameters
6975                         //
6976                         Parameter [] p = Parameters.FixedParameters;
6977                         if (p != null) {
6978                                 // TODO: should be done in parser and it needs to do cycle
6979                                 if ((p [0].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
6980                                         Report.Error (631, Location, "ref and out are not valid in this context");
6981                                         return false;
6982                                 }
6983                         }
6984
6985                         PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6986                                 Name, PropertyAttributes.None, MemberType, ParameterTypes);
6987                         
6988                         if (!Get.IsDummy)
6989                                 PropertyBuilder.SetGetMethod (GetBuilder);
6990
6991                         if (!Set.IsDummy)
6992                                 PropertyBuilder.SetSetMethod (SetBuilder);
6993                                 
6994                         TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, ParameterTypes);
6995
6996                         return true;
6997                 }
6998
6999                 public override string GetSignatureForError ()
7000                 {
7001                         StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
7002                         if (MemberName.Left != null) {
7003                                 sb.Append ('.');
7004                                 sb.Append (MemberName.Left);
7005                         }
7006
7007                         sb.Append (".this");
7008                         sb.Append (Parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
7009                         return sb.ToString ();
7010                 }
7011
7012                 public override bool MarkForDuplicationCheck ()
7013                 {
7014                         caching_flags |= Flags.TestMethodDuplication;
7015                         return true;
7016                 }
7017         }
7018
7019         public class Operator : MethodOrOperator, IIteratorContainer {
7020
7021                 const int AllowedModifiers =
7022                         Modifiers.PUBLIC |
7023                         Modifiers.UNSAFE |
7024                         Modifiers.EXTERN |
7025                         Modifiers.STATIC;
7026
7027                 public enum OpType : byte {
7028
7029                         // Unary operators
7030                         LogicalNot,
7031                         OnesComplement,
7032                         Increment,
7033                         Decrement,
7034                         True,
7035                         False,
7036
7037                         // Unary and Binary operators
7038                         Addition,
7039                         Subtraction,
7040
7041                         UnaryPlus,
7042                         UnaryNegation,
7043                         
7044                         // Binary operators
7045                         Multiply,
7046                         Division,
7047                         Modulus,
7048                         BitwiseAnd,
7049                         BitwiseOr,
7050                         ExclusiveOr,
7051                         LeftShift,
7052                         RightShift,
7053                         Equality,
7054                         Inequality,
7055                         GreaterThan,
7056                         LessThan,
7057                         GreaterThanOrEqual,
7058                         LessThanOrEqual,
7059
7060                         // Implicit and Explicit
7061                         Implicit,
7062                         Explicit,
7063
7064                         // Just because of enum
7065                         TOP
7066                 };
7067
7068                 public readonly OpType OperatorType;
7069                 
7070                 public Operator (DeclSpace parent, OpType type, Expression ret_type,
7071                                  int mod_flags, Parameters parameters,
7072                                  ToplevelBlock block, Attributes attrs, Location loc)
7073                         : base (parent, ret_type, mod_flags, AllowedModifiers, false,
7074                                 new MemberName ("op_" + type, loc), attrs, parameters)
7075                 {
7076                         OperatorType = type;
7077                         Block = block;
7078                 }
7079
7080                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) 
7081                 {
7082                         if (a.Type == TypeManager.conditional_attribute_type) {
7083                                 Error_ConditionalAttributeIsNotValid ();
7084                                 return;
7085                         }
7086
7087                         base.ApplyAttributeBuilder (a, cb);
7088                 }
7089                 
7090                 protected override bool CheckForDuplications ()
7091                 {
7092                         ArrayList ar = Parent.PartialContainer.Operators;
7093                         if (ar != null) {
7094                                 int arLen = ar.Count;
7095                                         
7096                                 for (int i = 0; i < arLen; i++) {
7097                                         Operator o = (Operator) ar [i];
7098                                         if (IsDuplicateImplementation (o))
7099                                                 return false;
7100                                 }
7101                         }
7102
7103                         ar = Parent.PartialContainer.Methods;
7104                         if (ar != null) {
7105                                 int arLen = ar.Count;
7106                                         
7107                                 for (int i = 0; i < arLen; i++) {
7108                                         Method m = (Method) ar [i];
7109                                         if (IsDuplicateImplementation (m))
7110                                                 return false;
7111                                 }
7112                         }
7113
7114                         return true;
7115                 }
7116
7117                 public override bool Define ()
7118                 {
7119                         const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
7120                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
7121                                 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
7122                                 return false;
7123                         }
7124
7125                         if (!base.Define ())
7126                                 return false;
7127
7128                         if (MemberType == TypeManager.void_type) {
7129                                 Report.Error (590, Location, "User-defined operators cannot return void");
7130                                 return false;
7131                         }
7132
7133                         Type declaring_type = MethodBuilder.DeclaringType;
7134                         Type return_type = MemberType;
7135                         Type first_arg_type = ParameterTypes [0];
7136
7137                         // Rules for conversion operators
7138                         
7139                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7140                                 if (first_arg_type == return_type && first_arg_type == declaring_type){
7141                                         Report.Error (555, Location,
7142                                                 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
7143                                         return false;
7144                                 }
7145                                 
7146                                 if (first_arg_type != declaring_type && return_type != declaring_type){
7147                                         Report.Error (
7148                                                 556, Location, 
7149                                                 "User-defined conversion must convert to or from the " +
7150                                                 "enclosing type");
7151                                         return false;
7152                                 }
7153
7154                                 if (first_arg_type.IsInterface || return_type.IsInterface){
7155                                         Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
7156                                                 GetSignatureForError ());
7157                                         return false;
7158                                 }
7159                                 
7160                                 if (first_arg_type.IsSubclassOf (return_type) || return_type.IsSubclassOf (first_arg_type)) {
7161                                         if (declaring_type.IsSubclassOf (return_type) || declaring_type.IsSubclassOf (first_arg_type)) {
7162                                                 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from base class",
7163                                                         GetSignatureForError ());
7164                                                 return false;
7165                                         }
7166                                         Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from derived class",
7167                                                 GetSignatureForError ());
7168                                         return false;
7169                                 }
7170                         } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
7171                                 if (first_arg_type != declaring_type || ParameterTypes [1] != TypeManager.int32_type) {
7172                                         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");
7173                                         return false;
7174                                 }
7175                         } else if (Parameters.Count == 1) {
7176                                 // Checks for Unary operators
7177
7178                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7179                                         if (return_type != declaring_type && !return_type.IsSubclassOf (declaring_type)) {
7180                                                 Report.Error (448, Location,
7181                                                         "The return type for ++ or -- operator must be the containing type or derived from the containing type");
7182                                                 return false;
7183                                         }
7184                                         if (first_arg_type != declaring_type) {
7185                                                 Report.Error (
7186                                                         559, Location, "The parameter type for ++ or -- operator must be the containing type");
7187                                                 return false;
7188                                         }
7189                                 }
7190                                 
7191                                 if (first_arg_type != declaring_type){
7192                                         Report.Error (
7193                                                 562, Location,
7194                                                 "The parameter of a unary operator must be the " +
7195                                                 "containing type");
7196                                         return false;
7197                                 }
7198                                 
7199                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7200                                         if (return_type != TypeManager.bool_type){
7201                                                 Report.Error (
7202                                                         215, Location,
7203                                                         "The return type of operator True or False " +
7204                                                         "must be bool");
7205                                                 return false;
7206                                         }
7207                                 }
7208                                 
7209                         } else {
7210                                 // Checks for Binary operators
7211                                 
7212                                 if (first_arg_type != declaring_type &&
7213                                     ParameterTypes [1] != declaring_type){
7214                                         Report.Error (
7215                                                 563, Location,
7216                                                 "One of the parameters of a binary operator must " +
7217                                                 "be the containing type");
7218                                         return false;
7219                                 }
7220                         }
7221
7222                         return true;
7223                 }
7224
7225                 protected override bool DoDefine ()
7226                 {
7227                         if (!base.DoDefine ())
7228                                 return false;
7229
7230                         flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
7231                         return true;
7232                 }
7233                 
7234                 public override void Emit ()
7235                 {
7236                         base.Emit ();
7237
7238                         Parameters.ApplyAttributes (MethodBuilder);
7239
7240                         //
7241                         // abstract or extern methods have no bodies
7242                         //
7243                         if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
7244                                 return;
7245                         
7246                         EmitContext ec;
7247                         if ((flags & MethodAttributes.PinvokeImpl) == 0)
7248                                 ec = CreateEmitContext (Parent, MethodBuilder.GetILGenerator ());
7249                         else
7250                                 ec = CreateEmitContext (Parent, null);
7251                         
7252                         SourceMethod source = SourceMethod.Create (Parent, MethodBuilder, Block);
7253                         ec.EmitTopBlock (this, Block);
7254
7255                         if (source != null)
7256                                 source.CloseMethod ();
7257
7258                         Block = null;
7259                 }
7260
7261                 // Operator cannot be override
7262                 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
7263                 {
7264                         return null;
7265                 }
7266
7267                 public static string GetName (OpType ot)
7268                 {
7269                         switch (ot){
7270                         case OpType.LogicalNot:
7271                                 return "!";
7272                         case OpType.OnesComplement:
7273                                 return "~";
7274                         case OpType.Increment:
7275                                 return "++";
7276                         case OpType.Decrement:
7277                                 return "--";
7278                         case OpType.True:
7279                                 return "true";
7280                         case OpType.False:
7281                                 return "false";
7282                         case OpType.Addition:
7283                                 return "+";
7284                         case OpType.Subtraction:
7285                                 return "-";
7286                         case OpType.UnaryPlus:
7287                                 return "+";
7288                         case OpType.UnaryNegation:
7289                                 return "-";
7290                         case OpType.Multiply:
7291                                 return "*";
7292                         case OpType.Division:
7293                                 return "/";
7294                         case OpType.Modulus:
7295                                 return "%";
7296                         case OpType.BitwiseAnd:
7297                                 return "&";
7298                         case OpType.BitwiseOr:
7299                                 return "|";
7300                         case OpType.ExclusiveOr:
7301                                 return "^";
7302                         case OpType.LeftShift:
7303                                 return "<<";
7304                         case OpType.RightShift:
7305                                 return ">>";
7306                         case OpType.Equality:
7307                                 return "==";
7308                         case OpType.Inequality:
7309                                 return "!=";
7310                         case OpType.GreaterThan:
7311                                 return ">";
7312                         case OpType.LessThan:
7313                                 return "<";
7314                         case OpType.GreaterThanOrEqual:
7315                                 return ">=";
7316                         case OpType.LessThanOrEqual:
7317                                 return "<=";
7318                         case OpType.Implicit:
7319                                 return "implicit";
7320                         case OpType.Explicit:
7321                                 return "explicit";
7322                         default: return "";
7323                         }
7324                 }
7325
7326                 public static OpType GetOperatorType (string name)
7327                 {
7328                         if (name.StartsWith ("op_")){
7329                                 for (int i = 0; i < Unary.oper_names.Length; ++i) {
7330                                         if (Unary.oper_names [i] == name)
7331                                                 return (OpType)i;
7332                                 }
7333
7334                                 for (int i = 0; i < Binary.oper_names.Length; ++i) {
7335                                         if (Binary.oper_names [i] == name)
7336                                                 return (OpType)i;
7337                                 }
7338                         }
7339                         return OpType.TOP;
7340                 }
7341
7342                 public override string GetSignatureForError ()
7343                 {
7344                         StringBuilder sb = new StringBuilder ();
7345                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7346                                 sb.AppendFormat ("{0}.{1} operator {2}", Parent.GetSignatureForError (), GetName (OperatorType), Type.Type == null ? Type.ToString () : TypeManager.CSharpName (Type.Type));
7347                         }
7348                         else {
7349                                 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
7350                         }
7351
7352                         sb.Append (Parameters.GetSignatureForError ());
7353                         return sb.ToString ();
7354                 }
7355         }
7356
7357         //
7358         // This is used to compare method signatures
7359         //
7360         struct MethodSignature {
7361                 public string Name;
7362                 public Type RetType;
7363                 public Type [] Parameters;
7364                 
7365                 /// <summary>
7366                 ///    This delegate is used to extract methods which have the
7367                 ///    same signature as the argument
7368                 /// </summary>
7369                 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
7370                 
7371                 public MethodSignature (string name, Type ret_type, Type [] parameters)
7372                 {
7373                         Name = name;
7374                         RetType = ret_type;
7375
7376                         if (parameters == null)
7377                                 Parameters = Type.EmptyTypes;
7378                         else
7379                                 Parameters = parameters;
7380                 }
7381
7382                 public override string ToString ()
7383                 {
7384                         string pars = "";
7385                         if (Parameters.Length != 0){
7386                                 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
7387                                 for (int i = 0; i < Parameters.Length; i++){
7388                                         sb.Append (Parameters [i]);
7389                                         if (i+1 < Parameters.Length)
7390                                                 sb.Append (", ");
7391                                 }
7392                                 pars = sb.ToString ();
7393                         }
7394
7395                         return String.Format ("{0} {1} ({2})", RetType, Name, pars);
7396                 }
7397                 
7398                 public override int GetHashCode ()
7399                 {
7400                         return Name.GetHashCode ();
7401                 }
7402
7403                 public override bool Equals (Object o)
7404                 {
7405                         MethodSignature other = (MethodSignature) o;
7406
7407                         if (other.Name != Name)
7408                                 return false;
7409
7410                         if (other.RetType != RetType)
7411                                 return false;
7412                         
7413                         if (Parameters == null){
7414                                 if (other.Parameters == null)
7415                                         return true;
7416                                 return false;
7417                         }
7418
7419                         if (other.Parameters == null)
7420                                 return false;
7421                         
7422                         int c = Parameters.Length;
7423                         if (other.Parameters.Length != c)
7424                                 return false;
7425
7426                         for (int i = 0; i < c; i++)
7427                                 if (other.Parameters [i] != Parameters [i])
7428                                         return false;
7429
7430                         return true;
7431                 }
7432
7433                 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
7434                 {
7435                         MethodSignature sig = (MethodSignature) filter_criteria;
7436
7437                         if (m.Name != sig.Name)
7438                                 return false;
7439
7440                         Type ReturnType;
7441                         MethodInfo mi = m as MethodInfo;
7442                         PropertyInfo pi = m as PropertyInfo;
7443
7444                         if (mi != null)
7445                                 ReturnType = mi.ReturnType;
7446                         else if (pi != null)
7447                                 ReturnType = pi.PropertyType;
7448                         else
7449                                 return false;
7450                         
7451                         //
7452                         // we use sig.RetType == null to mean `do not check the
7453                         // method return value.  
7454                         //
7455                         if (sig.RetType != null)
7456                                 if (ReturnType != sig.RetType)
7457                                         return false;
7458
7459                         Type [] args;
7460                         if (mi != null)
7461                                 args = TypeManager.GetParameterData (mi).Types;
7462                         else
7463                                 args = TypeManager.GetArgumentTypes (pi);
7464                         Type [] sigp = sig.Parameters;
7465
7466                         if (args.Length != sigp.Length)
7467                                 return false;
7468
7469                         for (int i = args.Length; i > 0; ){
7470                                 i--;
7471                                 if (args [i] != sigp [i])
7472                                         return false;
7473                         }
7474                         return true;
7475                 }
7476         }
7477 }