Merge some MD mcs changes
[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, GenericMethod generic,
38                         FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
39                         MemberName name, Attributes attrs)
40                         : base (parent, generic, type, mod, allowed_mod, name, attrs)
41                 {
42                 }
43
44                 protected void CheckReservedNameConflict (string prefix, MethodSpec accessor)
45                 {
46                         string name;
47                         AParametersCollection parameters;
48                         if (accessor != null) {
49                                 name = accessor.Name;
50                                 parameters = accessor.Parameters;
51                         } else {
52                                 name = prefix + ShortName;
53                                 if (IsExplicitImpl)
54                                         name = MemberName.Left + "." + name;
55
56                                 if (this is Indexer) {
57                                         parameters = ((Indexer) this).ParameterInfo;
58                                         if (prefix[0] == 's') {
59                                                 var data = new IParameterData[parameters.Count + 1];
60                                                 Array.Copy (parameters.FixedParameters, data, data.Length - 1);
61                                                 data[data.Length - 1] = new ParameterData ("value", Parameter.Modifier.NONE);
62                                                 var types = new TypeSpec[data.Length];
63                                                 Array.Copy (parameters.Types, types, data.Length - 1);
64                                                 types[data.Length - 1] = member_type;
65
66                                                 parameters = new ParametersImported (data, types, false);
67                                         }
68                                 } else {
69                                         if (prefix[0] == 's')
70                                                 parameters = ParametersCompiled.CreateFullyResolved (new[] { member_type });
71                                         else
72                                                 parameters = ParametersCompiled.EmptyReadOnlyParameters;
73                                 }
74                         }
75
76                         var conflict = MemberCache.FindMember (Parent.Definition,
77                                 new MemberFilter (name, 0, MemberKind.Method, parameters, null),
78                                 BindingRestriction.DeclaredOnly | BindingRestriction.NoAccessors);
79
80                         if (conflict != null) {
81                                 Report.SymbolRelatedToPreviousError (conflict);
82                                 Report.Error (82, Location, "A member `{0}' is already reserved", conflict.GetSignatureForError ());
83                         }
84                 }
85
86                 protected override bool VerifyClsCompliance ()
87                 {
88                         if (!base.VerifyClsCompliance ())
89                                 return false;
90
91                         if (!MemberType.IsCLSCompliant ()) {
92                                 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
93                                         GetSignatureForError ());
94                         }
95                         return true;
96                 }
97
98         }
99
100         public class PropertySpec : MemberSpec, IInterfaceMemberSpec
101         {
102                 PropertyInfo info;
103                 TypeSpec memberType;
104                 MethodSpec set, get;
105
106                 public PropertySpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, PropertyInfo info, Modifiers modifiers)
107                         : base (kind, declaringType, definition, modifiers)
108                 {
109                         this.info = info;
110                         this.memberType = memberType;
111                 }
112
113                 #region Properties
114
115                 public MethodSpec Get {
116                         get {
117                                 return get;
118                         }
119                         set {
120                                 get = value;
121                                 get.IsAccessor = true;
122                         }
123                 }
124
125                 public MethodSpec Set { 
126                         get {
127                                 return set;
128                         }
129                         set {
130                                 set = value;
131                                 set.IsAccessor = true;
132                         }
133                 }
134
135                 public bool HasDifferentAccessibility {
136                         get {
137                                 return HasGet && HasSet && 
138                                         (Get.Modifiers & Modifiers.AccessibilityMask) != (Set.Modifiers & Modifiers.AccessibilityMask);
139                         }
140                 }
141
142                 public bool HasGet {
143                         get {
144                                 return Get != null;
145                         }
146                 }
147
148                 public bool HasSet {
149                         get {
150                                 return Set != null;
151                         }
152                 }
153
154                 public PropertyInfo MetaInfo {
155                         get {
156                                 if ((state & StateFlags.PendingMetaInflate) != 0)
157                                         throw new NotSupportedException ();
158
159                                 return info;
160                         }
161                 }
162
163                 public TypeSpec MemberType {
164                         get {
165                                 return memberType;
166                         }
167                 }
168
169                 #endregion
170
171                 public override MemberSpec InflateMember (TypeParameterInflator inflator)
172                 {
173                         var ps = (PropertySpec) base.InflateMember (inflator);
174                         ps.memberType = inflator.Inflate (memberType);
175                         return ps;
176                 }
177
178                 public override List<TypeSpec> ResolveMissingDependencies ()
179                 {
180                         return memberType.ResolveMissingDependencies ();
181                 }
182         }
183
184         //
185         // Properties and Indexers both generate PropertyBuilders, we use this to share 
186         // their common bits.
187         //
188         abstract public class PropertyBase : PropertyBasedMember {
189
190                 public class GetMethod : PropertyMethod
191                 {
192                         static readonly string[] attribute_targets = new string [] { "method", "return" };
193
194                         internal const string Prefix = "get_";
195
196                         public GetMethod (PropertyBase method, Modifiers modifiers, Attributes attrs, Location loc)
197                                 : base (method, Prefix, modifiers, attrs, loc)
198                         {
199                         }
200
201                         public override MethodBuilder Define (DeclSpace parent)
202                         {
203                                 base.Define (parent);
204
205                                 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags);
206
207                                 method_data = new MethodData (method, ModFlags, flags, this);
208
209                                 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
210                                         return null;
211
212                                 Spec.SetMetaInfo (method_data.MethodBuilder);
213
214                                 return method_data.MethodBuilder;
215                         }
216
217                         public override TypeSpec ReturnType {
218                                 get {
219                                         return method.MemberType;
220                                 }
221                         }
222
223                         public override ParametersCompiled ParameterInfo {
224                                 get {
225                                         return ParametersCompiled.EmptyReadOnlyParameters;
226                                 }
227                         }
228
229                         public override string[] ValidAttributeTargets {
230                                 get {
231                                         return attribute_targets;
232                                 }
233                         }
234                 }
235
236                 public class SetMethod : PropertyMethod {
237
238                         static readonly string[] attribute_targets = new string[] { "method", "param", "return" };
239
240                         internal const string Prefix = "set_";
241
242                         protected ParametersCompiled parameters;
243
244                         public SetMethod (PropertyBase method, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
245                                 : base (method, Prefix, modifiers, attrs, loc)
246                         {
247                                 this.parameters = parameters;
248                         }
249
250                         protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
251                         {
252                                 if (a.Target == AttributeTargets.Parameter) {
253                                         parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa);
254                                         return;
255                                 }
256
257                                 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
258                         }
259
260                         public override ParametersCompiled ParameterInfo {
261                             get {
262                                 return parameters;
263                             }
264                         }
265
266                         public override MethodBuilder Define (DeclSpace parent)
267                         {
268                                 parameters.Resolve (this);
269                                 
270                                 base.Define (parent);
271
272                                 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags);
273
274                                 method_data = new MethodData (method, ModFlags, flags, this);
275
276                                 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
277                                         return null;
278
279                                 Spec.SetMetaInfo (method_data.MethodBuilder);
280
281                                 return method_data.MethodBuilder;
282                         }
283
284                         public override TypeSpec ReturnType {
285                                 get {
286                                         return Parent.Compiler.BuiltinTypes.Void;
287                                 }
288                         }
289
290                         public override string[] ValidAttributeTargets {
291                                 get {
292                                         return attribute_targets;
293                                 }
294                         }
295                 }
296
297                 static readonly string[] attribute_targets = new string[] { "property" };
298
299                 public abstract class PropertyMethod : AbstractPropertyEventMethod
300                 {
301                         const Modifiers AllowedModifiers =
302                                 Modifiers.PUBLIC |
303                                 Modifiers.PROTECTED |
304                                 Modifiers.INTERNAL |
305                                 Modifiers.PRIVATE;
306                 
307                         protected readonly PropertyBase method;
308                         protected MethodAttributes flags;
309
310                         public PropertyMethod (PropertyBase method, string prefix, Modifiers modifiers, Attributes attrs, Location loc)
311                                 : base (method, prefix, attrs, loc)
312                         {
313                                 this.method = method;
314                                 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, modifiers, 0, loc, Report);
315                                 this.ModFlags |= (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
316                         }
317
318                         public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
319                         {
320                                 if (a.Type == pa.MethodImpl) {
321                                         method.is_external_implementation = a.IsInternalCall ();
322                                 }
323
324                                 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
325                         }
326
327                         public override AttributeTargets AttributeTargets {
328                                 get {
329                                         return AttributeTargets.Method;
330                                 }
331                         }
332
333                         public override bool IsClsComplianceRequired ()
334                         {
335                                 return method.IsClsComplianceRequired ();
336                         }
337
338                         public virtual MethodBuilder Define (DeclSpace parent)
339                         {
340                                 TypeContainer container = parent.PartialContainer;
341
342                                 //
343                                 // Check for custom access modifier
344                                 //
345                                 if ((ModFlags & Modifiers.AccessibilityMask) == 0) {
346                                         ModFlags |= method.ModFlags;
347                                         flags = method.flags;
348                                 } else {
349                                         if (container.Kind == MemberKind.Interface)
350                                                 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
351                                                         GetSignatureForError ());
352                                         else if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
353                                                 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
354                                         }
355
356                                         CheckModifiers (ModFlags);
357                                         ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask));
358                                         ModFlags |= Modifiers.PROPERTY_CUSTOM;
359                                         flags = ModifiersExtensions.MethodAttr (ModFlags);
360                                         flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
361                                 }
362
363                                 CheckAbstractAndExtern (block != null);
364                                 CheckProtectedModifier ();
365
366                                 if (block != null && block.IsIterator)
367                                         Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
368
369                                 return null;
370                         }
371
372                         public bool HasCustomAccessModifier {
373                                 get {
374                                         return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
375                                 }
376                         }
377
378                         public PropertyBase Property {
379                                 get {
380                                         return method;
381                                 }
382                         }
383
384                         public override ObsoleteAttribute GetAttributeObsolete ()
385                         {
386                                 return method.GetAttributeObsolete ();
387                         }
388
389                         public override string GetSignatureForError()
390                         {
391                                 return method.GetSignatureForError () + "." + prefix.Substring (0, 3);
392                         }
393
394                         void CheckModifiers (Modifiers modflags)
395                         {
396                                 if (!ModifiersExtensions.IsRestrictedModifier (modflags & Modifiers.AccessibilityMask, method.ModFlags & Modifiers.AccessibilityMask)) {
397                                         Report.Error (273, Location,
398                                                 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
399                                                 GetSignatureForError (), method.GetSignatureForError ());
400                                 }
401                         }
402                 }
403
404                 PropertyMethod get, set, first;
405                 PropertyBuilder PropertyBuilder;
406
407                 public PropertyBase (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags,
408                                      Modifiers allowed_mod, MemberName name, Attributes attrs)
409                         : base (parent, null, type, mod_flags, allowed_mod, name, attrs)
410                 {
411                 }
412
413                 #region Properties
414
415                 public override AttributeTargets AttributeTargets {
416                         get {
417                                 return AttributeTargets.Property;
418                         }
419                 }
420
421                 public PropertyMethod AccessorFirst {
422                         get {
423                                 return first;
424                         }
425                 }
426
427                 public PropertyMethod AccessorSecond {
428                         get {
429                                 return first == get ? set : get;
430                         }
431                 }
432
433                 public override Variance ExpectedMemberTypeVariance {
434                         get {
435                                 return (get != null && set != null) ?
436                                         Variance.None : set == null ?
437                                         Variance.Covariant :
438                                         Variance.Contravariant;
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.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
658                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder);
659                         } else if (member_type.HasDynamicElement) {
660                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder, member_type, Location);
661                         }
662
663                         ConstraintChecker.Check (this, member_type, type_expr.Location);
664
665                         first.Emit (Parent);
666                         if (AccessorSecond != null)
667                                 AccessorSecond.Emit (Parent);
668
669                         base.Emit ();
670                 }
671
672                 public override bool IsUsed {
673                         get {
674                                 if (IsExplicitImpl)
675                                         return true;
676
677                                 return Get.IsUsed | Set.IsUsed;
678                         }
679                 }
680
681                 protected override void SetMemberName (MemberName new_name)
682                 {
683                         base.SetMemberName (new_name);
684
685                         if (Get != null)
686                                 Get.UpdateName (this);
687
688                         if (Set != null)
689                                 Set.UpdateName (this);
690                 }
691
692                 //
693                 //   Represents header string for documentation comment.
694                 //
695                 public override string DocCommentHeader {
696                         get { return "P:"; }
697                 }
698         }
699                         
700         public class Property : PropertyBase
701         {
702                 public sealed class BackingField : Field
703                 {
704                         readonly Property property;
705
706                         public BackingField (Property p)
707                                 : base (p.Parent, p.type_expr,
708                                 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
709                                 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
710                         {
711                                 this.property = p;
712                         }
713
714                         public string OriginalName {
715                                 get {
716                                         return property.Name;
717                                 }
718                         }
719
720                         public override string GetSignatureForError ()
721                         {
722                                 return property.GetSignatureForError ();
723                         }
724                 }
725
726                 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
727                                  MemberName name, Attributes attrs)
728                         : base (parent, type, mod,
729                                 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
730                                 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
731                                 AllowedModifiersClass,
732                                 name, attrs)
733                 {
734                 }
735
736                 public override void Accept (StructuralVisitor visitor)
737                 {
738                         visitor.Visit (this);
739                 }
740                 
741
742                 void CreateAutomaticProperty ()
743                 {
744                         // Create backing field
745                         Field field = new BackingField (this);
746                         if (!field.Define ())
747                                 return;
748
749                         Parent.PartialContainer.AddField (field);
750
751                         FieldExpr fe = new FieldExpr (field, Location);
752                         if ((field.ModFlags & Modifiers.STATIC) == 0)
753                                 fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
754
755                         // Create get block
756                         Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
757                         Return r = new Return (fe, Location);
758                         Get.Block.AddStatement (r);
759
760                         // Create set block
761                         Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location);
762                         Assign a = new SimpleAssign (fe, new SimpleName ("value", Location));
763                         Set.Block.AddStatement (new StatementExpression (a));
764                 }
765
766                 public override bool Define ()
767                 {
768                         if (!base.Define ())
769                                 return false;
770
771                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
772
773                         if (!IsInterface && (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
774                                 AccessorSecond != null && Get.Block == null && Set.Block == null) {
775                                 if (Compiler.Settings.Version <= LanguageVersion.ISO_2)
776                                         Report.FeatureIsNotAvailable (Compiler, Location, "automatically implemented properties");
777
778                                 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
779                                 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
780                                 CreateAutomaticProperty ();
781                         }
782
783                         if (!DefineAccessors ())
784                                 return false;
785
786                         if (AccessorSecond == null) {
787                                 PropertyMethod pm;
788                                 if (AccessorFirst is GetMethod)
789                                         pm = new SetMethod (this, 0, ParametersCompiled.EmptyReadOnlyParameters, null, Location);
790                                 else
791                                         pm = new GetMethod (this, 0, null, Location);
792
793                                 Parent.AddMember (pm);
794                         }
795
796                         if (!CheckBase ())
797                                 return false;
798
799                         DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters);
800                         return true;
801                 }
802
803                 public override void Emit ()
804                 {
805                         if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
806                                 Report.Error (842, Location,
807                                         "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
808                                         GetSignatureForError ());
809                         }
810
811                         base.Emit ();
812                 }
813         }
814
815         /// <summary>
816         /// For case when event is declared like property (with add and remove accessors).
817         /// </summary>
818         public class EventProperty: Event {
819                 public abstract class AEventPropertyAccessor : AEventAccessor
820                 {
821                         protected AEventPropertyAccessor (EventProperty method, string prefix, Attributes attrs, Location loc)
822                                 : base (method, prefix, attrs, loc)
823                         {
824                         }
825
826                         public override MethodBuilder Define (DeclSpace ds)
827                         {
828                                 CheckAbstractAndExtern (block != null);
829                                 return base.Define (ds);
830                         }
831                         
832                         public override string GetSignatureForError ()
833                         {
834                                 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
835                         }
836                 }
837
838                 public sealed class AddDelegateMethod: AEventPropertyAccessor
839                 {
840                         public AddDelegateMethod (EventProperty method, Attributes attrs, Location loc)
841                                 : base (method, AddPrefix, attrs, loc)
842                         {
843                         }
844                 }
845
846                 public sealed class RemoveDelegateMethod: AEventPropertyAccessor
847                 {
848                         public RemoveDelegateMethod (EventProperty method, Attributes attrs, Location loc)
849                                 : base (method, RemovePrefix, attrs, loc)
850                         {
851                         }
852                 }
853
854                 static readonly string[] attribute_targets = new string [] { "event" };
855
856                 public EventProperty (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
857                         : base (parent, type, mod_flags, name, attrs)
858                 {
859                 }
860
861                 public override void Accept (StructuralVisitor visitor)
862                 {
863                         visitor.Visit (this);
864                 }
865                 
866                 public override bool Define()
867                 {
868                         if (!base.Define ())
869                                 return false;
870
871                         SetIsUsed ();
872                         return true;
873                 }
874
875                 public override string[] ValidAttributeTargets {
876                         get {
877                                 return attribute_targets;
878                         }
879                 }
880         }
881
882         /// <summary>
883         /// Event is declared like field.
884         /// </summary>
885         public class EventField : Event
886         {
887                 abstract class EventFieldAccessor : AEventAccessor
888                 {
889                         protected EventFieldAccessor (EventField method, string prefix)
890                                 : base (method, prefix, null, method.Location)
891                         {
892                         }
893
894                         protected abstract MethodSpec GetOperation (Location loc);
895
896                         public override void Emit (DeclSpace parent)
897                         {
898                                 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
899                                         block = new ToplevelBlock (Compiler, ParameterInfo, Location);
900                                         FabricateBodyStatement ();
901                                 }
902
903                                 base.Emit (parent);
904                         }
905
906                         void FabricateBodyStatement ()
907                         {
908                                 //
909                                 // Delegate obj1 = backing_field
910                                 // do {
911                                 //   Delegate obj2 = obj1;
912                                 //   obj1 =     Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1);
913                                 // } while (obj1 != obj2)
914                                 //
915
916                                 var field_info = ((EventField) method).backing_field;
917                                 FieldExpr f_expr = new FieldExpr (field_info, Location);
918                                 if (!IsStatic)
919                                         f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
920
921                                 var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
922                                 var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
923
924                                 block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr)));
925
926                                 var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality,
927                                         new LocalVariableReference (obj1, Location), new LocalVariableReference (obj2, Location), 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, null, 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, Name, 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                                 if (IsExplicitImpl) {
1527                                         Report.Error (415, a.Location,
1528                                                 "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration",
1529                                                 TypeManager.CSharpName (a.Type));
1530                                 }
1531
1532                                 // Attribute was copied to container
1533                                 return;
1534                         }
1535
1536                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1537                 }
1538
1539                 protected override bool CheckForDuplications ()
1540                 {
1541                         return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1542                 }
1543                 
1544                 public override bool Define ()
1545                 {
1546                         if (!base.Define ())
1547                                 return false;
1548
1549                         if (!DefineParameters (parameters))
1550                                 return false;
1551
1552                         if (OptAttributes != null) {
1553                                 Attribute indexer_attr = OptAttributes.Search (Module.PredefinedAttributes.IndexerName);
1554                                 if (indexer_attr != null) {
1555                                         var compiling = indexer_attr.Type.MemberDefinition as TypeContainer;
1556                                         if (compiling != null)
1557                                                 compiling.Define ();
1558
1559                                         string name = indexer_attr.GetIndexerAttributeValue ();
1560                                         if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1561                                                 Report.Error (609, indexer_attr.Location,
1562                                                         "Cannot set the `IndexerName' attribute on an indexer marked override");
1563                                         }
1564
1565                                         if (!string.IsNullOrEmpty (name))
1566                                                 ShortName = name;
1567                                 }
1568                         }
1569
1570                         if (InterfaceType != null) {
1571                                 string base_IndexerName = InterfaceType.MemberDefinition.GetAttributeDefaultMember ();
1572                                 if (base_IndexerName != Name)
1573                                         ShortName = base_IndexerName;
1574                         }
1575
1576                         if (!Parent.PartialContainer.AddMember (this))
1577                                 return false;
1578
1579                         flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1580                         
1581                         if (!DefineAccessors ())
1582                                 return false;
1583
1584                         if (!CheckBase ())
1585                                 return false;
1586
1587                         DefineBuilders (MemberKind.Indexer, parameters);
1588                         return true;
1589                 }
1590
1591                 public override bool EnableOverloadChecks (MemberCore overload)
1592                 {
1593                         if (overload is Indexer) {
1594                                 caching_flags |= Flags.MethodOverloadsExist;
1595                                 return true;
1596                         }
1597
1598                         return base.EnableOverloadChecks (overload);
1599                 }
1600
1601                 public override void Emit ()
1602                 {
1603                         parameters.CheckConstraints (this);
1604
1605                         base.Emit ();
1606                 }
1607
1608                 public override string GetSignatureForError ()
1609                 {
1610                         StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
1611                         if (MemberName.Left != null) {
1612                                 sb.Append (".");
1613                                 sb.Append (MemberName.Left.GetSignatureForError ());
1614                         }
1615
1616                         sb.Append (".this");
1617                         sb.Append (parameters.GetSignatureForError ("[", "]", parameters.Count));
1618                         return sb.ToString ();
1619                 }
1620
1621                 public override string GetSignatureForDocumentation ()
1622                 {
1623                         return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1624                 }
1625
1626                 protected override bool VerifyClsCompliance ()
1627                 {
1628                         if (!base.VerifyClsCompliance ())
1629                                 return false;
1630
1631                         parameters.VerifyClsCompliance (this);
1632                         return true;
1633                 }
1634         }
1635
1636         public class IndexerSpec : PropertySpec, IParametersMember
1637         {
1638                 AParametersCollection parameters;
1639
1640                 public IndexerSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, AParametersCollection parameters, PropertyInfo info, Modifiers modifiers)
1641                         : base (MemberKind.Indexer, declaringType, definition, memberType, info, modifiers)
1642                 {
1643                         this.parameters = parameters;
1644                 }
1645
1646                 #region Properties
1647                 public AParametersCollection Parameters {
1648                         get {
1649                                 return parameters;
1650                         }
1651                 }
1652                 #endregion
1653
1654                 public override string GetSignatureForDocumentation ()
1655                 {
1656                         return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1657                 }
1658
1659                 public override string GetSignatureForError ()
1660                 {
1661                         return DeclaringType.GetSignatureForError () + ".this" + parameters.GetSignatureForError ("[", "]", parameters.Count);
1662                 }
1663
1664                 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1665                 {
1666                         var spec = (IndexerSpec) base.InflateMember (inflator);
1667                         spec.parameters = parameters.Inflate (inflator);
1668                         return spec;
1669                 }
1670
1671                 public override List<TypeSpec> ResolveMissingDependencies ()
1672                 {
1673                         var missing = base.ResolveMissingDependencies ();
1674                         foreach (var pt in parameters.Types) {
1675                                 var m = pt.GetMissingDependencies ();
1676                                 if (m == null)
1677                                         continue;
1678
1679                                 if (missing == null)
1680                                         missing = new List<TypeSpec> ();
1681
1682                                 missing.AddRange (m);
1683                         }
1684
1685                         return missing;
1686                 }
1687         }
1688 }