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