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