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 void CheckReservedNameConflict (string prefix
, MethodSpec accessor
)
48 AParametersCollection parameters
;
49 if (accessor
!= null) {
51 parameters
= accessor
.Parameters
;
53 name
= prefix
+ ShortName
;
55 name
= MemberName
.Left
+ "." + name
;
57 if (this is Indexer
) {
58 parameters
= ((Indexer
) this).ParameterInfo
;
59 if (prefix
[0] == 's') {
60 var data
= new IParameterData
[parameters
.Count
+ 1];
61 Array
.Copy (parameters
.FixedParameters
, data
, data
.Length
- 1);
62 data
[data
.Length
- 1] = new ParameterData ("value", Parameter
.Modifier
.NONE
);
63 var types
= new TypeSpec
[data
.Length
];
64 Array
.Copy (parameters
.Types
, types
, data
.Length
- 1);
65 types
[data
.Length
- 1] = member_type
;
67 parameters
= new ParametersImported (data
, types
);
71 parameters
= ParametersCompiled
.CreateFullyResolved (new[] { member_type }
);
73 parameters
= ParametersCompiled
.EmptyReadOnlyParameters
;
77 var conflict
= MemberCache
.FindMember (Parent
.Definition
,
78 new MemberFilter (name
, 0, MemberKind
.Method
, parameters
, null),
79 BindingRestriction
.DeclaredOnly
| BindingRestriction
.NoAccessors
);
81 if (conflict
!= null) {
82 Report
.SymbolRelatedToPreviousError (conflict
);
83 Report
.Error (82, Location
, "A member `{0}' is already reserved", conflict
.GetSignatureForError ());
87 protected override bool VerifyClsCompliance ()
89 if (!base.VerifyClsCompliance ())
92 if (!MemberType
.IsCLSCompliant ()) {
93 Report
.Warning (3003, 1, Location
, "Type of `{0}' is not CLS-compliant",
94 GetSignatureForError ());
101 public class PropertySpec
: MemberSpec
, IInterfaceMemberSpec
107 public PropertySpec (MemberKind kind
, TypeSpec declaringType
, IMemberDefinition definition
, TypeSpec memberType
, PropertyInfo info
, Modifiers modifiers
)
108 : base (kind
, declaringType
, definition
, modifiers
)
111 this.memberType
= memberType
;
116 public MethodSpec Get
{
122 get.IsAccessor
= true;
126 public MethodSpec Set
{
132 set.IsAccessor
= true;
136 public bool IsNotRealProperty
{
138 return (state
& StateFlags
.IsNotRealProperty
) != 0;
141 state
|= StateFlags
.IsNotRealProperty
;
145 public bool HasDifferentAccessibility
{
147 return HasGet
&& HasSet
&&
148 (Get
.Modifiers
& Modifiers
.AccessibilityMask
) != (Set
.Modifiers
& Modifiers
.AccessibilityMask
);
164 public PropertyInfo MetaInfo
{
166 if ((state
& StateFlags
.PendingMetaInflate
) != 0)
167 throw new NotSupportedException ();
173 public TypeSpec MemberType
{
181 public override MemberSpec
InflateMember (TypeParameterInflator inflator
)
183 var ps
= (PropertySpec
) base.InflateMember (inflator
);
184 ps
.memberType
= inflator
.Inflate (memberType
);
190 // Properties and Indexers both generate PropertyBuilders, we use this to share
191 // their common bits.
193 abstract public class PropertyBase
: PropertyBasedMember
{
195 public class GetMethod
: PropertyMethod
197 static string[] attribute_targets
= new string [] { "method", "return" }
;
199 internal const string Prefix
= "get_";
201 public GetMethod (PropertyBase method
, Modifiers modifiers
, Attributes attrs
, Location loc
)
202 : base (method
, Prefix
, modifiers
, attrs
, loc
)
206 public override MethodBuilder
Define (DeclSpace parent
)
208 base.Define (parent
);
210 Spec
= new MethodSpec (MemberKind
.Method
, parent
.PartialContainer
.Definition
, this, ReturnType
, null, ParameterInfo
, ModFlags
);
212 method_data
= new MethodData (method
, ModFlags
, flags
, this);
214 if (!method_data
.Define (parent
, method
.GetFullName (MemberName
), Report
))
217 Spec
.SetMetaInfo (method_data
.MethodBuilder
);
219 return method_data
.MethodBuilder
;
222 public override TypeSpec ReturnType
{
224 return method
.MemberType
;
228 public override ParametersCompiled ParameterInfo
{
230 return ParametersCompiled
.EmptyReadOnlyParameters
;
234 public override string[] ValidAttributeTargets
{
236 return attribute_targets
;
241 public class SetMethod
: PropertyMethod
{
243 static string[] attribute_targets
= new string [] { "method", "param", "return" }
;
245 internal const string Prefix
= "set_";
247 ImplicitParameter param_attr
;
248 protected ParametersCompiled parameters
;
250 public SetMethod (PropertyBase method
, Modifiers modifiers
, ParametersCompiled parameters
, Attributes attrs
, Location loc
)
251 : base (method
, Prefix
, modifiers
, attrs
, loc
)
253 this.parameters
= parameters
;
256 protected override void ApplyToExtraTarget (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
258 if (a
.Target
== AttributeTargets
.Parameter
) {
259 if (param_attr
== null)
260 param_attr
= new ImplicitParameter (method_data
.MethodBuilder
);
262 param_attr
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
266 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
269 public override ParametersCompiled ParameterInfo
{
275 public override MethodBuilder
Define (DeclSpace parent
)
277 parameters
.Resolve (this);
279 base.Define (parent
);
281 Spec
= new MethodSpec (MemberKind
.Method
, parent
.PartialContainer
.Definition
, this, ReturnType
, null, ParameterInfo
, ModFlags
);
283 method_data
= new MethodData (method
, ModFlags
, flags
, this);
285 if (!method_data
.Define (parent
, method
.GetFullName (MemberName
), Report
))
288 Spec
.SetMetaInfo (method_data
.MethodBuilder
);
290 return method_data
.MethodBuilder
;
293 public override TypeSpec ReturnType
{
295 return TypeManager
.void_type
;
299 public override string[] ValidAttributeTargets
{
301 return attribute_targets
;
306 static string[] attribute_targets
= new string [] { "property" }
;
308 public abstract class PropertyMethod
: AbstractPropertyEventMethod
310 public const Modifiers AllowedModifiers
=
312 Modifiers
.PROTECTED
|
316 protected readonly PropertyBase method
;
317 protected MethodAttributes flags
;
319 public PropertyMethod (PropertyBase method
, string prefix
, Modifiers modifiers
, Attributes attrs
, Location loc
)
320 : base (method
, prefix
, attrs
, loc
)
322 this.method
= method
;
323 this.ModFlags
= modifiers
| (method
.ModFlags
& (Modifiers
.STATIC
| Modifiers
.UNSAFE
));
326 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
328 if (a
.IsInternalMethodImplAttribute
) {
329 method
.is_external_implementation
= true;
332 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
335 public override AttributeTargets AttributeTargets
{
337 return AttributeTargets
.Method
;
341 public override bool IsClsComplianceRequired ()
343 return method
.IsClsComplianceRequired ();
346 public virtual MethodBuilder
Define (DeclSpace parent
)
348 TypeContainer container
= parent
.PartialContainer
;
351 // Check for custom access modifier
353 if ((ModFlags
& Modifiers
.AccessibilityMask
) == 0) {
354 ModFlags
|= method
.ModFlags
;
355 flags
= method
.flags
;
357 if (container
.Kind
== MemberKind
.Interface
)
358 Report
.Error (275, Location
, "`{0}': accessibility modifiers may not be used on accessors in an interface",
359 GetSignatureForError ());
361 if ((method
.ModFlags
& Modifiers
.ABSTRACT
) != 0 && (ModFlags
& Modifiers
.PRIVATE
) != 0) {
362 Report
.Error (442, Location
, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
365 CheckModifiers (ModFlags
);
366 ModFlags
|= (method
.ModFlags
& (~Modifiers
.AccessibilityMask
));
367 ModFlags
|= Modifiers
.PROPERTY_CUSTOM
;
368 flags
= ModifiersExtensions
.MethodAttr (ModFlags
);
369 flags
|= (method
.flags
& (~MethodAttributes
.MemberAccessMask
));
372 CheckAbstractAndExtern (block
!= null);
373 CheckProtectedModifier ();
375 if (block
!= null && block
.IsIterator
)
376 Iterator
.CreateIterator (this, Parent
.PartialContainer
, ModFlags
, Compiler
);
381 public bool HasCustomAccessModifier
{
383 return (ModFlags
& Modifiers
.PROPERTY_CUSTOM
) != 0;
387 public PropertyBase Property
{
393 public override ObsoleteAttribute
GetAttributeObsolete ()
395 return method
.GetAttributeObsolete ();
398 public override string GetSignatureForError()
400 return method
.GetSignatureForError () + "." + prefix
.Substring (0, 3);
403 void CheckModifiers (Modifiers modflags
)
405 if (!ModifiersExtensions
.IsRestrictedModifier (modflags
& Modifiers
.AccessibilityMask
, method
.ModFlags
& Modifiers
.AccessibilityMask
)) {
406 Report
.Error (273, Location
,
407 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
408 GetSignatureForError (), method
.GetSignatureForError ());
413 PropertyMethod
get, set, first
;
414 PropertyBuilder PropertyBuilder
;
416 public PropertyBase (DeclSpace parent
, FullNamedExpression type
, Modifiers mod_flags
,
417 Modifiers allowed_mod
, MemberName name
, Attributes attrs
)
418 : base (parent
, null, type
, mod_flags
, allowed_mod
, name
, attrs
)
424 public override AttributeTargets AttributeTargets
{
426 return AttributeTargets
.Property
;
430 public PropertyMethod AccessorFirst
{
436 public PropertyMethod AccessorSecond
{
438 return first
== get ? set : get;
442 public PropertyMethod Get
{
451 Parent
.AddMember (get);
455 public PropertyMethod Set
{
464 Parent
.AddMember (set);
468 public override string[] ValidAttributeTargets
{
470 return attribute_targets
;
476 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
478 if (a
.HasSecurityAttribute
) {
479 a
.Error_InvalidSecurityParent ();
483 if (a
.Type
== pa
.Dynamic
) {
484 a
.Error_MisusedDynamicAttribute ();
488 PropertyBuilder
.SetCustomAttribute ((ConstructorInfo
) ctor
.GetMetaInfo (), cdata
);
491 void CheckMissingAccessor (MemberKind kind
, ParametersCompiled parameters
, bool get)
493 if (IsExplicitImpl
) {
495 if (kind
== MemberKind
.Indexer
)
496 filter
= new MemberFilter (MemberCache
.IndexerNameAlias
, 0, kind
, parameters
, null);
498 filter
= new MemberFilter (MemberName
.Name
, 0, kind
, null, null);
500 var implementing
= MemberCache
.FindMember (InterfaceType
, filter
, BindingRestriction
.DeclaredOnly
) as PropertySpec
;
502 if (implementing
== null)
505 var accessor
= get ? implementing
.Get
: implementing
.Set
;
506 if (accessor
!= null) {
507 Report
.SymbolRelatedToPreviousError (accessor
);
508 Report
.Error (551, Location
, "Explicit interface implementation `{0}' is missing accessor `{1}'",
509 GetSignatureForError (), accessor
.GetSignatureForError ());
514 protected override bool CheckOverrideAgainstBase (MemberSpec base_member
)
516 var ok
= base.CheckOverrideAgainstBase (base_member
);
519 // Check base property accessors conflict
521 var base_prop
= (PropertySpec
) base_member
;
523 if (!base_prop
.HasGet
) {
524 Report
.SymbolRelatedToPreviousError (base_prop
);
525 Report
.Error (545, Get
.Location
,
526 "`{0}': cannot override because `{1}' does not have an overridable get accessor",
527 Get
.GetSignatureForError (), base_prop
.GetSignatureForError ());
529 } else if (Get
.HasCustomAccessModifier
|| base_prop
.HasDifferentAccessibility
) {
530 if (!CheckAccessModifiers (Get
, base_prop
.Get
)) {
531 Error_CannotChangeAccessModifiers (Get
, base_prop
.Get
);
538 if (!base_prop
.HasSet
) {
539 Report
.SymbolRelatedToPreviousError (base_prop
);
540 Report
.Error (546, Set
.Location
,
541 "`{0}': cannot override because `{1}' does not have an overridable set accessor",
542 Set
.GetSignatureForError (), base_prop
.GetSignatureForError ());
544 } else if (Set
.HasCustomAccessModifier
|| base_prop
.HasDifferentAccessibility
) {
545 if (!CheckAccessModifiers (Set
, base_prop
.Set
)) {
546 Error_CannotChangeAccessModifiers (Set
, base_prop
.Set
);
552 if ((Set
== null || !Set
.HasCustomAccessModifier
) && (Get
== null || !Get
.HasCustomAccessModifier
)) {
553 if (!CheckAccessModifiers (this, base_prop
)) {
554 Error_CannotChangeAccessModifiers (this, base_prop
);
562 protected override void DoMemberTypeDependentChecks ()
564 base.DoMemberTypeDependentChecks ();
568 if (MemberType
.IsStatic
)
569 Error_StaticReturnType ();
572 protected override void DoMemberTypeIndependentChecks ()
574 base.DoMemberTypeIndependentChecks ();
577 // Accessors modifiers check
579 if (AccessorSecond
!= null) {
580 if ((Get
.ModFlags
& Modifiers
.AccessibilityMask
) != 0 && (Set
.ModFlags
& Modifiers
.AccessibilityMask
) != 0) {
581 Report
.Error (274, Location
, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
582 GetSignatureForError ());
584 } else if ((ModFlags
& Modifiers
.OVERRIDE
) == 0 &&
585 (Get
== null && (Set
.ModFlags
& Modifiers
.AccessibilityMask
) != 0) ||
586 (Set
== null && (Get
.ModFlags
& Modifiers
.AccessibilityMask
) != 0)) {
587 Report
.Error (276, Location
,
588 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
589 GetSignatureForError ());
593 protected bool DefineAccessors ()
595 first
.Define (Parent
);
596 if (AccessorSecond
!= null)
597 AccessorSecond
.Define (Parent
);
602 protected void DefineBuilders (MemberKind kind
, ParametersCompiled parameters
)
604 PropertyBuilder
= Parent
.TypeBuilder
.DefineProperty (
605 GetFullName (MemberName
), PropertyAttributes
.None
,
606 #if !BOOTSTRAP_BASIC // Requires trunk version mscorlib
607 IsStatic
? 0 : CallingConventions
.HasThis
,
609 MemberType
.GetMetaInfo (), null, null,
610 parameters
.GetMetaInfo (), null, null);
613 if (kind
== MemberKind
.Indexer
)
614 spec
= new IndexerSpec (Parent
.Definition
, this, MemberType
, parameters
, PropertyBuilder
, ModFlags
);
616 spec
= new PropertySpec (kind
, Parent
.Definition
, this, MemberType
, PropertyBuilder
, ModFlags
);
621 var method
= Get
.Spec
.GetMetaInfo () as MethodBuilder
;
622 if (method
!= null) {
623 PropertyBuilder
.SetGetMethod (method
);
624 Parent
.MemberCache
.AddMember (this, method
.Name
, Get
.Spec
);
627 CheckMissingAccessor (kind
, parameters
, true);
633 var method
= Set
.Spec
.GetMetaInfo () as MethodBuilder
;
634 if (method
!= null) {
635 PropertyBuilder
.SetSetMethod (method
);
636 Parent
.MemberCache
.AddMember (this, method
.Name
, Set
.Spec
);
639 CheckMissingAccessor (kind
, parameters
, false);
642 Parent
.MemberCache
.AddMember (this, PropertyBuilder
.Name
, spec
);
645 public override void Emit ()
647 CheckReservedNameConflict (GetMethod
.Prefix
, get == null ? null : get.Spec
);
648 CheckReservedNameConflict (SetMethod
.Prefix
, set == null ? null : set.Spec
);
650 if (OptAttributes
!= null)
651 OptAttributes
.Emit ();
653 if (member_type
== InternalType
.Dynamic
) {
654 PredefinedAttributes
.Get
.Dynamic
.EmitAttribute (PropertyBuilder
);
656 var trans_flags
= TypeManager
.HasDynamicTypeUsed (member_type
);
657 if (trans_flags
!= null) {
658 var pa
= PredefinedAttributes
.Get
.DynamicTransform
;
659 if (pa
.Constructor
!= null || pa
.ResolveConstructor (Location
, ArrayContainer
.MakeType (TypeManager
.bool_type
))) {
660 PropertyBuilder
.SetCustomAttribute (
661 new CustomAttributeBuilder (pa
.Constructor
, new object[] { trans_flags }
));
667 if (AccessorSecond
!= null)
668 AccessorSecond
.Emit (Parent
);
673 public override bool IsUsed
{
678 return Get
.IsUsed
| Set
.IsUsed
;
682 protected override void SetMemberName (MemberName new_name
)
684 base.SetMemberName (new_name
);
687 Get
.UpdateName (this);
690 Set
.UpdateName (this);
694 // Represents header string for documentation comment.
696 public override string DocCommentHeader
{
701 public class Property
: PropertyBase
703 public sealed class BackingField
: Field
705 readonly Property property
;
707 public BackingField (Property p
)
708 : base (p
.Parent
, p
.type_expr
,
709 Modifiers
.BACKING_FIELD
| Modifiers
.COMPILER_GENERATED
| Modifiers
.PRIVATE
| (p
.ModFlags
& (Modifiers
.STATIC
| Modifiers
.UNSAFE
)),
710 new MemberName ("<" + p
.GetFullName (p
.MemberName
) + ">k__BackingField", p
.Location
), null)
715 public string OriginalName
{
717 return property
.Name
;
721 public override string GetSignatureForError ()
723 return property
.GetSignatureForError ();
727 const Modifiers AllowedModifiers
=
730 Modifiers
.PROTECTED
|
741 const Modifiers AllowedInterfaceModifiers
=
744 public Property (DeclSpace parent
, FullNamedExpression type
, Modifiers mod
,
745 MemberName name
, Attributes attrs
)
746 : base (parent
, type
, mod
,
747 parent
.PartialContainer
.Kind
== MemberKind
.Interface
? AllowedInterfaceModifiers
: AllowedModifiers
,
752 void CreateAutomaticProperty ()
754 // Create backing field
755 Field field
= new BackingField (this);
756 if (!field
.Define ())
759 Parent
.PartialContainer
.AddField (field
);
761 FieldExpr fe
= new FieldExpr (field
, Location
);
762 if ((field
.ModFlags
& Modifiers
.STATIC
) == 0)
763 fe
.InstanceExpression
= new CompilerGeneratedThis (fe
.Type
, Location
);
766 Get
.Block
= new ToplevelBlock (Compiler
, ParametersCompiled
.EmptyReadOnlyParameters
, Location
);
767 Return r
= new Return (fe
, Location
);
768 Get
.Block
.AddStatement (r
);
771 Set
.Block
= new ToplevelBlock (Compiler
, Set
.ParameterInfo
, Location
);
772 Assign a
= new SimpleAssign (fe
, new SimpleName ("value", Location
));
773 Set
.Block
.AddStatement (new StatementExpression (a
));
776 public override bool Define ()
781 flags
|= MethodAttributes
.HideBySig
| MethodAttributes
.SpecialName
;
783 if (!IsInterface
&& (ModFlags
& (Modifiers
.ABSTRACT
| Modifiers
.EXTERN
)) == 0 &&
784 AccessorSecond
!= null && Get
.Block
== null && Set
.Block
== null) {
785 if (RootContext
.Version
<= LanguageVersion
.ISO_2
)
786 Report
.FeatureIsNotAvailable (Location
, "automatically implemented properties");
788 Get
.ModFlags
|= Modifiers
.COMPILER_GENERATED
;
789 Set
.ModFlags
|= Modifiers
.COMPILER_GENERATED
;
790 CreateAutomaticProperty ();
793 if (!DefineAccessors ())
799 DefineBuilders (MemberKind
.Property
, ParametersCompiled
.EmptyReadOnlyParameters
);
803 public override void Emit ()
805 if ((AccessorFirst
.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 public abstract class AEventPropertyAccessor
: AEventAccessor
821 protected AEventPropertyAccessor (EventProperty method
, string prefix
, Attributes attrs
, Location loc
)
822 : base (method
, prefix
, attrs
, loc
)
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 public sealed class AddDelegateMethod
: AEventPropertyAccessor
840 public AddDelegateMethod (EventProperty method
, Attributes attrs
, Location loc
)
841 : base (method
, AddPrefix
, attrs
, loc
)
846 public sealed class RemoveDelegateMethod
: AEventPropertyAccessor
848 public RemoveDelegateMethod (EventProperty method
, Attributes attrs
, Location loc
)
849 : base (method
, RemovePrefix
, attrs
, loc
)
854 static readonly string[] attribute_targets
= new string [] { "event" }
;
856 public EventProperty (DeclSpace parent
, FullNamedExpression type
, Modifiers mod_flags
, MemberName name
, Attributes attrs
)
857 : base (parent
, type
, mod_flags
, name
, attrs
)
861 public override bool Define()
870 public override string[] ValidAttributeTargets
{
872 return attribute_targets
;
878 /// Event is declared like field.
880 public class EventField
: Event
{
881 abstract class EventFieldAccessor
: AEventAccessor
883 protected EventFieldAccessor (EventField method
, string prefix
)
884 : base (method
, prefix
, null, Location
.Null
)
888 public override void Emit (DeclSpace parent
)
890 if ((method
.ModFlags
& (Modifiers
.ABSTRACT
| Modifiers
.EXTERN
)) == 0) {
891 if (parent
is Class
) {
892 MethodBuilder mb
= method_data
.MethodBuilder
;
893 mb
.SetImplementationFlags (mb
.GetMethodImplementationFlags () | MethodImplAttributes
.Synchronized
);
896 var field_info
= ((EventField
) method
).BackingField
;
897 FieldExpr f_expr
= new FieldExpr (field_info
, Location
);
898 if ((method
.ModFlags
& Modifiers
.STATIC
) == 0)
899 f_expr
.InstanceExpression
= new CompilerGeneratedThis (field_info
.Spec
.MemberType
, Location
);
901 block
= new ToplevelBlock (Compiler
, ParameterInfo
, Location
);
902 block
.AddStatement (new StatementExpression (
903 new CompoundAssign (Operation
,
905 block
.GetParameterReference (ParameterInfo
[0].Name
, Location
),
912 protected abstract Binary
.Operator Operation { get; }
915 sealed class AddDelegateMethod
: EventFieldAccessor
917 public AddDelegateMethod (EventField method
):
918 base (method
, AddPrefix
)
922 protected override Binary
.Operator Operation
{
923 get { return Binary.Operator.Addition; }
927 sealed class RemoveDelegateMethod
: EventFieldAccessor
929 public RemoveDelegateMethod (EventField method
):
930 base (method
, RemovePrefix
)
934 protected override Binary
.Operator Operation
{
935 get { return Binary.Operator.Subtraction; }
940 static readonly string[] attribute_targets
= new string [] { "event", "field", "method" }
;
941 static readonly string[] attribute_targets_interface
= new string[] { "event", "method" }
;
943 public Field BackingField
;
944 public Expression Initializer
;
946 public EventField (DeclSpace parent
, FullNamedExpression type
, Modifiers mod_flags
, MemberName name
, Attributes attrs
)
947 : base (parent
, type
, mod_flags
, name
, attrs
)
949 Add
= new AddDelegateMethod (this);
950 Remove
= new RemoveDelegateMethod (this);
953 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
955 if (a
.Target
== AttributeTargets
.Field
) {
956 BackingField
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
960 if (a
.Target
== AttributeTargets
.Method
) {
961 int errors
= Report
.Errors
;
962 Add
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
963 if (errors
== Report
.Errors
)
964 Remove
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
968 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
971 public override bool Define()
976 if (Initializer
!= null && (ModFlags
& Modifiers
.ABSTRACT
) != 0) {
977 Report
.Error (74, Location
, "`{0}': abstract event cannot have an initializer",
978 GetSignatureForError ());
981 if (!HasBackingField
) {
986 // FIXME: We are unable to detect whether generic event is used because
987 // we are using FieldExpr instead of EventExpr for event access in that
988 // case. When this issue will be fixed this hack can be removed.
989 if (TypeManager
.IsGenericType (MemberType
) || Parent
.IsGeneric
)
992 if (Add
.IsInterfaceImplementation
)
995 BackingField
= new Field (Parent
,
996 new TypeExpression (MemberType
, Location
),
997 Modifiers
.BACKING_FIELD
| Modifiers
.COMPILER_GENERATED
| Modifiers
.PRIVATE
| (ModFlags
& (Modifiers
.STATIC
| Modifiers
.UNSAFE
)),
1000 Parent
.PartialContainer
.AddField (BackingField
);
1001 BackingField
.Initializer
= Initializer
;
1002 BackingField
.ModFlags
&= ~Modifiers
.COMPILER_GENERATED
;
1004 // Call define because we passed fields definition
1005 return BackingField
.Define ();
1008 public bool HasBackingField
{
1010 return !IsInterface
&& (ModFlags
& Modifiers
.ABSTRACT
) == 0;
1014 public override string[] ValidAttributeTargets
{
1016 return HasBackingField
? attribute_targets
: attribute_targets_interface
;
1021 public abstract class Event
: PropertyBasedMember
{
1022 public abstract class AEventAccessor
: AbstractPropertyEventMethod
1024 protected readonly Event method
;
1025 ImplicitParameter param_attr
;
1026 ParametersCompiled parameters
;
1028 static readonly string[] attribute_targets
= new string [] { "method", "param", "return" }
;
1030 public const string AddPrefix
= "add_";
1031 public const string RemovePrefix
= "remove_";
1033 protected AEventAccessor (Event method
, string prefix
, Attributes attrs
, Location loc
)
1034 : base (method
, prefix
, attrs
, loc
)
1036 this.method
= method
;
1037 this.ModFlags
= method
.ModFlags
;
1038 this.parameters
= ParametersCompiled
.CreateImplicitParameter (method
.TypeExpression
, loc
);;
1041 public bool IsInterfaceImplementation
{
1042 get { return method_data.implementing != null; }
1045 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
1047 if (a
.IsInternalMethodImplAttribute
) {
1048 method
.is_external_implementation
= true;
1051 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
1054 protected override void ApplyToExtraTarget (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
1056 if (a
.Target
== AttributeTargets
.Parameter
) {
1057 if (param_attr
== null)
1058 param_attr
= new ImplicitParameter (method_data
.MethodBuilder
);
1060 param_attr
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
1064 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
1067 public override AttributeTargets AttributeTargets
{
1069 return AttributeTargets
.Method
;
1073 public override bool IsClsComplianceRequired ()
1075 return method
.IsClsComplianceRequired ();
1078 public virtual MethodBuilder
Define (DeclSpace parent
)
1080 parameters
.Resolve (this);
1082 method_data
= new MethodData (method
, method
.ModFlags
,
1083 method
.flags
| MethodAttributes
.HideBySig
| MethodAttributes
.SpecialName
, this);
1085 if (!method_data
.Define (parent
, method
.GetFullName (MemberName
), Report
))
1088 MethodBuilder mb
= method_data
.MethodBuilder
;
1089 ParameterInfo
.ApplyAttributes (mb
);
1090 Spec
= new MethodSpec (MemberKind
.Method
, parent
.PartialContainer
.Definition
, this, ReturnType
, mb
, ParameterInfo
, method
.ModFlags
);
1091 Spec
.IsAccessor
= true;
1096 public override TypeSpec ReturnType
{
1098 return TypeManager
.void_type
;
1102 public override ObsoleteAttribute
GetAttributeObsolete ()
1104 return method
.GetAttributeObsolete ();
1107 public override string[] ValidAttributeTargets
{
1109 return attribute_targets
;
1113 public override ParametersCompiled ParameterInfo
{
1121 const Modifiers AllowedModifiers
=
1124 Modifiers
.PROTECTED
|
1125 Modifiers
.INTERNAL
|
1130 Modifiers
.OVERRIDE
|
1132 Modifiers
.ABSTRACT
|
1135 const Modifiers AllowedInterfaceModifiers
=
1138 AEventAccessor
add, remove;
1139 EventBuilder EventBuilder
;
1141 protected Event (DeclSpace parent
, FullNamedExpression type
, Modifiers mod_flags
, MemberName name
, Attributes attrs
)
1142 : base (parent
, null, type
, mod_flags
,
1143 parent
.PartialContainer
.Kind
== MemberKind
.Interface
? AllowedInterfaceModifiers
: AllowedModifiers
,
1150 public override AttributeTargets AttributeTargets
{
1152 return AttributeTargets
.Event
;
1156 public AEventAccessor Add
{
1162 Parent
.AddMember (value);
1166 public AEventAccessor Remove
{
1172 Parent
.AddMember (value);
1177 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
1179 if ((a
.HasSecurityAttribute
)) {
1180 a
.Error_InvalidSecurityParent ();
1184 EventBuilder
.SetCustomAttribute ((ConstructorInfo
) ctor
.GetMetaInfo (), cdata
);
1187 protected override bool CheckOverrideAgainstBase (MemberSpec base_member
)
1189 var ok
= base.CheckOverrideAgainstBase (base_member
);
1191 if (!CheckAccessModifiers (this, base_member
)) {
1192 Error_CannotChangeAccessModifiers (this, base_member
);
1199 public override bool Define ()
1201 if (!base.Define ())
1204 if (!TypeManager
.IsDelegateType (MemberType
)) {
1205 Report
.Error (66, Location
, "`{0}': event must be of a delegate type", GetSignatureForError ());
1212 // Now define the accessors
1214 var AddBuilder
= Add
.Define (Parent
);
1215 if (AddBuilder
== null)
1218 var RemoveBuilder
= remove.Define (Parent
);
1219 if (RemoveBuilder
== null)
1222 EventBuilder
= Parent
.TypeBuilder
.DefineEvent (Name
, EventAttributes
.None
, MemberType
.GetMetaInfo ());
1223 EventBuilder
.SetAddOnMethod (AddBuilder
);
1224 EventBuilder
.SetRemoveOnMethod (RemoveBuilder
);
1226 var spec
= new EventSpec (Parent
.Definition
, this, MemberType
, ModFlags
, Add
.Spec
, remove.Spec
);
1228 Parent
.MemberCache
.AddMember (this, Name
, spec
);
1229 Parent
.MemberCache
.AddMember (this, AddBuilder
.Name
, Add
.Spec
);
1230 Parent
.MemberCache
.AddMember (this, RemoveBuilder
.Name
, remove.Spec
);
1235 public override void Emit ()
1237 CheckReservedNameConflict (null, add.Spec
);
1238 CheckReservedNameConflict (null, remove.Spec
);
1240 if (OptAttributes
!= null) {
1241 OptAttributes
.Emit ();
1245 Remove
.Emit (Parent
);
1251 // Represents header string for documentation comment.
1253 public override string DocCommentHeader
{
1254 get { return "E:"; }
1258 public class EventSpec
: MemberSpec
, IInterfaceMemberSpec
1260 MethodSpec
add, remove;
1262 public EventSpec (TypeSpec declaringType
, IMemberDefinition definition
, TypeSpec eventType
, Modifiers modifiers
, MethodSpec
add, MethodSpec
remove)
1263 : base (MemberKind
.Event
, declaringType
, definition
, modifiers
)
1265 this.AccessorAdd
= add;
1266 this.AccessorRemove
= remove;
1267 this.MemberType
= eventType
;
1272 public MethodSpec AccessorAdd
{
1281 public MethodSpec AccessorRemove
{
1290 public TypeSpec MemberType { get; private set; }
1294 public override MemberSpec
InflateMember (TypeParameterInflator inflator
)
1296 var es
= (EventSpec
) base.InflateMember (inflator
);
1297 es
.MemberType
= inflator
.Inflate (MemberType
);
1302 public class Indexer
: PropertyBase
, IParametersMember
1304 public class GetIndexerMethod
: GetMethod
, IParametersMember
1306 ParametersCompiled parameters
;
1308 public GetIndexerMethod (PropertyBase property
, Modifiers modifiers
, ParametersCompiled parameters
, Attributes attrs
, Location loc
)
1309 : base (property
, modifiers
, attrs
, loc
)
1311 this.parameters
= parameters
;
1314 public override MethodBuilder
Define (DeclSpace parent
)
1316 parameters
.Resolve (this);
1317 return base.Define (parent
);
1320 public override ParametersCompiled ParameterInfo
{
1326 #region IParametersMember Members
1328 AParametersCollection IParametersMember
.Parameters
{
1334 TypeSpec IInterfaceMemberSpec
.MemberType
{
1343 public class SetIndexerMethod
: SetMethod
, IParametersMember
1345 public SetIndexerMethod (PropertyBase property
, Modifiers modifiers
, ParametersCompiled parameters
, Attributes attrs
, Location loc
)
1346 : base (property
, modifiers
, parameters
, attrs
, loc
)
1350 #region IParametersMember Members
1352 AParametersCollection IParametersMember
.Parameters
{
1358 TypeSpec IInterfaceMemberSpec
.MemberType
{
1367 const Modifiers AllowedModifiers
=
1370 Modifiers
.PROTECTED
|
1371 Modifiers
.INTERNAL
|
1375 Modifiers
.OVERRIDE
|
1380 const Modifiers AllowedInterfaceModifiers
=
1383 readonly ParametersCompiled parameters
;
1385 public Indexer (DeclSpace parent
, FullNamedExpression type
, MemberName name
, Modifiers mod
,
1386 ParametersCompiled parameters
, Attributes attrs
)
1387 : base (parent
, type
, mod
,
1388 parent
.PartialContainer
.Kind
== MemberKind
.Interface
? AllowedInterfaceModifiers
: AllowedModifiers
,
1391 this.parameters
= parameters
;
1394 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
1396 if (a
.Type
== pa
.IndexerName
) {
1397 if (IsExplicitImpl
) {
1398 Report
.Error (415, a
.Location
,
1399 "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration",
1400 TypeManager
.CSharpName (a
.Type
));
1403 // Attribute was copied to container
1407 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
1410 protected override bool CheckForDuplications ()
1412 return Parent
.MemberCache
.CheckExistingMembersOverloads (this, parameters
);
1415 public override bool Define ()
1417 if (!base.Define ())
1420 if (!DefineParameters (parameters
))
1423 if (OptAttributes
!= null) {
1424 Attribute indexer_attr
= OptAttributes
.Search (PredefinedAttributes
.Get
.IndexerName
);
1425 if (indexer_attr
!= null) {
1426 var compiling
= indexer_attr
.Type
.MemberDefinition
as TypeContainer
;
1427 if (compiling
!= null)
1428 compiling
.Define ();
1430 string name
= indexer_attr
.GetIndexerAttributeValue ();
1431 if ((ModFlags
& Modifiers
.OVERRIDE
) != 0) {
1432 Report
.Error (609, indexer_attr
.Location
,
1433 "Cannot set the `IndexerName' attribute on an indexer marked override");
1436 if (!string.IsNullOrEmpty (name
))
1441 if (InterfaceType
!= null) {
1442 string base_IndexerName
= InterfaceType
.MemberDefinition
.GetAttributeDefaultMember ();
1443 if (base_IndexerName
!= Name
)
1444 ShortName
= base_IndexerName
;
1447 if (!Parent
.PartialContainer
.AddMember (this))
1450 flags
|= MethodAttributes
.HideBySig
| MethodAttributes
.SpecialName
;
1452 if (!DefineAccessors ())
1458 DefineBuilders (MemberKind
.Indexer
, parameters
);
1462 public override bool EnableOverloadChecks (MemberCore overload
)
1464 if (overload
is Indexer
) {
1465 caching_flags
|= Flags
.MethodOverloadsExist
;
1469 return base.EnableOverloadChecks (overload
);
1472 public override string GetDocCommentName (DeclSpace ds
)
1474 return DocUtil
.GetMethodDocCommentName (this, parameters
, ds
);
1477 public override string GetSignatureForError ()
1479 StringBuilder sb
= new StringBuilder (Parent
.GetSignatureForError ());
1480 if (MemberName
.Left
!= null) {
1482 sb
.Append (MemberName
.Left
.GetSignatureForError ());
1485 sb
.Append (".this");
1486 sb
.Append (parameters
.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
1487 return sb
.ToString ();
1490 public AParametersCollection Parameters
{
1496 public ParametersCompiled ParameterInfo
{
1502 protected override bool VerifyClsCompliance ()
1504 if (!base.VerifyClsCompliance ())
1507 parameters
.VerifyClsCompliance (this);
1512 public class IndexerSpec
: PropertySpec
, IParametersMember
1514 AParametersCollection parameters
;
1516 public IndexerSpec (TypeSpec declaringType
, IMemberDefinition definition
, TypeSpec memberType
, AParametersCollection parameters
, PropertyInfo info
, Modifiers modifiers
)
1517 : base (MemberKind
.Indexer
, declaringType
, definition
, memberType
, info
, modifiers
)
1519 this.parameters
= parameters
;
1522 public override string GetSignatureForError ()
1524 return DeclaringType
.GetSignatureForError () + ".this" + parameters
.GetSignatureForError ("[", "]", parameters
.Count
);
1527 public AParametersCollection Parameters
{