Remove GenericMethod
[mono.git] / mcs / mcs / property.cs
1 //
2 // property.cs: Property based 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 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
12 // Copyright 2011 Xamarin Inc
13 //
14
15 using System;
16 using System.Collections.Generic;
17 using System.Text;
18
19 #if NET_2_1
20 using XmlElement = System.Object;
21 #endif
22
23 #if STATIC
24 using IKVM.Reflection;
25 using IKVM.Reflection.Emit;
26 #else
27 using System.Reflection;
28 using System.Reflection.Emit;
29 #endif
30
31 namespace Mono.CSharp
32 {
33         // It is used as a base class for all property based members
34         // This includes properties, indexers, and events
35         public abstract class PropertyBasedMember : InterfaceMemberBase
36         {
37                 public PropertyBasedMember (DeclSpace parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
38                         : base (parent, type, mod, allowed_mod, name, attrs)
39                 {
40                 }
41
42                 protected void CheckReservedNameConflict (string prefix, MethodSpec accessor)
43                 {
44                         string name;
45                         AParametersCollection parameters;
46                         if (accessor != null) {
47                                 name = accessor.Name;
48                                 parameters = accessor.Parameters;
49                         } else {
50                                 name = prefix + ShortName;
51                                 if (IsExplicitImpl)
52                                         name = MemberName.Left + "." + name;
53
54                                 if (this is Indexer) {
55                                         parameters = ((Indexer) this).ParameterInfo;
56                                         if (prefix[0] == 's') {
57                                                 var data = new IParameterData[parameters.Count + 1];
58                                                 Array.Copy (parameters.FixedParameters, data, data.Length - 1);
59                                                 data[data.Length - 1] = new ParameterData ("value", Parameter.Modifier.NONE);
60                                                 var types = new TypeSpec[data.Length];
61                                                 Array.Copy (parameters.Types, types, data.Length - 1);
62                                                 types[data.Length - 1] = member_type;
63
64                                                 parameters = new ParametersImported (data, types, false);
65                                         }
66                                 } else {
67                                         if (prefix[0] == 's')
68                                                 parameters = ParametersCompiled.CreateFullyResolved (new[] { member_type });
69                                         else
70                                                 parameters = ParametersCompiled.EmptyReadOnlyParameters;
71                                 }
72                         }
73
74                         var conflict = MemberCache.FindMember (Parent.Definition,
75                                 new MemberFilter (name, 0, MemberKind.Method, parameters, null),
76                                 BindingRestriction.DeclaredOnly | BindingRestriction.NoAccessors);
77
78                         if (conflict != null) {
79                                 Report.SymbolRelatedToPreviousError (conflict);
80                                 Report.Error (82, Location, "A member `{0}' is already reserved", conflict.GetSignatureForError ());
81                         }
82                 }
83
84                 protected override bool VerifyClsCompliance ()
85                 {
86                         if (!base.VerifyClsCompliance ())
87                                 return false;
88
89                         if (!MemberType.IsCLSCompliant ()) {
90                                 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
91                                         GetSignatureForError ());
92                         }
93                         return true;
94                 }
95
96         }
97
98         public class PropertySpec : MemberSpec, IInterfaceMemberSpec
99         {
100                 PropertyInfo info;
101                 TypeSpec memberType;
102                 MethodSpec set, get;
103
104                 public PropertySpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, PropertyInfo info, Modifiers modifiers)
105                         : base (kind, declaringType, definition, modifiers)
106                 {
107                         this.info = info;
108                         this.memberType = memberType;
109                 }
110
111                 #region Properties
112
113                 public MethodSpec Get {
114                         get {
115                                 return get;
116                         }
117                         set {
118                                 get = value;
119                                 get.IsAccessor = true;
120                         }
121                 }
122
123                 public MethodSpec Set { 
124                         get {
125                                 return set;
126                         }
127                         set {
128                                 set = value;
129                                 set.IsAccessor = true;
130                         }
131                 }
132
133                 public bool HasDifferentAccessibility {
134                         get {
135                                 return HasGet && HasSet && 
136                                         (Get.Modifiers & Modifiers.AccessibilityMask) != (Set.Modifiers & Modifiers.AccessibilityMask);
137                         }
138                 }
139
140                 public bool HasGet {
141                         get {
142                                 return Get != null;
143                         }
144                 }
145
146                 public bool HasSet {
147                         get {
148                                 return Set != null;
149                         }
150                 }
151
152                 public PropertyInfo MetaInfo {
153                         get {
154                                 if ((state & StateFlags.PendingMetaInflate) != 0)
155                                         throw new NotSupportedException ();
156
157                                 return info;
158                         }
159                 }
160
161                 public TypeSpec MemberType {
162                         get {
163                                 return memberType;
164                         }
165                 }
166
167                 #endregion
168
169                 public override MemberSpec InflateMember (TypeParameterInflator inflator)
170                 {
171                         var ps = (PropertySpec) base.InflateMember (inflator);
172                         ps.memberType = inflator.Inflate (memberType);
173                         return ps;
174                 }
175
176                 public override List<TypeSpec> ResolveMissingDependencies ()
177                 {
178                         return memberType.ResolveMissingDependencies ();
179                 }
180         }
181
182         //
183         // Properties and Indexers both generate PropertyBuilders, we use this to share 
184         // their common bits.
185         //
186         abstract public class PropertyBase : PropertyBasedMember {
187
188                 public class GetMethod : PropertyMethod
189                 {
190                         static readonly string[] attribute_targets = new string [] { "method", "return" };
191
192                         internal const string Prefix = "get_";
193
194                         public GetMethod (PropertyBase method, Modifiers modifiers, Attributes attrs, Location loc)
195                                 : base (method, Prefix, modifiers, attrs, loc)
196                         {
197                         }
198
199                         public override MethodBuilder Define (DeclSpace parent)
200                         {
201                                 base.Define (parent);
202
203                                 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags);
204
205                                 method_data = new MethodData (method, ModFlags, flags, this);
206
207                                 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
208                                         return null;
209
210                                 Spec.SetMetaInfo (method_data.MethodBuilder);
211
212                                 return method_data.MethodBuilder;
213                         }
214
215                         public override TypeSpec ReturnType {
216                                 get {
217                                         return method.MemberType;
218                                 }
219                         }
220
221                         public override ParametersCompiled ParameterInfo {
222                                 get {
223                                         return ParametersCompiled.EmptyReadOnlyParameters;
224                                 }
225                         }
226
227                         public override string[] ValidAttributeTargets {
228                                 get {
229                                         return attribute_targets;
230                                 }
231                         }
232                 }
233
234                 public class SetMethod : PropertyMethod {
235
236                         static readonly string[] attribute_targets = new string[] { "method", "param", "return" };
237
238                         internal const string Prefix = "set_";
239
240                         protected ParametersCompiled parameters;
241
242                         public SetMethod (PropertyBase method, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
243                                 : base (method, Prefix, modifiers, attrs, loc)
244                         {
245                                 this.parameters = parameters;
246                         }
247
248                         protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
249                         {
250                                 if (a.Target == AttributeTargets.Parameter) {
251                                         parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa);
252                                         return;
253                                 }
254
255                                 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
256                         }
257
258                         public override ParametersCompiled ParameterInfo {
259                             get {
260                                 return parameters;
261                             }
262                         }
263
264                         public override MethodBuilder Define (DeclSpace parent)
265                         {
266                                 parameters.Resolve (this);
267                                 
268                                 base.Define (parent);
269
270                                 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags);
271
272                                 method_data = new MethodData (method, ModFlags, flags, this);
273
274                                 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
275                                         return null;
276
277                                 Spec.SetMetaInfo (method_data.MethodBuilder);
278
279                                 return method_data.MethodBuilder;
280                         }
281
282                         public override TypeSpec ReturnType {
283                                 get {
284                                         return Parent.Compiler.BuiltinTypes.Void;
285                                 }
286                         }
287
288                         public override string[] ValidAttributeTargets {
289                                 get {
290                                         return attribute_targets;
291                                 }
292                         }
293                 }
294
295                 static readonly string[] attribute_targets = new string[] { "property" };
296
297                 public abstract class PropertyMethod : AbstractPropertyEventMethod
298                 {
299                         const Modifiers AllowedModifiers =
300                                 Modifiers.PUBLIC |
301                                 Modifiers.PROTECTED |
302                                 Modifiers.INTERNAL |
303                                 Modifiers.PRIVATE;
304                 
305                         protected readonly PropertyBase method;
306                         protected MethodAttributes flags;
307
308                         public PropertyMethod (PropertyBase method, string prefix, Modifiers modifiers, Attributes attrs, Location loc)
309                                 : base (method, prefix, attrs, loc)
310                         {
311                                 this.method = method;
312                                 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, modifiers, 0, loc, Report);
313                                 this.ModFlags |= (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
314                         }
315
316                         public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
317                         {
318                                 if (a.Type == pa.MethodImpl) {
319                                         method.is_external_implementation = a.IsInternalCall ();
320                                 }
321
322                                 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
323                         }
324
325                         public override AttributeTargets AttributeTargets {
326                                 get {
327                                         return AttributeTargets.Method;
328                                 }
329                         }
330
331                         public override bool IsClsComplianceRequired ()
332                         {
333                                 return method.IsClsComplianceRequired ();
334                         }
335
336                         public virtual MethodBuilder Define (DeclSpace parent)
337                         {
338                                 TypeContainer container = parent.PartialContainer;
339
340                                 //
341                                 // Check for custom access modifier
342                                 //
343                                 if ((ModFlags & Modifiers.AccessibilityMask) == 0) {
344                                         ModFlags |= method.ModFlags;
345                                         flags = method.flags;
346                                 } else {
347                                         if (container.Kind == MemberKind.Interface)
348                                                 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
349                                                         GetSignatureForError ());
350                                         else if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
351                                                 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
352                                         }
353
354                                         CheckModifiers (ModFlags);
355                                         ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask));
356                                         ModFlags |= Modifiers.PROPERTY_CUSTOM;
357                                         flags = ModifiersExtensions.MethodAttr (ModFlags);
358                                         flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
359                                 }
360
361                                 CheckAbstractAndExtern (block != null);
362                                 CheckProtectedModifier ();
363
364                                 if (block != null && block.IsIterator)
365                                         Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
366
367                                 return null;
368                         }
369
370                         public bool HasCustomAccessModifier {
371                                 get {
372                                         return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
373                                 }
374                         }
375
376                         public PropertyBase Property {
377                                 get {
378                                         return method;
379                                 }
380                         }
381
382                         public override ObsoleteAttribute GetAttributeObsolete ()
383                         {
384                                 return method.GetAttributeObsolete ();
385                         }
386
387                         public override string GetSignatureForError()
388                         {
389                                 return method.GetSignatureForError () + "." + prefix.Substring (0, 3);
390                         }
391
392                         void CheckModifiers (Modifiers modflags)
393                         {
394                                 if (!ModifiersExtensions.IsRestrictedModifier (modflags & Modifiers.AccessibilityMask, method.ModFlags & Modifiers.AccessibilityMask)) {
395                                         Report.Error (273, Location,
396                                                 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
397                                                 GetSignatureForError (), method.GetSignatureForError ());
398                                 }
399                         }
400                 }
401
402                 PropertyMethod get, set, first;
403                 PropertyBuilder PropertyBuilder;
404
405                 public PropertyBase (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags,
406                                      Modifiers allowed_mod, MemberName name, Attributes attrs)
407                         : base (parent, type, mod_flags, allowed_mod, name, attrs)
408                 {
409                 }
410
411                 #region Properties
412
413                 public override AttributeTargets AttributeTargets {
414                         get {
415                                 return AttributeTargets.Property;
416                         }
417                 }
418
419                 public PropertyMethod AccessorFirst {
420                         get {
421                                 return first;
422                         }
423                 }
424
425                 public PropertyMethod AccessorSecond {
426                         get {
427                                 return first == get ? set : get;
428                         }
429                 }
430
431                 public override Variance ExpectedMemberTypeVariance {
432                         get {
433                                 return (get != null && set != null) ?
434                                         Variance.None : set == null ?
435                                         Variance.Covariant :
436                                         Variance.Contravariant;
437                         }
438                 }
439
440                 public PropertyMethod Get {
441                         get {
442                                 return get;
443                         }
444                         set {
445                                 get = value;
446                                 if (first == null)
447                                         first = value;
448
449                                 Parent.AddMember (get);
450                         }
451                 }
452
453                 public PropertyMethod Set {
454                         get {
455                                 return set;
456                         }
457                         set {
458                                 set = value;
459                                 if (first == null)
460                                         first = value;
461
462                                 Parent.AddMember (set);
463                         }
464                 }
465
466                 public override string[] ValidAttributeTargets {
467                         get {
468                                 return attribute_targets;
469                         }
470                 }
471
472                 #endregion
473
474                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
475                 {
476                         if (a.HasSecurityAttribute) {
477                                 a.Error_InvalidSecurityParent ();
478                                 return;
479                         }
480
481                         if (a.Type == pa.Dynamic) {
482                                 a.Error_MisusedDynamicAttribute ();
483                                 return;
484                         }
485
486                         PropertyBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
487                 }
488
489                 void CheckMissingAccessor (MemberKind kind, ParametersCompiled parameters, bool get)
490                 {
491                         if (IsExplicitImpl) {
492                                 MemberFilter filter;
493                                 if (kind == MemberKind.Indexer)
494                                         filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, kind, parameters, null);
495                                 else
496                                         filter = new MemberFilter (MemberName.Name, 0, kind, null, null);
497
498                                 var implementing = MemberCache.FindMember (InterfaceType, filter, BindingRestriction.DeclaredOnly) as PropertySpec;
499
500                                 if (implementing == null)
501                                         return;
502
503                                 var accessor = get ? implementing.Get : implementing.Set;
504                                 if (accessor != null) {
505                                         Report.SymbolRelatedToPreviousError (accessor);
506                                         Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
507                                                 GetSignatureForError (), accessor.GetSignatureForError ());
508                                 }
509                         }
510                 }
511
512                 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
513                 {
514                         var ok = base.CheckOverrideAgainstBase (base_member);
515
516                         //
517                         // Check base property accessors conflict
518                         //
519                         var base_prop = (PropertySpec) base_member;
520                         if (Get != null) {
521                                 if (!base_prop.HasGet) {
522                                         if (ok) {
523                                                 Report.SymbolRelatedToPreviousError (base_prop);
524                                                 Report.Error (545, Get.Location,
525                                                         "`{0}': cannot override because `{1}' does not have an overridable get accessor",
526                                                         Get.GetSignatureForError (), base_prop.GetSignatureForError ());
527                                                 ok = false;
528                                         }
529                                 } else if (Get.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
530                                         if (!CheckAccessModifiers (Get, base_prop.Get)) {
531                                                 Error_CannotChangeAccessModifiers (Get, base_prop.Get);
532                                                 ok = false;
533                                         }
534                                 }
535                         }
536
537                         if (Set != null) {
538                                 if (!base_prop.HasSet) {
539                                         if (ok) {
540                                                 Report.SymbolRelatedToPreviousError (base_prop);
541                                                 Report.Error (546, Set.Location,
542                                                         "`{0}': cannot override because `{1}' does not have an overridable set accessor",
543                                                         Set.GetSignatureForError (), base_prop.GetSignatureForError ());
544                                                 ok = false;
545                                         }
546                                 } else if (Set.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
547                                         if (!CheckAccessModifiers (Set, base_prop.Set)) {
548                                                 Error_CannotChangeAccessModifiers (Set, base_prop.Set);
549                                                 ok = false;
550                                         }
551                                 }
552                         }
553
554                         if ((Set == null || !Set.HasCustomAccessModifier) && (Get == null || !Get.HasCustomAccessModifier)) {
555                                 if (!CheckAccessModifiers (this, base_prop)) {
556                                         Error_CannotChangeAccessModifiers (this, base_prop);
557                                         ok = false;
558                                 }
559                         }
560
561                         return ok;
562                 }
563
564                 protected override void DoMemberTypeDependentChecks ()
565                 {
566                         base.DoMemberTypeDependentChecks ();
567
568                         IsTypePermitted ();
569
570                         if (MemberType.IsStatic)
571                                 Error_StaticReturnType ();
572                 }
573
574                 protected override void DoMemberTypeIndependentChecks ()
575                 {
576                         base.DoMemberTypeIndependentChecks ();
577
578                         //
579                         // Accessors modifiers check
580                         //
581                         if (AccessorSecond != null) {
582                                 if ((Get.ModFlags & Modifiers.AccessibilityMask) != 0 && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) {
583                                         Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
584                                                 GetSignatureForError ());
585                                 }
586                         } else if ((ModFlags & Modifiers.OVERRIDE) == 0 && 
587                                 (Get == null && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) ||
588                                 (Set == null && (Get.ModFlags & Modifiers.AccessibilityMask) != 0)) {
589                                 Report.Error (276, Location, 
590                                               "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
591                                               GetSignatureForError ());
592                         }
593                 }
594
595                 protected bool DefineAccessors ()
596                 {
597                         first.Define (Parent);
598                         if (AccessorSecond != null)
599                                 AccessorSecond.Define (Parent);
600
601                         return true;
602                 }
603
604                 protected void DefineBuilders (MemberKind kind, ParametersCompiled parameters)
605                 {
606                         PropertyBuilder = Parent.TypeBuilder.DefineProperty (
607                                 GetFullName (MemberName), PropertyAttributes.None,
608 #if !BOOTSTRAP_BASIC    // Requires trunk version mscorlib
609                                 IsStatic ? 0 : CallingConventions.HasThis,
610 #endif
611                                 MemberType.GetMetaInfo (), null, null,
612                                 parameters.GetMetaInfo (), null, null);
613
614                         PropertySpec spec;
615                         if (kind == MemberKind.Indexer)
616                                 spec = new IndexerSpec (Parent.Definition, this, MemberType, parameters, PropertyBuilder, ModFlags);
617                         else
618                                 spec = new PropertySpec (kind, Parent.Definition, this, MemberType, PropertyBuilder, ModFlags);
619
620                         if (Get != null) {
621                                 spec.Get = Get.Spec;
622
623                                 var method = Get.Spec.GetMetaInfo () as MethodBuilder;
624                                 if (method != null) {
625                                         PropertyBuilder.SetGetMethod (method);
626                                         Parent.MemberCache.AddMember (this, method.Name, Get.Spec);
627                                 }
628                         } else {
629                                 CheckMissingAccessor (kind, parameters, true);
630                         }
631
632                         if (Set != null) {
633                                 spec.Set = Set.Spec;
634
635                                 var method = Set.Spec.GetMetaInfo () as MethodBuilder;
636                                 if (method != null) {
637                                         PropertyBuilder.SetSetMethod (method);
638                                         Parent.MemberCache.AddMember (this, method.Name, Set.Spec);
639                                 }
640                         } else {
641                                 CheckMissingAccessor (kind, parameters, false);
642                         }
643
644                         Parent.MemberCache.AddMember (this, PropertyBuilder.Name, spec);
645                 }
646
647                 public override void Emit ()
648                 {
649                         CheckReservedNameConflict (GetMethod.Prefix, get == null ? null : get.Spec);
650                         CheckReservedNameConflict (SetMethod.Prefix, set == null ? null : set.Spec);
651
652                         if (OptAttributes != null)
653                                 OptAttributes.Emit ();
654
655                         if (member_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
656                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder);
657                         } else if (member_type.HasDynamicElement) {
658                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder, member_type, Location);
659                         }
660
661                         ConstraintChecker.Check (this, member_type, type_expr.Location);
662
663                         first.Emit (Parent);
664                         if (AccessorSecond != null)
665                                 AccessorSecond.Emit (Parent);
666
667                         base.Emit ();
668                 }
669
670                 public override bool IsUsed {
671                         get {
672                                 if (IsExplicitImpl)
673                                         return true;
674
675                                 return Get.IsUsed | Set.IsUsed;
676                         }
677                 }
678
679                 protected override void SetMemberName (MemberName new_name)
680                 {
681                         base.SetMemberName (new_name);
682
683                         if (Get != null)
684                                 Get.UpdateName (this);
685
686                         if (Set != null)
687                                 Set.UpdateName (this);
688                 }
689
690                 //
691                 //   Represents header string for documentation comment.
692                 //
693                 public override string DocCommentHeader {
694                         get { return "P:"; }
695                 }
696         }
697                         
698         public class Property : PropertyBase
699         {
700                 public sealed class BackingField : Field
701                 {
702                         readonly Property property;
703
704                         public BackingField (Property p)
705                                 : base (p.Parent, p.type_expr,
706                                 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
707                                 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
708                         {
709                                 this.property = p;
710                         }
711
712                         public Property OriginalProperty {
713                                 get {
714                                         return property;
715                                 }
716                         }
717
718                         public override string GetSignatureForError ()
719                         {
720                                 return property.GetSignatureForError ();
721                         }
722                 }
723
724                 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
725                                  MemberName name, Attributes attrs)
726                         : base (parent, type, mod,
727                                 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
728                                 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
729                                 AllowedModifiersClass,
730                                 name, attrs)
731                 {
732                 }
733
734                 public override void Accept (StructuralVisitor visitor)
735                 {
736                         visitor.Visit (this);
737                 }
738                 
739
740                 void CreateAutomaticProperty ()
741                 {
742                         // Create backing field
743                         Field field = new BackingField (this);
744                         if (!field.Define ())
745                                 return;
746
747                         Parent.PartialContainer.AddField (field);
748
749                         FieldExpr fe = new FieldExpr (field, Location);
750                         if ((field.ModFlags & Modifiers.STATIC) == 0)
751                                 fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
752
753                         // Create get block
754                         Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
755                         Return r = new Return (fe, Location);
756                         Get.Block.AddStatement (r);
757
758                         // Create set block
759                         Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location);
760                         Assign a = new SimpleAssign (fe, new SimpleName ("value", Location));
761                         Set.Block.AddStatement (new StatementExpression (a));
762                 }
763
764                 public override bool Define ()
765                 {
766                         if (!base.Define ())
767                                 return false;
768
769                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
770
771                         if (!IsInterface && (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
772                                 AccessorSecond != null && Get.Block == null && Set.Block == null) {
773                                 if (Compiler.Settings.Version <= LanguageVersion.ISO_2)
774                                         Report.FeatureIsNotAvailable (Compiler, Location, "automatically implemented properties");
775
776                                 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
777                                 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
778                                 CreateAutomaticProperty ();
779                         }
780
781                         if (!DefineAccessors ())
782                                 return false;
783
784                         if (AccessorSecond == null) {
785                                 PropertyMethod pm;
786                                 if (AccessorFirst is GetMethod)
787                                         pm = new SetMethod (this, 0, ParametersCompiled.EmptyReadOnlyParameters, null, Location);
788                                 else
789                                         pm = new GetMethod (this, 0, null, Location);
790
791                                 Parent.AddMember (pm);
792                         }
793
794                         if (!CheckBase ())
795                                 return false;
796
797                         DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters);
798                         return true;
799                 }
800
801                 public override void Emit ()
802                 {
803                         if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
804                                 Report.Error (842, Location,
805                                         "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
806                                         GetSignatureForError ());
807                         }
808
809                         base.Emit ();
810                 }
811         }
812
813         /// <summary>
814         /// For case when event is declared like property (with add and remove accessors).
815         /// </summary>
816         public class EventProperty: Event {
817                 public abstract class AEventPropertyAccessor : AEventAccessor
818                 {
819                         protected AEventPropertyAccessor (EventProperty method, string prefix, Attributes attrs, Location loc)
820                                 : base (method, prefix, attrs, loc)
821                         {
822                         }
823
824                         public override MethodBuilder Define (DeclSpace ds)
825                         {
826                                 CheckAbstractAndExtern (block != null);
827                                 return base.Define (ds);
828                         }
829                         
830                         public override string GetSignatureForError ()
831                         {
832                                 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
833                         }
834                 }
835
836                 public sealed class AddDelegateMethod: AEventPropertyAccessor
837                 {
838                         public AddDelegateMethod (EventProperty method, Attributes attrs, Location loc)
839                                 : base (method, AddPrefix, attrs, loc)
840                         {
841                         }
842                 }
843
844                 public sealed class RemoveDelegateMethod: AEventPropertyAccessor
845                 {
846                         public RemoveDelegateMethod (EventProperty method, Attributes attrs, Location loc)
847                                 : base (method, RemovePrefix, attrs, loc)
848                         {
849                         }
850                 }
851
852                 static readonly string[] attribute_targets = new string [] { "event" };
853
854                 public EventProperty (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
855                         : base (parent, type, mod_flags, name, attrs)
856                 {
857                 }
858
859                 public override void Accept (StructuralVisitor visitor)
860                 {
861                         visitor.Visit (this);
862                 }
863                 
864                 public override bool Define()
865                 {
866                         if (!base.Define ())
867                                 return false;
868
869                         SetIsUsed ();
870                         return true;
871                 }
872
873                 public override string[] ValidAttributeTargets {
874                         get {
875                                 return attribute_targets;
876                         }
877                 }
878         }
879
880         /// <summary>
881         /// Event is declared like field.
882         /// </summary>
883         public class EventField : Event
884         {
885                 abstract class EventFieldAccessor : AEventAccessor
886                 {
887                         protected EventFieldAccessor (EventField method, string prefix)
888                                 : base (method, prefix, null, method.Location)
889                         {
890                         }
891
892                         protected abstract MethodSpec GetOperation (Location loc);
893
894                         public override void Emit (DeclSpace parent)
895                         {
896                                 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
897                                         block = new ToplevelBlock (Compiler, ParameterInfo, Location);
898                                         FabricateBodyStatement ();
899                                 }
900
901                                 base.Emit (parent);
902                         }
903
904                         void FabricateBodyStatement ()
905                         {
906                                 //
907                                 // Delegate obj1 = backing_field
908                                 // do {
909                                 //   Delegate obj2 = obj1;
910                                 //   obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1);
911                                 // } while ((object)obj1 != (object)obj2)
912                                 //
913
914                                 var field_info = ((EventField) method).backing_field;
915                                 FieldExpr f_expr = new FieldExpr (field_info, Location);
916                                 if (!IsStatic)
917                                         f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
918
919                                 var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
920                                 var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
921
922                                 block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr)));
923
924                                 var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality,
925                                         new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj1, Location), Location),
926                                         new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj2, Location), Location),
927                                         Location));
928
929                                 var body = new ExplicitBlock (block, Location, Location);
930                                 block.AddStatement (new Do (body, cond, Location));
931
932                                 body.AddStatement (new StatementExpression (
933                                         new SimpleAssign (new LocalVariableReference (obj2, Location), new LocalVariableReference (obj1, Location))));
934
935                                 var args_oper = new Arguments (2);
936                                 args_oper.Add (new Argument (new LocalVariableReference (obj2, Location)));
937                                 args_oper.Add (new Argument (block.GetParameterReference (0, Location)));
938
939                                 var op_method = GetOperation (Location);
940
941                                 var args = new Arguments (3);
942                                 args.Add (new Argument (f_expr, Argument.AType.Ref));
943                                 args.Add (new Argument (new Cast (
944                                         new TypeExpression (field_info.MemberType, Location),
945                                         new Invocation (MethodGroupExpr.CreatePredefined (op_method, op_method.DeclaringType, Location), args_oper),
946                                         Location)));
947                                 args.Add (new Argument (new LocalVariableReference (obj1, Location)));
948
949                                 var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location);
950                                 if (cas == null)
951                                         return;
952
953                                 body.AddStatement (new StatementExpression (new SimpleAssign (
954                                         new LocalVariableReference (obj1, Location),
955                                         new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args))));
956                         }
957                 }
958
959                 sealed class AddDelegateMethod: EventFieldAccessor
960                 {
961                         public AddDelegateMethod (EventField method):
962                                 base (method, AddPrefix)
963                         {
964                         }
965
966                         protected override MethodSpec GetOperation (Location loc)
967                         {
968                                 return Module.PredefinedMembers.DelegateCombine.Resolve (loc);
969                         }
970                 }
971
972                 sealed class RemoveDelegateMethod: EventFieldAccessor
973                 {
974                         public RemoveDelegateMethod (EventField method):
975                                 base (method, RemovePrefix)
976                         {
977                         }
978
979                         protected override MethodSpec GetOperation (Location loc)
980                         {
981                                 return Module.PredefinedMembers.DelegateRemove.Resolve (loc);
982                         }
983                 }
984
985
986                 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
987                 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
988
989                 Expression initializer;
990                 Field backing_field;
991                 List<FieldDeclarator> declarators;
992
993                 public EventField (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
994                         : base (parent, type, mod_flags, name, attrs)
995                 {
996                         Add = new AddDelegateMethod (this);
997                         Remove = new RemoveDelegateMethod (this);
998                 }
999
1000                 #region Properties
1001
1002                 public List<FieldDeclarator> Declarators {
1003                         get {
1004                                 return this.declarators;
1005                         }
1006                 }
1007
1008                 bool HasBackingField {
1009                         get {
1010                                 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
1011                         }
1012                 }
1013
1014                 public Expression Initializer {
1015                         get {
1016                                 return initializer;
1017                         }
1018                         set {
1019                                 initializer = value;
1020                         }
1021                 }
1022
1023                 public override string[] ValidAttributeTargets {
1024                         get {
1025                                 return HasBackingField ? attribute_targets : attribute_targets_interface;
1026                         }
1027                 }
1028
1029                 #endregion
1030
1031                 
1032                 public override void Accept (StructuralVisitor visitor)
1033                 {
1034                         visitor.Visit (this);
1035                 }
1036
1037                 public void AddDeclarator (FieldDeclarator declarator)
1038                 {
1039                         if (declarators == null)
1040                                 declarators = new List<FieldDeclarator> (2);
1041
1042                         declarators.Add (declarator);
1043
1044                         // TODO: This will probably break
1045                         Parent.AddMember (this, declarator.Name.Value);
1046                 }
1047
1048                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1049                 {
1050                         if (a.Target == AttributeTargets.Field) {
1051                                 backing_field.ApplyAttributeBuilder (a, ctor, cdata, pa);
1052                                 return;
1053                         }
1054
1055                         if (a.Target == AttributeTargets.Method) {
1056                                 int errors = Report.Errors;
1057                                 Add.ApplyAttributeBuilder (a, ctor, cdata, pa);
1058                                 if (errors == Report.Errors)
1059                                         Remove.ApplyAttributeBuilder (a, ctor, cdata, pa);
1060                                 return;
1061                         }
1062
1063                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1064                 }
1065
1066                 public override bool Define()
1067                 {
1068                         var mod_flags_src = ModFlags;
1069
1070                         if (!base.Define ())
1071                                 return false;
1072
1073                         if (declarators != null) {
1074                                 if ((mod_flags_src & Modifiers.DEFAULT_ACCESS_MODIFER) != 0)
1075                                         mod_flags_src &= ~(Modifiers.AccessibilityMask | Modifiers.DEFAULT_ACCESS_MODIFER);
1076
1077                                 var t = new TypeExpression (MemberType, TypeExpression.Location);
1078                                 int index = Parent.PartialContainer.Events.IndexOf (this);
1079                                 foreach (var d in declarators) {
1080                                         var ef = new EventField (Parent, t, mod_flags_src, new MemberName (d.Name.Value, d.Name.Location), OptAttributes);
1081
1082                                         if (d.Initializer != null)
1083                                                 ef.initializer = d.Initializer;
1084
1085                                         Parent.PartialContainer.Events.Insert (++index, ef);
1086                                 }
1087                         }
1088
1089                         if (!HasBackingField) {
1090                                 SetIsUsed ();
1091                                 return true;
1092                         }
1093
1094                         if (Add.IsInterfaceImplementation)
1095                                 SetIsUsed ();
1096
1097                         backing_field = new Field (Parent,
1098                                 new TypeExpression (MemberType, Location),
1099                                 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
1100                                 MemberName, null);
1101
1102                         Parent.PartialContainer.AddField (backing_field);
1103                         backing_field.Initializer = Initializer;
1104                         backing_field.ModFlags &= ~Modifiers.COMPILER_GENERATED;
1105
1106                         // Call define because we passed fields definition
1107                         backing_field.Define ();
1108
1109                         // Set backing field for event fields
1110                         spec.BackingField = backing_field.Spec;
1111
1112                         return true;
1113                 }
1114         }
1115
1116         public abstract class Event : PropertyBasedMember
1117         {
1118                 public abstract class AEventAccessor : AbstractPropertyEventMethod
1119                 {
1120                         protected readonly Event method;
1121                         readonly ParametersCompiled parameters;
1122
1123                         static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
1124
1125                         public const string AddPrefix = "add_";
1126                         public const string RemovePrefix = "remove_";
1127
1128                         protected AEventAccessor (Event method, string prefix, Attributes attrs, Location loc)
1129                                 : base (method, prefix, attrs, loc)
1130                         {
1131                                 this.method = method;
1132                                 this.ModFlags = method.ModFlags;
1133                                 this.parameters = ParametersCompiled.CreateImplicitParameter (method.TypeExpression, loc);
1134                         }
1135
1136                         public bool IsInterfaceImplementation {
1137                                 get { return method_data.implementing != null; }
1138                         }
1139
1140                         public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1141                         {
1142                                 if (a.Type == pa.MethodImpl) {
1143                                         method.is_external_implementation = a.IsInternalCall ();
1144                                 }
1145
1146                                 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1147                         }
1148
1149                         protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1150                         {
1151                                 if (a.Target == AttributeTargets.Parameter) {
1152                                         parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa);
1153                                         return;
1154                                 }
1155
1156                                 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1157                         }
1158
1159                         public override AttributeTargets AttributeTargets {
1160                                 get {
1161                                         return AttributeTargets.Method;
1162                                 }
1163                         }
1164
1165                         public override bool IsClsComplianceRequired ()
1166                         {
1167                                 return method.IsClsComplianceRequired ();
1168                         }
1169
1170                         public virtual MethodBuilder Define (DeclSpace parent)
1171                         {
1172                                 // Fill in already resolved event type to speed things up and
1173                                 // avoid confusing duplicate errors
1174                                 ((Parameter) parameters.FixedParameters[0]).Type = method.member_type;
1175                                 parameters.Types = new TypeSpec[] { method.member_type };
1176
1177                                 method_data = new MethodData (method, method.ModFlags,
1178                                         method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
1179
1180                                 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
1181                                         return null;
1182
1183                                 MethodBuilder mb = method_data.MethodBuilder;
1184
1185                                 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, mb, ParameterInfo, method.ModFlags);
1186                                 Spec.IsAccessor = true;
1187
1188                                 return mb;
1189                         }
1190
1191                         public override TypeSpec ReturnType {
1192                                 get {
1193                                         return Parent.Compiler.BuiltinTypes.Void;
1194                                 }
1195                         }
1196
1197                         public override ObsoleteAttribute GetAttributeObsolete ()
1198                         {
1199                                 return method.GetAttributeObsolete ();
1200                         }
1201
1202                         public override string[] ValidAttributeTargets {
1203                                 get {
1204                                         return attribute_targets;
1205                                 }
1206                         }
1207
1208                         public override ParametersCompiled ParameterInfo {
1209                                 get {
1210                                         return parameters;
1211                                 }
1212                         }
1213                 }
1214
1215                 AEventAccessor add, remove;
1216                 EventBuilder EventBuilder;
1217                 protected EventSpec spec;
1218
1219                 protected Event (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1220                         : base (parent, type, mod_flags,
1221                                 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
1222                                 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
1223                                 AllowedModifiersClass,
1224                                 name, attrs)
1225                 {
1226                 }
1227
1228                 #region Properties
1229
1230                 public override AttributeTargets AttributeTargets {
1231                         get {
1232                                 return AttributeTargets.Event;
1233                         }
1234                 }
1235
1236                 public AEventAccessor Add {
1237                         get {
1238                                 return this.add;
1239                         }
1240                         set {
1241                                 add = value;
1242                                 Parent.AddMember (value);
1243                         }
1244                 }
1245
1246                 public override Variance ExpectedMemberTypeVariance {
1247                         get {
1248                                 return Variance.Contravariant;
1249                         }
1250                 }
1251
1252                 public AEventAccessor Remove {
1253                         get {
1254                                 return this.remove;
1255                         }
1256                         set {
1257                                 remove = value;
1258                                 Parent.AddMember (value);
1259                         }
1260                 }
1261                 #endregion
1262
1263                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1264                 {
1265                         if ((a.HasSecurityAttribute)) {
1266                                 a.Error_InvalidSecurityParent ();
1267                                 return;
1268                         }
1269
1270                         EventBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1271                 }
1272
1273                 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
1274                 {
1275                         var ok = base.CheckOverrideAgainstBase (base_member);
1276
1277                         if (!CheckAccessModifiers (this, base_member)) {
1278                                 Error_CannotChangeAccessModifiers (this, base_member);
1279                                 ok = false;
1280                         }
1281
1282                         return ok;
1283                 }
1284
1285                 public override bool Define ()
1286                 {
1287                         if (!base.Define ())
1288                                 return false;
1289
1290                         if (!MemberType.IsDelegate) {
1291                                 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
1292                         }
1293
1294                         if (!CheckBase ())
1295                                 return false;
1296
1297                         //
1298                         // Now define the accessors
1299                         //
1300                         var AddBuilder = Add.Define (Parent);
1301                         if (AddBuilder == null)
1302                                 return false;
1303
1304                         var RemoveBuilder = remove.Define (Parent);
1305                         if (RemoveBuilder == null)
1306                                 return false;
1307
1308                         EventBuilder = Parent.TypeBuilder.DefineEvent (GetFullName (MemberName), EventAttributes.None, MemberType.GetMetaInfo ());
1309                         EventBuilder.SetAddOnMethod (AddBuilder);
1310                         EventBuilder.SetRemoveOnMethod (RemoveBuilder);
1311
1312                         spec = new EventSpec (Parent.Definition, this, MemberType, ModFlags, Add.Spec, remove.Spec);
1313
1314                         Parent.MemberCache.AddMember (this, GetFullName (MemberName), spec);
1315                         Parent.MemberCache.AddMember (this, AddBuilder.Name, Add.Spec);
1316                         Parent.MemberCache.AddMember (this, RemoveBuilder.Name, remove.Spec);
1317
1318                         return true;
1319                 }
1320
1321                 public override void Emit ()
1322                 {
1323                         CheckReservedNameConflict (null, add.Spec);
1324                         CheckReservedNameConflict (null, remove.Spec);
1325
1326                         if (OptAttributes != null) {
1327                                 OptAttributes.Emit ();
1328                         }
1329
1330                         ConstraintChecker.Check (this, member_type, type_expr.Location);
1331
1332                         Add.Emit (Parent);
1333                         Remove.Emit (Parent);
1334
1335                         base.Emit ();
1336                 }
1337
1338                 //
1339                 //   Represents header string for documentation comment.
1340                 //
1341                 public override string DocCommentHeader {
1342                         get { return "E:"; }
1343                 }
1344         }
1345
1346         public class EventSpec : MemberSpec, IInterfaceMemberSpec
1347         {
1348                 MethodSpec add, remove;
1349                 FieldSpec backing_field;
1350
1351                 public EventSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec eventType, Modifiers modifiers, MethodSpec add, MethodSpec remove)
1352                         : base (MemberKind.Event, declaringType, definition, modifiers)
1353                 {
1354                         this.AccessorAdd = add;
1355                         this.AccessorRemove = remove;
1356                         this.MemberType = eventType;
1357                 }
1358
1359                 #region Properties
1360
1361                 public MethodSpec AccessorAdd { 
1362                         get {
1363                                 return add;
1364                         }
1365                         set {
1366                                 add = value;
1367                         }
1368                 }
1369
1370                 public MethodSpec AccessorRemove {
1371                         get {
1372                                 return remove;
1373                         }
1374                         set {
1375                                 remove = value;
1376                         }
1377                 }
1378
1379                 public FieldSpec BackingField {
1380                         get {
1381                                 return backing_field;
1382                         }
1383                         set {
1384                                 backing_field = value;
1385                         }
1386                 }
1387
1388                 public TypeSpec MemberType { get; private set; }
1389
1390                 #endregion
1391
1392                 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1393                 {
1394                         var es = (EventSpec) base.InflateMember (inflator);
1395                         es.MemberType = inflator.Inflate (MemberType);
1396
1397                         if (backing_field != null)
1398                                 es.backing_field = (FieldSpec) backing_field.InflateMember (inflator);
1399
1400                         return es;
1401                 }
1402
1403                 public override List<TypeSpec> ResolveMissingDependencies ()
1404                 {
1405                         return MemberType.ResolveMissingDependencies ();
1406                 }
1407         }
1408  
1409         public class Indexer : PropertyBase, IParametersMember
1410         {
1411                 public class GetIndexerMethod : GetMethod, IParametersMember
1412                 {
1413                         ParametersCompiled parameters;
1414
1415                         public GetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1416                                 : base (property, modifiers, attrs, loc)
1417                         {
1418                                 this.parameters = parameters;
1419                         }
1420
1421                         public override MethodBuilder Define (DeclSpace parent)
1422                         {
1423                                 parameters.Resolve (this);
1424                                 return base.Define (parent);
1425                         }
1426
1427                         public override ParametersCompiled ParameterInfo {
1428                                 get {
1429                                         return parameters;
1430                                 }
1431                         }
1432
1433                         #region IParametersMember Members
1434
1435                         AParametersCollection IParametersMember.Parameters {
1436                                 get {
1437                                         return parameters;
1438                                 }
1439                         }
1440
1441                         TypeSpec IInterfaceMemberSpec.MemberType {
1442                                 get {
1443                                         return ReturnType;
1444                                 }
1445                         }
1446
1447                         #endregion
1448                 }
1449
1450                 public class SetIndexerMethod : SetMethod, IParametersMember
1451                 {
1452                         public SetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1453                                 : base (property, modifiers, parameters, attrs, loc)
1454                         {
1455                         }
1456
1457                         #region IParametersMember Members
1458
1459                         AParametersCollection IParametersMember.Parameters {
1460                                 get {
1461                                         return parameters;
1462                                 }
1463                         }
1464
1465                         TypeSpec IInterfaceMemberSpec.MemberType {
1466                                 get {
1467                                         return ReturnType;
1468                                 }
1469                         }
1470
1471                         #endregion
1472                 }
1473
1474                 const Modifiers AllowedModifiers =
1475                         Modifiers.NEW |
1476                         Modifiers.PUBLIC |
1477                         Modifiers.PROTECTED |
1478                         Modifiers.INTERNAL |
1479                         Modifiers.PRIVATE |
1480                         Modifiers.VIRTUAL |
1481                         Modifiers.SEALED |
1482                         Modifiers.OVERRIDE |
1483                         Modifiers.UNSAFE |
1484                         Modifiers.EXTERN |
1485                         Modifiers.ABSTRACT;
1486
1487                 const Modifiers AllowedInterfaceModifiers =
1488                         Modifiers.NEW;
1489
1490                 readonly ParametersCompiled parameters;
1491
1492                 public Indexer (DeclSpace parent, FullNamedExpression type, MemberName name, Modifiers mod,
1493                                 ParametersCompiled parameters, Attributes attrs)
1494                         : base (parent, type, mod,
1495                                 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1496                                 name, attrs)
1497                 {
1498                         this.parameters = parameters;
1499                 }
1500
1501                 #region Properties
1502
1503                 AParametersCollection IParametersMember.Parameters {
1504                         get {
1505                                 return parameters;
1506                         }
1507                 }
1508
1509                 public ParametersCompiled ParameterInfo {
1510                         get {
1511                                 return parameters;
1512                         }
1513                 }
1514
1515                 #endregion
1516
1517                 
1518                 public override void Accept (StructuralVisitor visitor)
1519                 {
1520                         visitor.Visit (this);
1521                 }
1522
1523                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1524                 {
1525                         if (a.Type == pa.IndexerName) {
1526                                 // Attribute was copied to container
1527                                 return;
1528                         }
1529
1530                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1531                 }
1532
1533                 protected override bool CheckForDuplications ()
1534                 {
1535                         return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1536                 }
1537                 
1538                 public override bool Define ()
1539                 {
1540                         if (!base.Define ())
1541                                 return false;
1542
1543                         if (!DefineParameters (parameters))
1544                                 return false;
1545
1546                         if (OptAttributes != null) {
1547                                 Attribute indexer_attr = OptAttributes.Search (Module.PredefinedAttributes.IndexerName);
1548                                 if (indexer_attr != null) {
1549                                         var compiling = indexer_attr.Type.MemberDefinition as TypeContainer;
1550                                         if (compiling != null)
1551                                                 compiling.Define ();
1552
1553                                         if (IsExplicitImpl) {
1554                                                 Report.Error (415, indexer_attr.Location,
1555                                                         "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration",
1556                                                         indexer_attr.Type.GetSignatureForError ());
1557                                         } else if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1558                                                 Report.Error (609, indexer_attr.Location,
1559                                                         "Cannot set the `IndexerName' attribute on an indexer marked override");
1560                                         } else {
1561                                                 string name = indexer_attr.GetIndexerAttributeValue ();
1562
1563                                                 if (!string.IsNullOrEmpty (name)) {
1564                                                         SetMemberName (new MemberName (MemberName.Left, name, Location));
1565                                                 }
1566                                         }
1567                                 }
1568                         }
1569
1570                         if (InterfaceType != null) {
1571                                 string base_IndexerName = InterfaceType.MemberDefinition.GetAttributeDefaultMember ();
1572                                 if (base_IndexerName != ShortName) {
1573                                         SetMemberName (new MemberName (MemberName.Left, base_IndexerName, new TypeExpression (InterfaceType, Location), Location));
1574                                 }
1575                         }
1576
1577                         if (!Parent.PartialContainer.AddMember (this))
1578                                 return false;
1579
1580                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1581                         
1582                         if (!DefineAccessors ())
1583                                 return false;
1584
1585                         if (!CheckBase ())
1586                                 return false;
1587
1588                         DefineBuilders (MemberKind.Indexer, parameters);
1589                         return true;
1590                 }
1591
1592                 public override bool EnableOverloadChecks (MemberCore overload)
1593                 {
1594                         if (overload is Indexer) {
1595                                 caching_flags |= Flags.MethodOverloadsExist;
1596                                 return true;
1597                         }
1598
1599                         return base.EnableOverloadChecks (overload);
1600                 }
1601
1602                 public override void Emit ()
1603                 {
1604                         parameters.CheckConstraints (this);
1605
1606                         base.Emit ();
1607                 }
1608
1609                 public override string GetSignatureForError ()
1610                 {
1611                         StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
1612                         if (MemberName.ExplicitInterface != null) {
1613                                 sb.Append (".");
1614                                 sb.Append (MemberName.ExplicitInterface.GetSignatureForError ());
1615                         }
1616
1617                         sb.Append (".this");
1618                         sb.Append (parameters.GetSignatureForError ("[", "]", parameters.Count));
1619                         return sb.ToString ();
1620                 }
1621
1622                 public override string GetSignatureForDocumentation ()
1623                 {
1624                         return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1625                 }
1626
1627                 protected override bool VerifyClsCompliance ()
1628                 {
1629                         if (!base.VerifyClsCompliance ())
1630                                 return false;
1631
1632                         parameters.VerifyClsCompliance (this);
1633                         return true;
1634                 }
1635         }
1636
1637         public class IndexerSpec : PropertySpec, IParametersMember
1638         {
1639                 AParametersCollection parameters;
1640
1641                 public IndexerSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, AParametersCollection parameters, PropertyInfo info, Modifiers modifiers)
1642                         : base (MemberKind.Indexer, declaringType, definition, memberType, info, modifiers)
1643                 {
1644                         this.parameters = parameters;
1645                 }
1646
1647                 #region Properties
1648                 public AParametersCollection Parameters {
1649                         get {
1650                                 return parameters;
1651                         }
1652                 }
1653                 #endregion
1654
1655                 public override string GetSignatureForDocumentation ()
1656                 {
1657                         return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1658                 }
1659
1660                 public override string GetSignatureForError ()
1661                 {
1662                         return DeclaringType.GetSignatureForError () + ".this" + parameters.GetSignatureForError ("[", "]", parameters.Count);
1663                 }
1664
1665                 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1666                 {
1667                         var spec = (IndexerSpec) base.InflateMember (inflator);
1668                         spec.parameters = parameters.Inflate (inflator);
1669                         return spec;
1670                 }
1671
1672                 public override List<TypeSpec> ResolveMissingDependencies ()
1673                 {
1674                         var missing = base.ResolveMissingDependencies ();
1675                         foreach (var pt in parameters.Types) {
1676                                 var m = pt.GetMissingDependencies ();
1677                                 if (m == null)
1678                                         continue;
1679
1680                                 if (missing == null)
1681                                         missing = new List<TypeSpec> ();
1682
1683                                 missing.AddRange (m);
1684                         }
1685
1686                         return missing;
1687                 }
1688         }
1689 }