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