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