2 // property.cs: Property based handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
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
;
25 using XmlElement
= System
.Object
;
30 using Mono
.CompilerServices
.SymbolWriter
;
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 ())
50 if (!MemberType
.IsCLSCompliant ()) {
51 Report
.Warning (3003, 1, Location
, "Type of `{0}' is not CLS-compliant",
52 GetSignatureForError ());
60 // `set' and `get' accessors are represented with an Accessor.
62 public class Accessor
{
64 // Null if the accessor is empty, or a Block if not
66 public const Modifiers AllowedModifiers
=
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
)
84 ModFlags
= ModifiersExtensions
.Check (AllowedModifiers
, mod
, 0, loc
, RootContext
.ToplevelTypes
.Compiler
.Report
);
88 public class PropertySpec
: MemberSpec
, IInterfaceMemberSpec
94 public PropertySpec (MemberKind kind
, TypeSpec declaringType
, IMemberDefinition definition
, TypeSpec memberType
, PropertyInfo info
, Modifiers modifiers
)
95 : base (kind
, declaringType
, definition
, modifiers
)
98 this.memberType
= memberType
;
103 public MethodSpec Get
{
109 get.IsAccessor
= true;
113 public MethodSpec Set
{
119 set.IsAccessor
= true;
123 public bool IsNotRealProperty
{
125 return (state
& StateFlags
.IsNotRealProperty
) != 0;
128 state
|= StateFlags
.IsNotRealProperty
;
132 public bool HasDifferentAccessibility
{
134 return HasGet
&& HasSet
&&
135 (Get
.Modifiers
& Modifiers
.AccessibilityMask
) != (Set
.Modifiers
& Modifiers
.AccessibilityMask
);
141 return Get
!= null && Get
.Kind
!= MemberKind
.FakeMethod
;
147 return Set
!= null && Set
.Kind
!= MemberKind
.FakeMethod
;
151 public PropertyInfo MetaInfo
{
153 if ((state
& StateFlags
.PendingMetaInflate
) != 0)
154 throw new NotSupportedException ();
160 public TypeSpec MemberType
{
168 public override MemberSpec
InflateMember (TypeParameterInflator inflator
)
170 var ps
= (PropertySpec
) base.InflateMember (inflator
);
171 ps
.memberType
= inflator
.Inflate (memberType
);
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
);
205 method_data
= new MethodData (method
, ModFlags
, flags
, this);
207 if (!method_data
.Define (parent
, method
.GetFullName (MemberName
), Report
))
210 Spec
.SetMetaInfo (method_data
.MethodBuilder
);
212 return method_data
.MethodBuilder
;
215 public override TypeSpec ReturnType
{
217 return method
.MemberType
;
221 public override ParametersCompiled ParameterInfo
{
223 return ParametersCompiled
.EmptyReadOnlyParameters
;
227 public override string[] ValidAttributeTargets
{
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
);
262 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
265 public override ParametersCompiled ParameterInfo
{
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
);
282 method_data
= new MethodData (method
, ModFlags
, flags
, this);
284 if (!method_data
.Define (parent
, method
.GetFullName (MemberName
), Report
))
287 Spec
.SetMetaInfo (method_data
.MethodBuilder
);
289 return method_data
.MethodBuilder
;
292 public override TypeSpec ReturnType
{
294 return TypeManager
.void_type
;
298 public override string[] ValidAttributeTargets
{
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
,
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
{
342 return AttributeTargets
.Method
;
346 public override bool IsClsComplianceRequired ()
348 return method
.IsClsComplianceRequired ();
351 public virtual MethodBuilder
Define (DeclSpace parent
)
353 CheckForDuplications ();
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));
360 Report
.SymbolRelatedToPreviousError (mi
);
361 Report
.Error (551, Location
, "Explicit interface implementation `{0}' is missing accessor `{1}'",
362 method
.GetSignatureForError (), mi
.GetSignatureForError ());
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
;
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
);
401 public bool HasCustomAccessModifier
{
403 return (ModFlags
& Modifiers
.PROPERTY_CUSTOM
) != 0;
407 public PropertyBase Property
{
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)
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 ();
462 if (a
.Type
== pa
.Dynamic
) {
463 a
.Error_MisusedDynamicAttribute ();
467 PropertyBuilder
.SetCustomAttribute ((ConstructorInfo
) ctor
.GetMetaInfo (), cdata
);
470 public override AttributeTargets AttributeTargets
{
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
;
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 ());
491 } else if (Get
.HasCustomAccessModifier
|| base_prop
.HasDifferentAccessibility
) {
492 if (!CheckAccessModifiers (Get
, base_prop
.Get
)) {
493 Error_CannotChangeAccessModifiers (Get
, base_prop
.Get
);
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 ());
506 } else if (Set
.HasCustomAccessModifier
|| base_prop
.HasDifferentAccessibility
) {
507 if (!CheckAccessModifiers (Set
, base_prop
.Set
)) {
508 Error_CannotChangeAccessModifiers (Set
, base_prop
.Set
);
514 if (!Set
.HasCustomAccessModifier
&& !Get
.HasCustomAccessModifier
) {
515 if (!CheckAccessModifiers (this, base_prop
)) {
516 Error_CannotChangeAccessModifiers (this, base_prop
);
524 protected override void DoMemberTypeDependentChecks ()
526 base.DoMemberTypeDependentChecks ();
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 ());
558 GetBuilder
= Get
.Define (Parent
);
559 return (Get
.IsDummy
) ? true : GetBuilder
!= null;
562 bool DefineSet (bool define
)
567 SetBuilder
= Set
.Define (Parent
);
568 return (Set
.IsDummy
) ? true : SetBuilder
!= null;
571 protected bool DefineAccessors ()
573 return DefineSet (define_set_first
) &&
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 ());
586 if (kind
== MemberKind
.Indexer
)
587 spec
= new IndexerSpec (Parent
.Definition
, this, MemberType
, parameters
, PropertyBuilder
, ModFlags
);
589 spec
= new PropertySpec (kind
, Parent
.Definition
, this, MemberType
, PropertyBuilder
, ModFlags
);
595 PropertyBuilder
.SetGetMethod (GetBuilder
);
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
614 if (PropertyBuilder
!= null) {
615 if (OptAttributes
!= null)
616 OptAttributes
.Emit ();
618 if (member_type
== InternalType
.Dynamic
) {
619 PredefinedAttributes
.Get
.Dynamic
.EmitAttribute (PropertyBuilder
);
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 }
));
642 /// Tests whether accessors are not in collision with some method (CS0111)
644 public bool AreAccessorsDuplicateImplementation (MethodCore mc
)
646 return Get
.IsDuplicateImplementation (mc
) || Set
.IsDuplicateImplementation (mc
);
649 public override bool IsUsed
{
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
{
668 return attribute_targets
;
673 // Represents header string for documentation comment.
675 public override string DocCommentHeader
{
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)
694 public string OriginalName
{
696 return property
.Name
;
700 public override string GetSignatureForError ()
702 return property
.GetSignatureForError ();
706 const Modifiers AllowedModifiers
=
709 Modifiers
.PROTECTED
|
720 const Modifiers AllowedInterfaceModifiers
=
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);
741 Get
= new GetMethod (this, get_block
);
743 if (set_block
== null)
744 Set
= new SetMethod (this);
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 ())
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
);
773 Get
.Block
= new ToplevelBlock (Compiler
, ParametersCompiled
.EmptyReadOnlyParameters
, Location
);
774 Return r
= new Return (fe
, Location
);
775 Get
.Block
.AddStatement (r
);
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 ()
788 flags
|= MethodAttributes
.HideBySig
| MethodAttributes
.SpecialName
;
790 if ((Get
.ModFlags
& Modifiers
.COMPILER_GENERATED
) != 0)
791 CreateAutomaticProperty ();
793 if (!DefineAccessors ())
799 DefineBuilders (MemberKind
.Property
, ParametersCompiled
.EmptyReadOnlyParameters
);
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 ());
816 /// For case when event is declared like property (with add and remove accessors).
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
,
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()
875 public override string[] ValidAttributeTargets
{
877 return attribute_targets
;
883 /// Event is declared like field.
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
,
910 block
.GetParameterReference (ParameterInfo
[0].Name
, Location
))));
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
);
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
);
972 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
975 public override bool Define()
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
) {
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
)
996 if (Add
.IsInterfaceImplementation
)
999 BackingField
= new Field (Parent
,
1000 new TypeExpression (MemberType
, Location
),
1001 Modifiers
.BACKING_FIELD
| Modifiers
.COMPILER_GENERATED
| Modifiers
.PRIVATE
| (ModFlags
& (Modifiers
.STATIC
| Modifiers
.UNSAFE
)),
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
{
1014 return !IsInterface
&& (ModFlags
& Modifiers
.ABSTRACT
) == 0;
1018 public override string[] ValidAttributeTargets
{
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
);
1076 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
1079 public override AttributeTargets AttributeTargets
{
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
))
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;
1108 public override TypeSpec ReturnType
{
1110 return TypeManager
.void_type
;
1114 public override ObsoleteAttribute
GetAttributeObsolete ()
1116 return method
.GetAttributeObsolete ();
1119 public override string[] ValidAttributeTargets
{
1121 return attribute_targets
;
1125 public override ParametersCompiled ParameterInfo
{
1133 const Modifiers AllowedModifiers
=
1136 Modifiers
.PROTECTED
|
1137 Modifiers
.INTERNAL
|
1142 Modifiers
.OVERRIDE
|
1144 Modifiers
.ABSTRACT
|
1147 const Modifiers AllowedInterfaceModifiers
=
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
,
1161 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
1163 if ((a
.HasSecurityAttribute
)) {
1164 a
.Error_InvalidSecurityParent ();
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
{
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
);
1194 public override bool Define ()
1196 if (!base.Define ())
1199 if (!TypeManager
.IsDelegateType (MemberType
)) {
1200 Report
.Error (66, Location
, "`{0}': event must be of a delegate type", GetSignatureForError ());
1207 // Now define the accessors
1209 AddBuilder
= Add
.Define (Parent
);
1210 if (AddBuilder
== null)
1213 RemoveBuilder
= Remove
.Define (Parent
);
1214 if (RemoveBuilder
== null)
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
);
1230 public override void Emit ()
1232 if (OptAttributes
!= null) {
1233 OptAttributes
.Emit ();
1237 Remove
.Emit (Parent
);
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
;
1264 public MethodSpec AccessorAdd
{
1273 public MethodSpec AccessorRemove
{
1282 public TypeSpec MemberType { get; private set; }
1286 public override MemberSpec
InflateMember (TypeParameterInflator inflator
)
1288 var es
= (EventSpec
) base.InflateMember (inflator
);
1289 es
.MemberType
= inflator
.Inflate (MemberType
);
1294 public class Indexer
: PropertyBase
, IParametersMember
1296 public class GetIndexerMethod
: GetMethod
, IParametersMember
1298 ParametersCompiled parameters
;
1300 public GetIndexerMethod (Indexer 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
;
1328 public override ParametersCompiled ParameterInfo
{
1334 #region IParametersMember Members
1336 AParametersCollection IParametersMember
.Parameters
{
1342 TypeSpec IInterfaceMemberSpec
.MemberType
{
1351 public class SetIndexerMethod
: SetMethod
, IParametersMember
1353 public SetIndexerMethod (Indexer 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
;
1375 #region IParametersMember Members
1377 AParametersCollection IParametersMember
.Parameters
{
1383 TypeSpec IInterfaceMemberSpec
.MemberType
{
1392 const Modifiers AllowedModifiers
=
1395 Modifiers
.PROTECTED
|
1396 Modifiers
.INTERNAL
|
1400 Modifiers
.OVERRIDE
|
1405 const Modifiers AllowedInterfaceModifiers
=
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);
1422 Get
= new GetIndexerMethod (this, get_block
);
1424 if (set_block
== null)
1425 Set
= new SetIndexerMethod (this);
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
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 ())
1456 if (!DefineParameters (parameters
))
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
))
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
))
1487 flags
|= MethodAttributes
.HideBySig
| MethodAttributes
.SpecialName
;
1489 if (!DefineAccessors ())
1495 DefineBuilders (MemberKind
.Indexer
, parameters
);
1499 public override bool EnableOverloadChecks (MemberCore overload
)
1501 if (overload
is Indexer
) {
1502 caching_flags
|= Flags
.MethodOverloadsExist
;
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) {
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
{
1533 public ParametersCompiled ParameterInfo
{
1539 protected override bool VerifyClsCompliance ()
1541 if (!base.VerifyClsCompliance ())
1544 parameters
.VerifyClsCompliance (this);
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
{