2010-06-04 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / property.cs
blobb90cd51dbf51167b454a61a569fa09385964937f
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
14 using System;
15 using System.Collections.Generic;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Runtime.CompilerServices;
19 using System.Runtime.InteropServices;
20 using System.Security;
21 using System.Security.Permissions;
22 using System.Text;
24 #if NET_2_1
25 using XmlElement = System.Object;
26 #else
27 using System.Xml;
28 #endif
30 using Mono.CompilerServices.SymbolWriter;
32 namespace Mono.CSharp
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
38 public PropertyBasedMember (DeclSpace parent, GenericMethod generic,
39 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
40 MemberName name, Attributes attrs)
41 : base (parent, generic, type, mod, allowed_mod, name, attrs)
45 protected override bool VerifyClsCompliance ()
47 if (!base.VerifyClsCompliance ())
48 return false;
50 if (!MemberType.IsCLSCompliant ()) {
51 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
52 GetSignatureForError ());
54 return true;
60 // `set' and `get' accessors are represented with an Accessor.
61 //
62 public class Accessor {
64 // Null if the accessor is empty, or a Block if not
66 public const Modifiers AllowedModifiers =
67 Modifiers.PUBLIC |
68 Modifiers.PROTECTED |
69 Modifiers.INTERNAL |
70 Modifiers.PRIVATE;
72 public ToplevelBlock Block;
73 public Attributes Attributes;
74 public Location Location;
75 public Modifiers ModFlags;
76 public ParametersCompiled Parameters;
78 public Accessor (ToplevelBlock b, Modifiers mod, Attributes attrs, ParametersCompiled p, Location loc)
80 Block = b;
81 Attributes = attrs;
82 Location = loc;
83 Parameters = p;
84 ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, 0, loc, RootContext.ToplevelTypes.Compiler.Report);
88 public class PropertySpec : MemberSpec, IInterfaceMemberSpec
90 PropertyInfo info;
91 TypeSpec memberType;
92 MethodSpec set, get;
94 public PropertySpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, PropertyInfo info, Modifiers modifiers)
95 : base (kind, declaringType, definition, modifiers)
97 this.info = info;
98 this.memberType = memberType;
101 #region Properties
103 public MethodSpec Get {
104 get {
105 return get;
107 set {
108 get = value;
109 get.IsAccessor = true;
113 public MethodSpec Set {
114 get {
115 return set;
117 set {
118 set = value;
119 set.IsAccessor = true;
123 public bool IsNotRealProperty {
124 get {
125 return (state & StateFlags.IsNotRealProperty) != 0;
127 set {
128 state |= StateFlags.IsNotRealProperty;
132 public bool HasDifferentAccessibility {
133 get {
134 return HasGet && HasSet &&
135 (Get.Modifiers & Modifiers.AccessibilityMask) != (Set.Modifiers & Modifiers.AccessibilityMask);
139 public bool HasGet {
140 get {
141 return Get != null && Get.Kind != MemberKind.FakeMethod;
145 public bool HasSet {
146 get {
147 return Set != null && Set.Kind != MemberKind.FakeMethod;
151 public PropertyInfo MetaInfo {
152 get {
153 if ((state & StateFlags.PendingMetaInflate) != 0)
154 throw new NotSupportedException ();
156 return info;
160 public TypeSpec MemberType {
161 get {
162 return memberType;
166 #endregion
168 public override MemberSpec InflateMember (TypeParameterInflator inflator)
170 var ps = (PropertySpec) base.InflateMember (inflator);
171 ps.memberType = inflator.Inflate (memberType);
172 return ps;
177 // Properties and Indexers both generate PropertyBuilders, we use this to share
178 // their common bits.
180 abstract public class PropertyBase : PropertyBasedMember {
182 public class GetMethod : PropertyMethod
184 static string[] attribute_targets = new string [] { "method", "return" };
186 public GetMethod (PropertyBase method):
187 base (method, "get_")
191 public GetMethod (PropertyBase method, Accessor accessor):
192 base (method, accessor, "get_")
196 public override MethodBuilder Define (DeclSpace parent)
198 base.Define (parent);
200 Spec = new MethodSpec (IsDummy ? MemberKind.FakeMethod : MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags);
202 if (IsDummy)
203 return null;
205 method_data = new MethodData (method, ModFlags, flags, this);
207 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
208 return null;
210 Spec.SetMetaInfo (method_data.MethodBuilder);
212 return method_data.MethodBuilder;
215 public override TypeSpec ReturnType {
216 get {
217 return method.MemberType;
221 public override ParametersCompiled ParameterInfo {
222 get {
223 return ParametersCompiled.EmptyReadOnlyParameters;
227 public override string[] ValidAttributeTargets {
228 get {
229 return attribute_targets;
234 public class SetMethod : PropertyMethod {
236 static string[] attribute_targets = new string [] { "method", "param", "return" };
237 ImplicitParameter param_attr;
238 protected ParametersCompiled parameters;
240 public SetMethod (PropertyBase method) :
241 base (method, "set_")
243 parameters = ParametersCompiled.CreateImplicitParameter (method.type_expr, Location);
246 public SetMethod (PropertyBase method, Accessor accessor):
247 base (method, accessor, "set_")
249 this.parameters = accessor.Parameters;
252 protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
254 if (a.Target == AttributeTargets.Parameter) {
255 if (param_attr == null)
256 param_attr = new ImplicitParameter (method_data.MethodBuilder);
258 param_attr.ApplyAttributeBuilder (a, ctor, cdata, pa);
259 return;
262 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
265 public override ParametersCompiled ParameterInfo {
266 get {
267 return parameters;
271 public override MethodBuilder Define (DeclSpace parent)
273 parameters.Resolve (this);
275 base.Define (parent);
277 Spec = new MethodSpec (IsDummy ? MemberKind.FakeMethod : MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags);
279 if (IsDummy)
280 return null;
282 method_data = new MethodData (method, ModFlags, flags, this);
284 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
285 return null;
287 Spec.SetMetaInfo (method_data.MethodBuilder);
289 return method_data.MethodBuilder;
292 public override TypeSpec ReturnType {
293 get {
294 return TypeManager.void_type;
298 public override string[] ValidAttributeTargets {
299 get {
300 return attribute_targets;
305 static string[] attribute_targets = new string [] { "property" };
307 public abstract class PropertyMethod : AbstractPropertyEventMethod
309 protected readonly PropertyBase method;
310 protected MethodAttributes flags;
312 public PropertyMethod (PropertyBase method, string prefix)
313 : base (method, prefix)
315 this.method = method;
316 this.ModFlags = method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE);
319 public PropertyMethod (PropertyBase method, Accessor accessor,
320 string prefix)
321 : base (method, accessor, prefix)
323 this.method = method;
324 this.ModFlags = accessor.ModFlags | (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
326 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
327 Report.FeatureIsNotAvailable (Location, "access modifiers on properties");
331 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
333 if (a.IsInternalMethodImplAttribute) {
334 method.is_external_implementation = true;
337 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
340 public override AttributeTargets AttributeTargets {
341 get {
342 return AttributeTargets.Method;
346 public override bool IsClsComplianceRequired ()
348 return method.IsClsComplianceRequired ();
351 public virtual MethodBuilder Define (DeclSpace parent)
353 CheckForDuplications ();
355 if (IsDummy) {
356 if (method.InterfaceType != null && parent.PartialContainer.PendingImplementations != null) {
357 var mi = parent.PartialContainer.PendingImplementations.IsInterfaceMethod (
358 MethodName, method.InterfaceType, new MethodData (method, ModFlags, flags, this));
359 if (mi != null) {
360 Report.SymbolRelatedToPreviousError (mi);
361 Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
362 method.GetSignatureForError (), mi.GetSignatureForError ());
365 return null;
368 TypeContainer container = parent.PartialContainer;
371 // Check for custom access modifier
373 if ((ModFlags & Modifiers.AccessibilityMask) == 0) {
374 ModFlags |= method.ModFlags;
375 flags = method.flags;
376 } else {
377 if (container.Kind == MemberKind.Interface)
378 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
379 GetSignatureForError ());
381 if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
382 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
385 CheckModifiers (ModFlags);
386 ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask));
387 ModFlags |= Modifiers.PROPERTY_CUSTOM;
388 flags = ModifiersExtensions.MethodAttr (ModFlags);
389 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
392 CheckAbstractAndExtern (block != null);
393 CheckProtectedModifier ();
395 if (block != null && block.IsIterator)
396 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
398 return null;
401 public bool HasCustomAccessModifier {
402 get {
403 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
407 public PropertyBase Property {
408 get {
409 return method;
413 public override ObsoleteAttribute GetAttributeObsolete ()
415 return method.GetAttributeObsolete ();
418 public override string GetSignatureForError()
420 return method.GetSignatureForError () + "." + prefix.Substring (0, 3);
423 void CheckModifiers (Modifiers modflags)
425 if (!ModifiersExtensions.IsRestrictedModifier (modflags & Modifiers.AccessibilityMask, method.ModFlags & Modifiers.AccessibilityMask)) {
426 Report.Error (273, Location,
427 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
428 GetSignatureForError (), method.GetSignatureForError ());
432 protected bool CheckForDuplications ()
434 if ((caching_flags & Flags.MethodOverloadsExist) == 0)
435 return true;
437 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParameterInfo);
441 public PropertyMethod Get, Set;
442 public PropertyBuilder PropertyBuilder;
443 public MethodBuilder GetBuilder, SetBuilder;
445 protected bool define_set_first = false;
447 public PropertyBase (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags,
448 Modifiers allowed_mod, MemberName name,
449 Attributes attrs, bool define_set_first)
450 : base (parent, null, type, mod_flags, allowed_mod, name, attrs)
452 this.define_set_first = define_set_first;
455 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
457 if (a.HasSecurityAttribute) {
458 a.Error_InvalidSecurityParent ();
459 return;
462 if (a.Type == pa.Dynamic) {
463 a.Error_MisusedDynamicAttribute ();
464 return;
467 PropertyBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
470 public override AttributeTargets AttributeTargets {
471 get {
472 return AttributeTargets.Property;
476 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
478 var ok = base.CheckOverrideAgainstBase (base_member);
481 // Check base property accessors conflict
483 var base_prop = (PropertySpec) base_member;
484 if (!Get.IsDummy) {
485 if (!base_prop.HasGet) {
486 Report.SymbolRelatedToPreviousError (base_prop);
487 Report.Error (545, Get.Location,
488 "`{0}': cannot override because `{1}' does not have an overridable get accessor",
489 Get.GetSignatureForError (), base_prop.GetSignatureForError ());
490 ok = false;
491 } else if (Get.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
492 if (!CheckAccessModifiers (Get, base_prop.Get)) {
493 Error_CannotChangeAccessModifiers (Get, base_prop.Get);
494 ok = false;
499 if (!Set.IsDummy) {
500 if (!base_prop.HasSet) {
501 Report.SymbolRelatedToPreviousError (base_prop);
502 Report.Error (546, Set.Location,
503 "`{0}': cannot override because `{1}' does not have an overridable set accessor",
504 Set.GetSignatureForError (), base_prop.GetSignatureForError ());
505 ok = false;
506 } else if (Set.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
507 if (!CheckAccessModifiers (Set, base_prop.Set)) {
508 Error_CannotChangeAccessModifiers (Set, base_prop.Set);
509 ok = false;
514 if (!Set.HasCustomAccessModifier && !Get.HasCustomAccessModifier) {
515 if (!CheckAccessModifiers (this, base_prop)) {
516 Error_CannotChangeAccessModifiers (this, base_prop);
517 ok = false;
521 return ok;
524 protected override void DoMemberTypeDependentChecks ()
526 base.DoMemberTypeDependentChecks ();
528 IsTypePermitted ();
530 if (MemberType.IsStatic)
531 Error_StaticReturnType ();
534 protected override void DoMemberTypeIndependentChecks ()
536 base.DoMemberTypeIndependentChecks ();
539 // Accessors modifiers check
541 if ((Get.ModFlags & Modifiers.AccessibilityMask) != 0 &&
542 (Set.ModFlags & Modifiers.AccessibilityMask) != 0) {
543 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
544 GetSignatureForError ());
547 if ((ModFlags & Modifiers.OVERRIDE) == 0 &&
548 (Get.IsDummy && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) ||
549 (Set.IsDummy && (Get.ModFlags & Modifiers.AccessibilityMask) != 0)) {
550 Report.Error (276, Location,
551 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
552 GetSignatureForError ());
556 bool DefineGet ()
558 GetBuilder = Get.Define (Parent);
559 return (Get.IsDummy) ? true : GetBuilder != null;
562 bool DefineSet (bool define)
564 if (!define)
565 return true;
567 SetBuilder = Set.Define (Parent);
568 return (Set.IsDummy) ? true : SetBuilder != null;
571 protected bool DefineAccessors ()
573 return DefineSet (define_set_first) &&
574 DefineGet () &&
575 DefineSet (!define_set_first);
578 protected void DefineBuilders (MemberKind kind, ParametersCompiled parameters)
580 // FIXME - PropertyAttributes.HasDefault ?
582 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
583 GetFullName (MemberName), PropertyAttributes.None, MemberType.GetMetaInfo (), parameters.GetMetaInfo ());
585 PropertySpec spec;
586 if (kind == MemberKind.Indexer)
587 spec = new IndexerSpec (Parent.Definition, this, MemberType, parameters, PropertyBuilder, ModFlags);
588 else
589 spec = new PropertySpec (kind, Parent.Definition, this, MemberType, PropertyBuilder, ModFlags);
591 spec.Get = Get.Spec;
592 spec.Set = Set.Spec;
594 if (!Get.IsDummy) {
595 PropertyBuilder.SetGetMethod (GetBuilder);
598 if (!Set.IsDummy) {
599 PropertyBuilder.SetSetMethod (SetBuilder);
602 Parent.MemberCache.AddMember (this, Get.IsDummy ? Get.Name : GetBuilder.Name, Get.Spec);
603 Parent.MemberCache.AddMember (this, Set.IsDummy ? Set.Name : SetBuilder.Name, Set.Spec);
604 Parent.MemberCache.AddMember (this, PropertyBuilder.Name, spec);
607 public override void Emit ()
610 // The PropertyBuilder can be null for explicit implementations, in that
611 // case, we do not actually emit the ".property", so there is nowhere to
612 // put the attribute
614 if (PropertyBuilder != null) {
615 if (OptAttributes != null)
616 OptAttributes.Emit ();
618 if (member_type == InternalType.Dynamic) {
619 PredefinedAttributes.Get.Dynamic.EmitAttribute (PropertyBuilder);
620 } else {
621 var trans_flags = TypeManager.HasDynamicTypeUsed (member_type);
622 if (trans_flags != null) {
623 var pa = PredefinedAttributes.Get.DynamicTransform;
624 if (pa.Constructor != null || pa.ResolveConstructor (Location, ArrayContainer.MakeType (TypeManager.bool_type))) {
625 PropertyBuilder.SetCustomAttribute (
626 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
632 if (!Get.IsDummy)
633 Get.Emit (Parent);
635 if (!Set.IsDummy)
636 Set.Emit (Parent);
638 base.Emit ();
641 /// <summary>
642 /// Tests whether accessors are not in collision with some method (CS0111)
643 /// </summary>
644 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
646 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
649 public override bool IsUsed {
650 get {
651 if (IsExplicitImpl)
652 return true;
654 return Get.IsUsed | Set.IsUsed;
658 protected override void SetMemberName (MemberName new_name)
660 base.SetMemberName (new_name);
662 Get.UpdateName (this);
663 Set.UpdateName (this);
666 public override string[] ValidAttributeTargets {
667 get {
668 return attribute_targets;
673 // Represents header string for documentation comment.
675 public override string DocCommentHeader {
676 get { return "P:"; }
680 public class Property : PropertyBase
682 public sealed class BackingField : Field
684 readonly Property property;
686 public BackingField (Property p)
687 : base (p.Parent, p.type_expr,
688 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
689 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
691 this.property = p;
694 public string OriginalName {
695 get {
696 return property.Name;
700 public override string GetSignatureForError ()
702 return property.GetSignatureForError ();
706 const Modifiers AllowedModifiers =
707 Modifiers.NEW |
708 Modifiers.PUBLIC |
709 Modifiers.PROTECTED |
710 Modifiers.INTERNAL |
711 Modifiers.PRIVATE |
712 Modifiers.STATIC |
713 Modifiers.SEALED |
714 Modifiers.OVERRIDE |
715 Modifiers.ABSTRACT |
716 Modifiers.UNSAFE |
717 Modifiers.EXTERN |
718 Modifiers.VIRTUAL;
720 const Modifiers AllowedInterfaceModifiers =
721 Modifiers.NEW;
723 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
724 MemberName name, Attributes attrs, Accessor get_block,
725 Accessor set_block, bool define_set_first)
726 : this (parent, type, mod, name, attrs, get_block, set_block,
727 define_set_first, null)
731 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
732 MemberName name, Attributes attrs, Accessor get_block,
733 Accessor set_block, bool define_set_first, Block current_block)
734 : base (parent, type, mod,
735 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
736 name, attrs, define_set_first)
738 if (get_block == null)
739 Get = new GetMethod (this);
740 else
741 Get = new GetMethod (this, get_block);
743 if (set_block == null)
744 Set = new SetMethod (this);
745 else
746 Set = new SetMethod (this, set_block);
748 if (!IsInterface && (mod & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
749 get_block != null && get_block.Block == null &&
750 set_block != null && set_block.Block == null) {
751 if (RootContext.Version <= LanguageVersion.ISO_2)
752 Report.FeatureIsNotAvailable (Location, "automatically implemented properties");
754 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
755 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
759 void CreateAutomaticProperty ()
761 // Create backing field
762 Field field = new BackingField (this);
763 if (!field.Define ())
764 return;
766 Parent.PartialContainer.AddField (field);
768 FieldExpr fe = new FieldExpr (field, Location);
769 if ((field.ModFlags & Modifiers.STATIC) == 0)
770 fe.InstanceExpression = new CompilerGeneratedThis (fe.Type, Location);
772 // Create get block
773 Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
774 Return r = new Return (fe, Location);
775 Get.Block.AddStatement (r);
777 // Create set block
778 Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location);
779 Assign a = new SimpleAssign (fe, new SimpleName ("value", Location));
780 Set.Block.AddStatement (new StatementExpression (a));
783 public override bool Define ()
785 if (!base.Define ())
786 return false;
788 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
790 if ((Get.ModFlags & Modifiers.COMPILER_GENERATED) != 0)
791 CreateAutomaticProperty ();
793 if (!DefineAccessors ())
794 return false;
796 if (!CheckBase ())
797 return false;
799 DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters);
800 return true;
803 public override void Emit ()
805 if (((Set.ModFlags | Get.ModFlags) & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
806 Report.Error (842, Location,
807 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
808 GetSignatureForError ());
811 base.Emit ();
815 /// <summary>
816 /// For case when event is declared like property (with add and remove accessors).
817 /// </summary>
818 public class EventProperty: Event {
819 abstract class AEventPropertyAccessor : AEventAccessor
821 protected AEventPropertyAccessor (EventProperty method, Accessor accessor, string prefix)
822 : base (method, accessor, prefix)
826 public override MethodBuilder Define (DeclSpace ds)
828 CheckAbstractAndExtern (block != null);
829 return base.Define (ds);
832 public override string GetSignatureForError ()
834 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
838 sealed class AddDelegateMethod: AEventPropertyAccessor
840 public AddDelegateMethod (EventProperty method, Accessor accessor):
841 base (method, accessor, AddPrefix)
846 sealed class RemoveDelegateMethod: AEventPropertyAccessor
848 public RemoveDelegateMethod (EventProperty method, Accessor accessor):
849 base (method, accessor, RemovePrefix)
855 static readonly string[] attribute_targets = new string [] { "event" };
857 public EventProperty (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags,
858 MemberName name,
859 Attributes attrs, Accessor add, Accessor remove)
860 : base (parent, type, mod_flags, name, attrs)
862 Add = new AddDelegateMethod (this, add);
863 Remove = new RemoveDelegateMethod (this, remove);
866 public override bool Define()
868 if (!base.Define ())
869 return false;
871 SetIsUsed ();
872 return true;
875 public override string[] ValidAttributeTargets {
876 get {
877 return attribute_targets;
882 /// <summary>
883 /// Event is declared like field.
884 /// </summary>
885 public class EventField : Event {
886 abstract class EventFieldAccessor : AEventAccessor
888 protected EventFieldAccessor (EventField method, string prefix)
889 : base (method, prefix)
893 public override void Emit (DeclSpace parent)
895 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
896 if (parent is Class) {
897 MethodBuilder mb = method_data.MethodBuilder;
898 mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | MethodImplAttributes.Synchronized);
901 var field_info = ((EventField) method).BackingField;
902 FieldExpr f_expr = new FieldExpr (field_info, Location);
903 if ((method.ModFlags & Modifiers.STATIC) == 0)
904 f_expr.InstanceExpression = new CompilerGeneratedThis (field_info.Spec.MemberType, Location);
906 block = new ToplevelBlock (Compiler, ParameterInfo, Location);
907 block.AddStatement (new StatementExpression (
908 new CompoundAssign (Operation,
909 f_expr,
910 block.GetParameterReference (ParameterInfo[0].Name, Location))));
913 base.Emit (parent);
916 protected abstract Binary.Operator Operation { get; }
919 sealed class AddDelegateMethod: EventFieldAccessor
921 public AddDelegateMethod (EventField method):
922 base (method, AddPrefix)
926 protected override Binary.Operator Operation {
927 get { return Binary.Operator.Addition; }
931 sealed class RemoveDelegateMethod: EventFieldAccessor
933 public RemoveDelegateMethod (EventField method):
934 base (method, RemovePrefix)
938 protected override Binary.Operator Operation {
939 get { return Binary.Operator.Subtraction; }
944 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
945 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
947 public Field BackingField;
948 public Expression Initializer;
950 public EventField (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
951 : base (parent, type, mod_flags, name, attrs)
953 Add = new AddDelegateMethod (this);
954 Remove = new RemoveDelegateMethod (this);
957 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
959 if (a.Target == AttributeTargets.Field) {
960 BackingField.ApplyAttributeBuilder (a, ctor, cdata, pa);
961 return;
964 if (a.Target == AttributeTargets.Method) {
965 int errors = Report.Errors;
966 Add.ApplyAttributeBuilder (a, ctor, cdata, pa);
967 if (errors == Report.Errors)
968 Remove.ApplyAttributeBuilder (a, ctor, cdata, pa);
969 return;
972 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
975 public override bool Define()
977 if (!base.Define ())
978 return false;
980 if (Initializer != null && (ModFlags & Modifiers.ABSTRACT) != 0) {
981 Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
982 GetSignatureForError ());
985 if (!HasBackingField) {
986 SetIsUsed ();
987 return true;
990 // FIXME: We are unable to detect whether generic event is used because
991 // we are using FieldExpr instead of EventExpr for event access in that
992 // case. When this issue will be fixed this hack can be removed.
993 if (TypeManager.IsGenericType (MemberType) || Parent.IsGeneric)
994 SetIsUsed ();
996 if (Add.IsInterfaceImplementation)
997 SetIsUsed ();
999 BackingField = new Field (Parent,
1000 new TypeExpression (MemberType, Location),
1001 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
1002 MemberName, null);
1004 Parent.PartialContainer.AddField (BackingField);
1005 BackingField.Initializer = Initializer;
1006 BackingField.ModFlags &= ~Modifiers.COMPILER_GENERATED;
1008 // Call define because we passed fields definition
1009 return BackingField.Define ();
1012 public bool HasBackingField {
1013 get {
1014 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
1018 public override string[] ValidAttributeTargets {
1019 get {
1020 return HasBackingField ? attribute_targets : attribute_targets_interface;
1025 public abstract class Event : PropertyBasedMember {
1026 public abstract class AEventAccessor : AbstractPropertyEventMethod
1028 protected readonly Event method;
1029 ImplicitParameter param_attr;
1030 ParametersCompiled parameters;
1032 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
1034 public const string AddPrefix = "add_";
1035 public const string RemovePrefix = "remove_";
1037 protected AEventAccessor (Event method, string prefix)
1038 : base (method, prefix)
1040 this.method = method;
1041 this.ModFlags = method.ModFlags;
1042 this.parameters = ParametersCompiled.CreateImplicitParameter (method.type_expr, Location);
1045 protected AEventAccessor (Event method, Accessor accessor, string prefix)
1046 : base (method, accessor, prefix)
1048 this.method = method;
1049 this.ModFlags = method.ModFlags;
1050 this.parameters = accessor.Parameters;
1053 public bool IsInterfaceImplementation {
1054 get { return method_data.implementing != null; }
1057 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1059 if (a.IsInternalMethodImplAttribute) {
1060 method.is_external_implementation = true;
1063 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1066 protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1068 if (a.Target == AttributeTargets.Parameter) {
1069 if (param_attr == null)
1070 param_attr = new ImplicitParameter (method_data.MethodBuilder);
1072 param_attr.ApplyAttributeBuilder (a, ctor, cdata, pa);
1073 return;
1076 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1079 public override AttributeTargets AttributeTargets {
1080 get {
1081 return AttributeTargets.Method;
1085 public override bool IsClsComplianceRequired ()
1087 return method.IsClsComplianceRequired ();
1090 public virtual MethodBuilder Define (DeclSpace parent)
1092 parameters.Resolve (this);
1094 method_data = new MethodData (method, method.ModFlags,
1095 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
1097 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
1098 return null;
1100 MethodBuilder mb = method_data.MethodBuilder;
1101 ParameterInfo.ApplyAttributes (mb);
1102 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, mb, ParameterInfo, method.ModFlags);
1103 Spec.IsAccessor = true;
1105 return mb;
1108 public override TypeSpec ReturnType {
1109 get {
1110 return TypeManager.void_type;
1114 public override ObsoleteAttribute GetAttributeObsolete ()
1116 return method.GetAttributeObsolete ();
1119 public override string[] ValidAttributeTargets {
1120 get {
1121 return attribute_targets;
1125 public override ParametersCompiled ParameterInfo {
1126 get {
1127 return parameters;
1133 const Modifiers AllowedModifiers =
1134 Modifiers.NEW |
1135 Modifiers.PUBLIC |
1136 Modifiers.PROTECTED |
1137 Modifiers.INTERNAL |
1138 Modifiers.PRIVATE |
1139 Modifiers.STATIC |
1140 Modifiers.VIRTUAL |
1141 Modifiers.SEALED |
1142 Modifiers.OVERRIDE |
1143 Modifiers.UNSAFE |
1144 Modifiers.ABSTRACT |
1145 Modifiers.EXTERN;
1147 const Modifiers AllowedInterfaceModifiers =
1148 Modifiers.NEW;
1150 public AEventAccessor Add, Remove;
1151 public EventBuilder EventBuilder;
1152 public MethodBuilder AddBuilder, RemoveBuilder;
1154 protected Event (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1155 : base (parent, null, type, mod_flags,
1156 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1157 name, attrs)
1161 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1163 if ((a.HasSecurityAttribute)) {
1164 a.Error_InvalidSecurityParent ();
1165 return;
1168 EventBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1171 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
1173 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
1176 public override AttributeTargets AttributeTargets {
1177 get {
1178 return AttributeTargets.Event;
1182 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
1184 var ok = base.CheckOverrideAgainstBase (base_member);
1186 if (!CheckAccessModifiers (this, base_member)) {
1187 Error_CannotChangeAccessModifiers (this, base_member);
1188 ok = false;
1191 return ok;
1194 public override bool Define ()
1196 if (!base.Define ())
1197 return false;
1199 if (!TypeManager.IsDelegateType (MemberType)) {
1200 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
1203 if (!CheckBase ())
1204 return false;
1207 // Now define the accessors
1209 AddBuilder = Add.Define (Parent);
1210 if (AddBuilder == null)
1211 return false;
1213 RemoveBuilder = Remove.Define (Parent);
1214 if (RemoveBuilder == null)
1215 return false;
1217 EventBuilder = Parent.TypeBuilder.DefineEvent (Name, EventAttributes.None, MemberType.GetMetaInfo ());
1218 EventBuilder.SetAddOnMethod (AddBuilder);
1219 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
1221 var spec = new EventSpec (Parent.Definition, this, MemberType, ModFlags, Add.Spec, Remove.Spec);
1223 Parent.MemberCache.AddMember (this, Name, spec);
1224 Parent.MemberCache.AddMember (this, AddBuilder.Name, Add.Spec);
1225 Parent.MemberCache.AddMember (this, RemoveBuilder.Name, Remove.Spec);
1227 return true;
1230 public override void Emit ()
1232 if (OptAttributes != null) {
1233 OptAttributes.Emit ();
1236 Add.Emit (Parent);
1237 Remove.Emit (Parent);
1239 base.Emit ();
1243 // Represents header string for documentation comment.
1245 public override string DocCommentHeader {
1246 get { return "E:"; }
1250 public class EventSpec : MemberSpec, IInterfaceMemberSpec
1252 MethodSpec add, remove;
1254 public EventSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec eventType, Modifiers modifiers, MethodSpec add, MethodSpec remove)
1255 : base (MemberKind.Event, declaringType, definition, modifiers)
1257 this.AccessorAdd = add;
1258 this.AccessorRemove = remove;
1259 this.MemberType = eventType;
1262 #region Properties
1264 public MethodSpec AccessorAdd {
1265 get {
1266 return add;
1268 set {
1269 add = value;
1273 public MethodSpec AccessorRemove {
1274 get {
1275 return remove;
1277 set {
1278 remove = value;
1282 public TypeSpec MemberType { get; private set; }
1284 #endregion
1286 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1288 var es = (EventSpec) base.InflateMember (inflator);
1289 es.MemberType = inflator.Inflate (MemberType);
1290 return es;
1294 public class Indexer : PropertyBase, IParametersMember
1296 public class GetIndexerMethod : GetMethod, IParametersMember
1298 ParametersCompiled parameters;
1300 public GetIndexerMethod (Indexer method):
1301 base (method)
1303 this.parameters = method.parameters;
1306 public GetIndexerMethod (PropertyBase method, Accessor accessor):
1307 base (method, accessor)
1309 parameters = accessor.Parameters;
1312 public override MethodBuilder Define (DeclSpace parent)
1314 parameters.Resolve (this);
1315 return base.Define (parent);
1318 public override bool EnableOverloadChecks (MemberCore overload)
1320 if (base.EnableOverloadChecks (overload)) {
1321 overload.caching_flags |= Flags.MethodOverloadsExist;
1322 return true;
1325 return false;
1328 public override ParametersCompiled ParameterInfo {
1329 get {
1330 return parameters;
1334 #region IParametersMember Members
1336 AParametersCollection IParametersMember.Parameters {
1337 get {
1338 return parameters;
1342 TypeSpec IInterfaceMemberSpec.MemberType {
1343 get {
1344 return ReturnType;
1348 #endregion
1351 public class SetIndexerMethod : SetMethod, IParametersMember
1353 public SetIndexerMethod (Indexer method):
1354 base (method)
1356 parameters = ParametersCompiled.MergeGenerated (Compiler, method.parameters, false, parameters [0], null);
1359 public SetIndexerMethod (PropertyBase method, Accessor accessor):
1360 base (method, accessor)
1362 parameters = method.Get.IsDummy ? accessor.Parameters : accessor.Parameters.Clone ();
1365 public override bool EnableOverloadChecks (MemberCore overload)
1367 if (base.EnableOverloadChecks (overload)) {
1368 overload.caching_flags |= Flags.MethodOverloadsExist;
1369 return true;
1372 return false;
1375 #region IParametersMember Members
1377 AParametersCollection IParametersMember.Parameters {
1378 get {
1379 return parameters;
1383 TypeSpec IInterfaceMemberSpec.MemberType {
1384 get {
1385 return ReturnType;
1389 #endregion
1392 const Modifiers AllowedModifiers =
1393 Modifiers.NEW |
1394 Modifiers.PUBLIC |
1395 Modifiers.PROTECTED |
1396 Modifiers.INTERNAL |
1397 Modifiers.PRIVATE |
1398 Modifiers.VIRTUAL |
1399 Modifiers.SEALED |
1400 Modifiers.OVERRIDE |
1401 Modifiers.UNSAFE |
1402 Modifiers.EXTERN |
1403 Modifiers.ABSTRACT;
1405 const Modifiers AllowedInterfaceModifiers =
1406 Modifiers.NEW;
1408 readonly ParametersCompiled parameters;
1410 public Indexer (DeclSpace parent, FullNamedExpression type, MemberName name, Modifiers mod,
1411 ParametersCompiled parameters, Attributes attrs,
1412 Accessor get_block, Accessor set_block, bool define_set_first)
1413 : base (parent, type, mod,
1414 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1415 name, attrs, define_set_first)
1417 this.parameters = parameters;
1419 if (get_block == null)
1420 Get = new GetIndexerMethod (this);
1421 else
1422 Get = new GetIndexerMethod (this, get_block);
1424 if (set_block == null)
1425 Set = new SetIndexerMethod (this);
1426 else
1427 Set = new SetIndexerMethod (this, set_block);
1430 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1432 if (a.Type == pa.IndexerName) {
1433 if (IsExplicitImpl) {
1434 Report.Error (415, a.Location,
1435 "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration",
1436 TypeManager.CSharpName (a.Type));
1439 // Attribute was copied to container
1440 return;
1443 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1446 protected override bool CheckForDuplications ()
1448 return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1451 public override bool Define ()
1453 if (!base.Define ())
1454 return false;
1456 if (!DefineParameters (parameters))
1457 return false;
1459 if (OptAttributes != null) {
1460 Attribute indexer_attr = OptAttributes.Search (PredefinedAttributes.Get.IndexerName);
1461 if (indexer_attr != null) {
1462 var compiling = indexer_attr.Type.MemberDefinition as TypeContainer;
1463 if (compiling != null)
1464 compiling.Define ();
1466 string name = indexer_attr.GetIndexerAttributeValue ();
1467 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1468 Report.Error (609, indexer_attr.Location,
1469 "Cannot set the `IndexerName' attribute on an indexer marked override");
1472 if (!string.IsNullOrEmpty (name))
1473 ShortName = name;
1477 if (InterfaceType != null) {
1478 string base_IndexerName = InterfaceType.MemberDefinition.GetAttributeDefaultMember ();
1479 if (base_IndexerName != Name)
1480 ShortName = base_IndexerName;
1483 if (!Parent.PartialContainer.AddMember (this) ||
1484 !Parent.PartialContainer.AddMember (Get) || !Parent.PartialContainer.AddMember (Set))
1485 return false;
1487 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1489 if (!DefineAccessors ())
1490 return false;
1492 if (!CheckBase ())
1493 return false;
1495 DefineBuilders (MemberKind.Indexer, parameters);
1496 return true;
1499 public override bool EnableOverloadChecks (MemberCore overload)
1501 if (overload is Indexer) {
1502 caching_flags |= Flags.MethodOverloadsExist;
1503 return true;
1506 return base.EnableOverloadChecks (overload);
1509 public override string GetDocCommentName (DeclSpace ds)
1511 return DocUtil.GetMethodDocCommentName (this, parameters, ds);
1514 public override string GetSignatureForError ()
1516 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
1517 if (MemberName.Left != null) {
1518 sb.Append ('.');
1519 sb.Append (MemberName.Left.GetSignatureForError ());
1522 sb.Append (".this");
1523 sb.Append (parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
1524 return sb.ToString ();
1527 public AParametersCollection Parameters {
1528 get {
1529 return parameters;
1533 public ParametersCompiled ParameterInfo {
1534 get {
1535 return parameters;
1539 protected override bool VerifyClsCompliance ()
1541 if (!base.VerifyClsCompliance ())
1542 return false;
1544 parameters.VerifyClsCompliance (this);
1545 return true;
1549 public class IndexerSpec : PropertySpec, IParametersMember
1551 AParametersCollection parameters;
1553 public IndexerSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, AParametersCollection parameters, PropertyInfo info, Modifiers modifiers)
1554 : base (MemberKind.Indexer, declaringType, definition, memberType, info, modifiers)
1556 this.parameters = parameters;
1559 public override string GetSignatureForError ()
1561 return DeclaringType.GetSignatureForError () + ".this" + parameters.GetSignatureForError ("[", "]", parameters.Count);
1564 public AParametersCollection Parameters {
1565 get {
1566 return parameters;