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