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
= new ParametersCompiled (Compiler
,
244 new Parameter (method
.type_expr
, "value", Parameter
.Modifier
.NONE
, null, Location
));
247 public SetMethod (PropertyBase method
, Accessor accessor
):
248 base (method
, accessor
, "set_")
250 this.parameters
= accessor
.Parameters
;
253 protected override void ApplyToExtraTarget (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
255 if (a
.Target
== AttributeTargets
.Parameter
) {
256 if (param_attr
== null)
257 param_attr
= new ImplicitParameter (method_data
.MethodBuilder
);
259 param_attr
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
263 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
266 public override ParametersCompiled ParameterInfo
{
272 public override MethodBuilder
Define (DeclSpace parent
)
274 parameters
.Resolve (this);
276 base.Define (parent
);
278 Spec
= new MethodSpec (IsDummy
? MemberKind
.FakeMethod
: 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 protected readonly PropertyBase method
;
311 protected MethodAttributes flags
;
313 public PropertyMethod (PropertyBase method
, string prefix
)
314 : base (method
, prefix
)
316 this.method
= method
;
317 this.ModFlags
= method
.ModFlags
& (Modifiers
.STATIC
| Modifiers
.UNSAFE
);
320 public PropertyMethod (PropertyBase method
, Accessor accessor
,
322 : base (method
, accessor
, prefix
)
324 this.method
= method
;
325 this.ModFlags
= accessor
.ModFlags
| (method
.ModFlags
& (Modifiers
.STATIC
| Modifiers
.UNSAFE
));
327 if (accessor
.ModFlags
!= 0 && RootContext
.Version
== LanguageVersion
.ISO_1
) {
328 Report
.FeatureIsNotAvailable (Location
, "access modifiers on properties");
332 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
334 if (a
.IsInternalMethodImplAttribute
) {
335 method
.is_external_implementation
= true;
338 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
341 public override AttributeTargets AttributeTargets
{
343 return AttributeTargets
.Method
;
347 public override bool IsClsComplianceRequired ()
349 return method
.IsClsComplianceRequired ();
352 public virtual MethodBuilder
Define (DeclSpace parent
)
354 CheckForDuplications ();
357 if (method
.InterfaceType
!= null && parent
.PartialContainer
.PendingImplementations
!= null) {
358 var mi
= parent
.PartialContainer
.PendingImplementations
.IsInterfaceMethod (
359 MethodName
, method
.InterfaceType
, new MethodData (method
, ModFlags
, flags
, this));
361 Report
.SymbolRelatedToPreviousError (mi
);
362 Report
.Error (551, Location
, "Explicit interface implementation `{0}' is missing accessor `{1}'",
363 method
.GetSignatureForError (), mi
.GetSignatureForError ());
369 TypeContainer container
= parent
.PartialContainer
;
372 // Check for custom access modifier
374 if ((ModFlags
& Modifiers
.AccessibilityMask
) == 0) {
375 ModFlags
|= method
.ModFlags
;
376 flags
= method
.flags
;
378 if (container
.Kind
== MemberKind
.Interface
)
379 Report
.Error (275, Location
, "`{0}': accessibility modifiers may not be used on accessors in an interface",
380 GetSignatureForError ());
382 if ((method
.ModFlags
& Modifiers
.ABSTRACT
) != 0 && (ModFlags
& Modifiers
.PRIVATE
) != 0) {
383 Report
.Error (442, Location
, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
386 CheckModifiers (ModFlags
);
387 ModFlags
|= (method
.ModFlags
& (~Modifiers
.AccessibilityMask
));
388 ModFlags
|= Modifiers
.PROPERTY_CUSTOM
;
389 flags
= ModifiersExtensions
.MethodAttr (ModFlags
);
390 flags
|= (method
.flags
& (~MethodAttributes
.MemberAccessMask
));
393 CheckAbstractAndExtern (block
!= null);
394 CheckProtectedModifier ();
396 if (block
!= null && block
.IsIterator
)
397 Iterator
.CreateIterator (this, Parent
.PartialContainer
, ModFlags
, Compiler
);
402 public bool HasCustomAccessModifier
{
404 return (ModFlags
& Modifiers
.PROPERTY_CUSTOM
) != 0;
408 public PropertyBase Property
{
414 public override ObsoleteAttribute
GetAttributeObsolete ()
416 return method
.GetAttributeObsolete ();
419 public override string GetSignatureForError()
421 return method
.GetSignatureForError () + "." + prefix
.Substring (0, 3);
424 void CheckModifiers (Modifiers modflags
)
426 if (!ModifiersExtensions
.IsRestrictedModifier (modflags
& Modifiers
.AccessibilityMask
, method
.ModFlags
& Modifiers
.AccessibilityMask
)) {
427 Report
.Error (273, Location
,
428 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
429 GetSignatureForError (), method
.GetSignatureForError ());
433 protected bool CheckForDuplications ()
435 if ((caching_flags
& Flags
.MethodOverloadsExist
) == 0)
438 return Parent
.MemberCache
.CheckExistingMembersOverloads (this, ParameterInfo
);
442 public PropertyMethod Get
, Set
;
443 public PropertyBuilder PropertyBuilder
;
444 public MethodBuilder GetBuilder
, SetBuilder
;
446 protected bool define_set_first
= false;
448 public PropertyBase (DeclSpace parent
, FullNamedExpression type
, Modifiers mod_flags
,
449 Modifiers allowed_mod
, MemberName name
,
450 Attributes attrs
, bool define_set_first
)
451 : base (parent
, null, type
, mod_flags
, allowed_mod
, name
, attrs
)
453 this.define_set_first
= define_set_first
;
456 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
458 if (a
.HasSecurityAttribute
) {
459 a
.Error_InvalidSecurityParent ();
463 if (a
.Type
== pa
.Dynamic
) {
464 a
.Error_MisusedDynamicAttribute ();
468 PropertyBuilder
.SetCustomAttribute ((ConstructorInfo
) ctor
.GetMetaInfo (), cdata
);
471 public override AttributeTargets AttributeTargets
{
473 return AttributeTargets
.Property
;
477 protected override bool CheckOverrideAgainstBase (MemberSpec base_member
)
479 var ok
= base.CheckOverrideAgainstBase (base_member
);
482 // Check base property accessors conflict
484 var base_prop
= (PropertySpec
) base_member
;
486 if (!base_prop
.HasGet
) {
487 Report
.SymbolRelatedToPreviousError (base_prop
);
488 Report
.Error (545, Get
.Location
,
489 "`{0}': cannot override because `{1}' does not have an overridable get accessor",
490 Get
.GetSignatureForError (), base_prop
.GetSignatureForError ());
492 } else if (Get
.HasCustomAccessModifier
|| base_prop
.HasDifferentAccessibility
) {
493 if (!CheckAccessModifiers (Get
, base_prop
.Get
)) {
494 Error_CannotChangeAccessModifiers (Get
, base_prop
.Get
);
501 if (!base_prop
.HasSet
) {
502 Report
.SymbolRelatedToPreviousError (base_prop
);
503 Report
.Error (546, Set
.Location
,
504 "`{0}': cannot override because `{1}' does not have an overridable set accessor",
505 Set
.GetSignatureForError (), base_prop
.GetSignatureForError ());
507 } else if (Set
.HasCustomAccessModifier
|| base_prop
.HasDifferentAccessibility
) {
508 if (!CheckAccessModifiers (Set
, base_prop
.Set
)) {
509 Error_CannotChangeAccessModifiers (Set
, base_prop
.Set
);
515 if (!Set
.HasCustomAccessModifier
&& !Get
.HasCustomAccessModifier
) {
516 if (!CheckAccessModifiers (this, base_prop
)) {
517 Error_CannotChangeAccessModifiers (this, base_prop
);
525 protected override void DoMemberTypeDependentChecks ()
527 base.DoMemberTypeDependentChecks ();
531 if (MemberType
.IsStatic
)
532 Error_StaticReturnType ();
535 protected override void DoMemberTypeIndependentChecks ()
537 base.DoMemberTypeIndependentChecks ();
540 // Accessors modifiers check
542 if ((Get
.ModFlags
& Modifiers
.AccessibilityMask
) != 0 &&
543 (Set
.ModFlags
& Modifiers
.AccessibilityMask
) != 0) {
544 Report
.Error (274, Location
, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
545 GetSignatureForError ());
548 if ((ModFlags
& Modifiers
.OVERRIDE
) == 0 &&
549 (Get
.IsDummy
&& (Set
.ModFlags
& Modifiers
.AccessibilityMask
) != 0) ||
550 (Set
.IsDummy
&& (Get
.ModFlags
& Modifiers
.AccessibilityMask
) != 0)) {
551 Report
.Error (276, Location
,
552 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
553 GetSignatureForError ());
559 GetBuilder
= Get
.Define (Parent
);
560 return (Get
.IsDummy
) ? true : GetBuilder
!= null;
563 bool DefineSet (bool define
)
568 SetBuilder
= Set
.Define (Parent
);
569 return (Set
.IsDummy
) ? true : SetBuilder
!= null;
572 protected bool DefineAccessors ()
574 return DefineSet (define_set_first
) &&
576 DefineSet (!define_set_first
);
579 protected void DefineBuilders (MemberKind kind
, ParametersCompiled parameters
)
581 // FIXME - PropertyAttributes.HasDefault ?
583 PropertyBuilder
= Parent
.TypeBuilder
.DefineProperty (
584 GetFullName (MemberName
), PropertyAttributes
.None
, MemberType
.GetMetaInfo (), parameters
.GetMetaInfo ());
587 if (kind
== MemberKind
.Indexer
)
588 spec
= new IndexerSpec (Parent
.Definition
, this, MemberType
, parameters
, PropertyBuilder
, ModFlags
);
590 spec
= new PropertySpec (kind
, Parent
.Definition
, this, MemberType
, PropertyBuilder
, ModFlags
);
596 PropertyBuilder
.SetGetMethod (GetBuilder
);
600 PropertyBuilder
.SetSetMethod (SetBuilder
);
603 Parent
.MemberCache
.AddMember (this, Get
.IsDummy
? Get
.Name
: GetBuilder
.Name
, Get
.Spec
);
604 Parent
.MemberCache
.AddMember (this, Set
.IsDummy
? Set
.Name
: SetBuilder
.Name
, Set
.Spec
);
605 Parent
.MemberCache
.AddMember (this, PropertyBuilder
.Name
, spec
);
608 public override void Emit ()
611 // The PropertyBuilder can be null for explicit implementations, in that
612 // case, we do not actually emit the ".property", so there is nowhere to
615 if (PropertyBuilder
!= null) {
616 if (OptAttributes
!= null)
617 OptAttributes
.Emit ();
619 if (member_type
== InternalType
.Dynamic
) {
620 PredefinedAttributes
.Get
.Dynamic
.EmitAttribute (PropertyBuilder
);
622 var trans_flags
= TypeManager
.HasDynamicTypeUsed (member_type
);
623 if (trans_flags
!= null) {
624 var pa
= PredefinedAttributes
.Get
.DynamicTransform
;
625 if (pa
.Constructor
!= null || pa
.ResolveConstructor (Location
, ArrayContainer
.MakeType (TypeManager
.bool_type
))) {
626 PropertyBuilder
.SetCustomAttribute (
627 new CustomAttributeBuilder (pa
.Constructor
, new object [] { trans_flags }
));
643 /// Tests whether accessors are not in collision with some method (CS0111)
645 public bool AreAccessorsDuplicateImplementation (MethodCore mc
)
647 return Get
.IsDuplicateImplementation (mc
) || Set
.IsDuplicateImplementation (mc
);
650 public override bool IsUsed
{
655 return Get
.IsUsed
| Set
.IsUsed
;
659 protected override void SetMemberName (MemberName new_name
)
661 base.SetMemberName (new_name
);
663 Get
.UpdateName (this);
664 Set
.UpdateName (this);
667 public override string[] ValidAttributeTargets
{
669 return attribute_targets
;
674 // Represents header string for documentation comment.
676 public override string DocCommentHeader
{
681 public class Property
: PropertyBase
683 public sealed class BackingField
: Field
685 readonly Property property
;
687 public BackingField (Property p
)
688 : base (p
.Parent
, p
.type_expr
,
689 Modifiers
.BACKING_FIELD
| Modifiers
.COMPILER_GENERATED
| Modifiers
.PRIVATE
| (p
.ModFlags
& (Modifiers
.STATIC
| Modifiers
.UNSAFE
)),
690 new MemberName ("<" + p
.GetFullName (p
.MemberName
) + ">k__BackingField", p
.Location
), null)
695 public string OriginalName
{
697 return property
.Name
;
701 public override string GetSignatureForError ()
703 return property
.GetSignatureForError ();
707 const Modifiers AllowedModifiers
=
710 Modifiers
.PROTECTED
|
721 const Modifiers AllowedInterfaceModifiers
=
724 public Property (DeclSpace parent
, FullNamedExpression type
, Modifiers mod
,
725 MemberName name
, Attributes attrs
, Accessor get_block
,
726 Accessor set_block
, bool define_set_first
)
727 : this (parent
, type
, mod
, name
, attrs
, get_block
, set_block
,
728 define_set_first
, null)
732 public Property (DeclSpace parent
, FullNamedExpression type
, Modifiers mod
,
733 MemberName name
, Attributes attrs
, Accessor get_block
,
734 Accessor set_block
, bool define_set_first
, Block current_block
)
735 : base (parent
, type
, mod
,
736 parent
.PartialContainer
.Kind
== MemberKind
.Interface
? AllowedInterfaceModifiers
: AllowedModifiers
,
737 name
, attrs
, define_set_first
)
739 if (get_block
== null)
740 Get
= new GetMethod (this);
742 Get
= new GetMethod (this, get_block
);
744 if (set_block
== null)
745 Set
= new SetMethod (this);
747 Set
= new SetMethod (this, set_block
);
749 if (!IsInterface
&& (mod
& (Modifiers
.ABSTRACT
| Modifiers
.EXTERN
)) == 0 &&
750 get_block
!= null && get_block
.Block
== null &&
751 set_block
!= null && set_block
.Block
== null) {
752 if (RootContext
.Version
<= LanguageVersion
.ISO_2
)
753 Report
.FeatureIsNotAvailable (Location
, "automatically implemented properties");
755 Get
.ModFlags
|= Modifiers
.COMPILER_GENERATED
;
756 Set
.ModFlags
|= Modifiers
.COMPILER_GENERATED
;
760 void CreateAutomaticProperty ()
762 // Create backing field
763 Field field
= new BackingField (this);
764 if (!field
.Define ())
767 Parent
.PartialContainer
.AddField (field
);
769 FieldExpr fe
= new FieldExpr (field
, Location
);
770 if ((field
.ModFlags
& Modifiers
.STATIC
) == 0)
771 fe
.InstanceExpression
= new CompilerGeneratedThis (fe
.Type
, Location
);
774 Get
.Block
= new ToplevelBlock (Compiler
, ParametersCompiled
.EmptyReadOnlyParameters
, Location
);
775 Return r
= new Return (fe
, Location
);
776 Get
.Block
.AddStatement (r
);
779 Set
.Block
= new ToplevelBlock (Compiler
, Set
.ParameterInfo
, Location
);
780 Assign a
= new SimpleAssign (fe
, new SimpleName ("value", Location
));
781 Set
.Block
.AddStatement (new StatementExpression (a
));
784 public override bool Define ()
789 flags
|= MethodAttributes
.HideBySig
| MethodAttributes
.SpecialName
;
791 if ((Get
.ModFlags
& Modifiers
.COMPILER_GENERATED
) != 0)
792 CreateAutomaticProperty ();
794 if (!DefineAccessors ())
800 DefineBuilders (MemberKind
.Property
, ParametersCompiled
.EmptyReadOnlyParameters
);
804 public override void Emit ()
806 if (((Set
.ModFlags
| Get
.ModFlags
) & (Modifiers
.STATIC
| Modifiers
.COMPILER_GENERATED
)) == Modifiers
.COMPILER_GENERATED
&& Parent
.PartialContainer
.HasExplicitLayout
) {
807 Report
.Error (842, Location
,
808 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
809 GetSignatureForError ());
817 /// For case when event is declared like property (with add and remove accessors).
819 public class EventProperty
: Event
{
820 abstract class AEventPropertyAccessor
: AEventAccessor
822 protected AEventPropertyAccessor (EventProperty method
, Accessor accessor
, string prefix
)
823 : base (method
, accessor
, prefix
)
827 public override MethodBuilder
Define (DeclSpace ds
)
829 CheckAbstractAndExtern (block
!= null);
830 return base.Define (ds
);
833 public override string GetSignatureForError ()
835 return method
.GetSignatureForError () + "." + prefix
.Substring (0, prefix
.Length
- 1);
839 sealed class AddDelegateMethod
: AEventPropertyAccessor
841 public AddDelegateMethod (EventProperty method
, Accessor accessor
):
842 base (method
, accessor
, AddPrefix
)
847 sealed class RemoveDelegateMethod
: AEventPropertyAccessor
849 public RemoveDelegateMethod (EventProperty method
, Accessor accessor
):
850 base (method
, accessor
, RemovePrefix
)
856 static readonly string[] attribute_targets
= new string [] { "event" }
;
858 public EventProperty (DeclSpace parent
, FullNamedExpression type
, Modifiers mod_flags
,
860 Attributes attrs
, Accessor
add, Accessor
remove)
861 : base (parent
, type
, mod_flags
, name
, attrs
)
863 Add
= new AddDelegateMethod (this, add);
864 Remove
= new RemoveDelegateMethod (this, remove);
867 public override bool Define()
876 public override string[] ValidAttributeTargets
{
878 return attribute_targets
;
884 /// Event is declared like field.
886 public class EventField
: Event
{
887 abstract class EventFieldAccessor
: AEventAccessor
889 protected EventFieldAccessor (EventField method
, string prefix
)
890 : base (method
, prefix
)
894 public override void Emit (DeclSpace parent
)
896 if ((method
.ModFlags
& (Modifiers
.ABSTRACT
| Modifiers
.EXTERN
)) == 0) {
897 if (parent
is Class
) {
898 MethodBuilder mb
= method_data
.MethodBuilder
;
899 mb
.SetImplementationFlags (mb
.GetMethodImplementationFlags () | MethodImplAttributes
.Synchronized
);
902 var field_info
= ((EventField
) method
).BackingField
;
903 FieldExpr f_expr
= new FieldExpr (field_info
, Location
);
904 if ((method
.ModFlags
& Modifiers
.STATIC
) == 0)
905 f_expr
.InstanceExpression
= new CompilerGeneratedThis (field_info
.Spec
.MemberType
, Location
);
907 block
= new ToplevelBlock (Compiler
, ParameterInfo
, Location
);
908 block
.AddStatement (new StatementExpression (
909 new CompoundAssign (Operation
,
911 block
.GetParameterReference (ParameterInfo
[0].Name
, Location
))));
917 protected abstract Binary
.Operator Operation { get; }
920 sealed class AddDelegateMethod
: EventFieldAccessor
922 public AddDelegateMethod (EventField method
):
923 base (method
, AddPrefix
)
927 protected override Binary
.Operator Operation
{
928 get { return Binary.Operator.Addition; }
932 sealed class RemoveDelegateMethod
: EventFieldAccessor
934 public RemoveDelegateMethod (EventField method
):
935 base (method
, RemovePrefix
)
939 protected override Binary
.Operator Operation
{
940 get { return Binary.Operator.Subtraction; }
945 static readonly string[] attribute_targets
= new string [] { "event", "field", "method" }
;
946 static readonly string[] attribute_targets_interface
= new string[] { "event", "method" }
;
948 public Field BackingField
;
949 public Expression Initializer
;
951 public EventField (DeclSpace parent
, FullNamedExpression type
, Modifiers mod_flags
, MemberName name
, Attributes attrs
)
952 : base (parent
, type
, mod_flags
, name
, attrs
)
954 Add
= new AddDelegateMethod (this);
955 Remove
= new RemoveDelegateMethod (this);
958 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
960 if (a
.Target
== AttributeTargets
.Field
) {
961 BackingField
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
965 if (a
.Target
== AttributeTargets
.Method
) {
966 int errors
= Report
.Errors
;
967 Add
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
968 if (errors
== Report
.Errors
)
969 Remove
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
973 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
976 public override bool Define()
981 if (Initializer
!= null && (ModFlags
& Modifiers
.ABSTRACT
) != 0) {
982 Report
.Error (74, Location
, "`{0}': abstract event cannot have an initializer",
983 GetSignatureForError ());
986 if (!HasBackingField
) {
991 // FIXME: We are unable to detect whether generic event is used because
992 // we are using FieldExpr instead of EventExpr for event access in that
993 // case. When this issue will be fixed this hack can be removed.
994 if (TypeManager
.IsGenericType (MemberType
) || Parent
.IsGeneric
)
997 if (Add
.IsInterfaceImplementation
)
1000 BackingField
= new Field (Parent
,
1001 new TypeExpression (MemberType
, Location
),
1002 Modifiers
.BACKING_FIELD
| Modifiers
.COMPILER_GENERATED
| Modifiers
.PRIVATE
| (ModFlags
& (Modifiers
.STATIC
| Modifiers
.UNSAFE
)),
1005 Parent
.PartialContainer
.AddField (BackingField
);
1006 BackingField
.Initializer
= Initializer
;
1007 BackingField
.ModFlags
&= ~Modifiers
.COMPILER_GENERATED
;
1009 // Call define because we passed fields definition
1010 return BackingField
.Define ();
1013 public bool HasBackingField
{
1015 return !IsInterface
&& (ModFlags
& Modifiers
.ABSTRACT
) == 0;
1019 public override string[] ValidAttributeTargets
{
1021 return HasBackingField
? attribute_targets
: attribute_targets_interface
;
1026 public abstract class Event
: PropertyBasedMember
{
1027 public abstract class AEventAccessor
: AbstractPropertyEventMethod
1029 protected readonly Event method
;
1030 ImplicitParameter param_attr
;
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
;
1044 protected AEventAccessor (Event method
, Accessor accessor
, string prefix
)
1045 : base (method
, accessor
, prefix
)
1047 this.method
= method
;
1048 this.ModFlags
= method
.ModFlags
;
1051 public bool IsInterfaceImplementation
{
1052 get { return method_data.implementing != null; }
1055 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
1057 if (a
.IsInternalMethodImplAttribute
) {
1058 method
.is_external_implementation
= true;
1061 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
1064 protected override void ApplyToExtraTarget (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
1066 if (a
.Target
== AttributeTargets
.Parameter
) {
1067 if (param_attr
== null)
1068 param_attr
= new ImplicitParameter (method_data
.MethodBuilder
);
1070 param_attr
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
1074 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
1077 public override AttributeTargets AttributeTargets
{
1079 return AttributeTargets
.Method
;
1083 public override bool IsClsComplianceRequired ()
1085 return method
.IsClsComplianceRequired ();
1088 public virtual MethodBuilder
Define (DeclSpace parent
)
1090 method_data
= new MethodData (method
, method
.ModFlags
,
1091 method
.flags
| MethodAttributes
.HideBySig
| MethodAttributes
.SpecialName
, this);
1093 if (!method_data
.Define (parent
, method
.GetFullName (MemberName
), Report
))
1096 MethodBuilder mb
= method_data
.MethodBuilder
;
1097 ParameterInfo
.ApplyAttributes (mb
);
1098 Spec
= new MethodSpec (MemberKind
.Method
, parent
.PartialContainer
.Definition
, this, ReturnType
, mb
, ParameterInfo
, method
.ModFlags
);
1099 Spec
.IsAccessor
= true;
1104 public override TypeSpec ReturnType
{
1106 return TypeManager
.void_type
;
1110 public override ObsoleteAttribute
GetAttributeObsolete ()
1112 return method
.GetAttributeObsolete ();
1115 public override string[] ValidAttributeTargets
{
1117 return attribute_targets
;
1121 public override ParametersCompiled ParameterInfo
{
1123 return method
.parameters
;
1129 const Modifiers AllowedModifiers
=
1132 Modifiers
.PROTECTED
|
1133 Modifiers
.INTERNAL
|
1138 Modifiers
.OVERRIDE
|
1140 Modifiers
.ABSTRACT
|
1143 const Modifiers AllowedInterfaceModifiers
=
1146 public AEventAccessor Add
, Remove
;
1147 public EventBuilder EventBuilder
;
1148 public MethodBuilder AddBuilder
, RemoveBuilder
;
1150 ParametersCompiled parameters
;
1152 protected Event (DeclSpace parent
, FullNamedExpression type
, Modifiers mod_flags
, MemberName name
, Attributes attrs
)
1153 : base (parent
, null, type
, mod_flags
,
1154 parent
.PartialContainer
.Kind
== MemberKind
.Interface
? AllowedInterfaceModifiers
: AllowedModifiers
,
1159 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
1161 if ((a
.HasSecurityAttribute
)) {
1162 a
.Error_InvalidSecurityParent ();
1166 EventBuilder
.SetCustomAttribute ((ConstructorInfo
) ctor
.GetMetaInfo (), cdata
);
1169 public bool AreAccessorsDuplicateImplementation (MethodCore mc
)
1171 return Add
.IsDuplicateImplementation (mc
) || Remove
.IsDuplicateImplementation (mc
);
1174 public override AttributeTargets AttributeTargets
{
1176 return AttributeTargets
.Event
;
1180 protected override bool CheckOverrideAgainstBase (MemberSpec base_member
)
1182 var ok
= base.CheckOverrideAgainstBase (base_member
);
1184 if (!CheckAccessModifiers (this, base_member
)) {
1185 Error_CannotChangeAccessModifiers (this, base_member
);
1192 public override bool Define ()
1194 if (!base.Define ())
1197 if (!TypeManager
.IsDelegateType (MemberType
)) {
1198 Report
.Error (66, Location
, "`{0}': event must be of a delegate type", GetSignatureForError ());
1201 parameters
= ParametersCompiled
.CreateFullyResolved (
1202 new Parameter (null, "value", Parameter
.Modifier
.NONE
, null, Location
), MemberType
);
1208 // Now define the accessors
1210 AddBuilder
= Add
.Define (Parent
);
1211 if (AddBuilder
== null)
1214 RemoveBuilder
= Remove
.Define (Parent
);
1215 if (RemoveBuilder
== null)
1218 EventBuilder
= Parent
.TypeBuilder
.DefineEvent (Name
, EventAttributes
.None
, MemberType
.GetMetaInfo ());
1219 EventBuilder
.SetAddOnMethod (AddBuilder
);
1220 EventBuilder
.SetRemoveOnMethod (RemoveBuilder
);
1222 var spec
= new EventSpec (Parent
.Definition
, this, MemberType
, ModFlags
, Add
.Spec
, Remove
.Spec
);
1224 Parent
.MemberCache
.AddMember (this, Name
, spec
);
1225 Parent
.MemberCache
.AddMember (this, AddBuilder
.Name
, Add
.Spec
);
1226 Parent
.MemberCache
.AddMember (this, RemoveBuilder
.Name
, Remove
.Spec
);
1231 public override void Emit ()
1233 if (OptAttributes
!= null) {
1234 OptAttributes
.Emit ();
1238 Remove
.Emit (Parent
);
1244 // Represents header string for documentation comment.
1246 public override string DocCommentHeader
{
1247 get { return "E:"; }
1251 public class EventSpec
: MemberSpec
, IInterfaceMemberSpec
1253 MethodSpec
add, remove;
1255 public EventSpec (TypeSpec declaringType
, IMemberDefinition definition
, TypeSpec eventType
, Modifiers modifiers
, MethodSpec
add, MethodSpec
remove)
1256 : base (MemberKind
.Event
, declaringType
, definition
, modifiers
)
1258 this.AccessorAdd
= add;
1259 this.AccessorRemove
= remove;
1260 this.MemberType
= eventType
;
1265 public MethodSpec AccessorAdd
{
1274 public MethodSpec AccessorRemove
{
1283 public TypeSpec MemberType { get; private set; }
1287 public override MemberSpec
InflateMember (TypeParameterInflator inflator
)
1289 var es
= (EventSpec
) base.InflateMember (inflator
);
1290 es
.MemberType
= inflator
.Inflate (MemberType
);
1295 public class Indexer
: PropertyBase
, IParametersMember
1297 public class GetIndexerMethod
: GetMethod
, IParametersMember
1299 ParametersCompiled parameters
;
1301 public GetIndexerMethod (Indexer method
):
1304 this.parameters
= method
.parameters
;
1307 public GetIndexerMethod (PropertyBase method
, Accessor accessor
):
1308 base (method
, accessor
)
1310 parameters
= accessor
.Parameters
;
1313 public override MethodBuilder
Define (DeclSpace parent
)
1315 parameters
.Resolve (this);
1316 return base.Define (parent
);
1319 public override bool EnableOverloadChecks (MemberCore overload
)
1321 if (base.EnableOverloadChecks (overload
)) {
1322 overload
.caching_flags
|= Flags
.MethodOverloadsExist
;
1329 public override ParametersCompiled ParameterInfo
{
1335 #region IParametersMember Members
1337 AParametersCollection IParametersMember
.Parameters
{
1343 TypeSpec IInterfaceMemberSpec
.MemberType
{
1352 public class SetIndexerMethod
: SetMethod
, IParametersMember
1354 public SetIndexerMethod (Indexer method
):
1357 parameters
= ParametersCompiled
.MergeGenerated (Compiler
, method
.parameters
, false, parameters
[0], null);
1360 public SetIndexerMethod (PropertyBase method
, Accessor accessor
):
1361 base (method
, accessor
)
1363 parameters
= method
.Get
.IsDummy
? accessor
.Parameters
: accessor
.Parameters
.Clone ();
1366 public override bool EnableOverloadChecks (MemberCore overload
)
1368 if (base.EnableOverloadChecks (overload
)) {
1369 overload
.caching_flags
|= Flags
.MethodOverloadsExist
;
1376 #region IParametersMember Members
1378 AParametersCollection IParametersMember
.Parameters
{
1384 TypeSpec IInterfaceMemberSpec
.MemberType
{
1393 const Modifiers AllowedModifiers
=
1396 Modifiers
.PROTECTED
|
1397 Modifiers
.INTERNAL
|
1401 Modifiers
.OVERRIDE
|
1406 const Modifiers AllowedInterfaceModifiers
=
1409 readonly ParametersCompiled parameters
;
1411 public Indexer (DeclSpace parent
, FullNamedExpression type
, MemberName name
, Modifiers mod
,
1412 ParametersCompiled parameters
, Attributes attrs
,
1413 Accessor get_block
, Accessor set_block
, bool define_set_first
)
1414 : base (parent
, type
, mod
,
1415 parent
.PartialContainer
.Kind
== MemberKind
.Interface
? AllowedInterfaceModifiers
: AllowedModifiers
,
1416 name
, attrs
, define_set_first
)
1418 this.parameters
= parameters
;
1420 if (get_block
== null)
1421 Get
= new GetIndexerMethod (this);
1423 Get
= new GetIndexerMethod (this, get_block
);
1425 if (set_block
== null)
1426 Set
= new SetIndexerMethod (this);
1428 Set
= new SetIndexerMethod (this, set_block
);
1431 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
1433 if (a
.Type
== pa
.IndexerName
) {
1434 if (IsExplicitImpl
) {
1435 Report
.Error (415, a
.Location
,
1436 "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration",
1437 TypeManager
.CSharpName (a
.Type
));
1440 // Attribute was copied to container
1444 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
1447 protected override bool CheckForDuplications ()
1449 return Parent
.MemberCache
.CheckExistingMembersOverloads (this, parameters
);
1452 public override bool Define ()
1454 if (!base.Define ())
1457 if (!DefineParameters (parameters
))
1460 if (OptAttributes
!= null) {
1461 Attribute indexer_attr
= OptAttributes
.Search (PredefinedAttributes
.Get
.IndexerName
);
1462 if (indexer_attr
!= null) {
1463 var compiling
= indexer_attr
.Type
.MemberDefinition
as TypeContainer
;
1464 if (compiling
!= null)
1465 compiling
.Define ();
1467 string name
= indexer_attr
.GetIndexerAttributeValue ();
1468 if ((ModFlags
& Modifiers
.OVERRIDE
) != 0) {
1469 Report
.Error (609, indexer_attr
.Location
,
1470 "Cannot set the `IndexerName' attribute on an indexer marked override");
1473 if (!string.IsNullOrEmpty (name
))
1478 if (InterfaceType
!= null) {
1479 string base_IndexerName
= InterfaceType
.MemberDefinition
.GetAttributeDefaultMember ();
1480 if (base_IndexerName
!= Name
)
1481 ShortName
= base_IndexerName
;
1484 if (!Parent
.PartialContainer
.AddMember (this) ||
1485 !Parent
.PartialContainer
.AddMember (Get
) || !Parent
.PartialContainer
.AddMember (Set
))
1488 flags
|= MethodAttributes
.HideBySig
| MethodAttributes
.SpecialName
;
1490 if (!DefineAccessors ())
1496 DefineBuilders (MemberKind
.Indexer
, parameters
);
1500 public override bool EnableOverloadChecks (MemberCore overload
)
1502 if (overload
is Indexer
) {
1503 caching_flags
|= Flags
.MethodOverloadsExist
;
1507 return base.EnableOverloadChecks (overload
);
1510 public override string GetDocCommentName (DeclSpace ds
)
1512 return DocUtil
.GetMethodDocCommentName (this, parameters
, ds
);
1515 public override string GetSignatureForError ()
1517 StringBuilder sb
= new StringBuilder (Parent
.GetSignatureForError ());
1518 if (MemberName
.Left
!= null) {
1520 sb
.Append (MemberName
.Left
.GetSignatureForError ());
1523 sb
.Append (".this");
1524 sb
.Append (parameters
.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
1525 return sb
.ToString ();
1528 public AParametersCollection Parameters
{
1534 public ParametersCompiled ParameterInfo
{
1540 protected override bool VerifyClsCompliance ()
1542 if (!base.VerifyClsCompliance ())
1545 parameters
.VerifyClsCompliance (this);
1550 public class IndexerSpec
: PropertySpec
, IParametersMember
1552 AParametersCollection parameters
;
1554 public IndexerSpec (TypeSpec declaringType
, IMemberDefinition definition
, TypeSpec memberType
, AParametersCollection parameters
, PropertyInfo info
, Modifiers modifiers
)
1555 : base (MemberKind
.Indexer
, declaringType
, definition
, memberType
, info
, modifiers
)
1557 this.parameters
= parameters
;
1560 public override string GetSignatureForError ()
1562 return DeclaringType
.GetSignatureForError () + ".this" + parameters
.GetSignatureForError ("[", "]", parameters
.Count
);
1565 public AParametersCollection Parameters
{