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