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