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, false);
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) {
525 Report.SymbolRelatedToPreviousError (base_prop);
526 Report.Error (545, Get.Location,
527 "`{0}': cannot override because `{1}' does not have an overridable get accessor",
528 Get.GetSignatureForError (), base_prop.GetSignatureForError ());
531 } else if (Get.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
532 if (!CheckAccessModifiers (Get, base_prop.Get)) {
533 Error_CannotChangeAccessModifiers (Get, base_prop.Get);
540 if (!base_prop.HasSet) {
542 Report.SymbolRelatedToPreviousError (base_prop);
543 Report.Error (546, Set.Location,
544 "`{0}': cannot override because `{1}' does not have an overridable set accessor",
545 Set.GetSignatureForError (), base_prop.GetSignatureForError ());
548 } else if (Set.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
549 if (!CheckAccessModifiers (Set, base_prop.Set)) {
550 Error_CannotChangeAccessModifiers (Set, base_prop.Set);
556 if ((Set == null || !Set.HasCustomAccessModifier) && (Get == null || !Get.HasCustomAccessModifier)) {
557 if (!CheckAccessModifiers (this, base_prop)) {
558 Error_CannotChangeAccessModifiers (this, base_prop);
566 protected override void DoMemberTypeDependentChecks ()
568 base.DoMemberTypeDependentChecks ();
572 if (MemberType.IsStatic)
573 Error_StaticReturnType ();
576 protected override void DoMemberTypeIndependentChecks ()
578 base.DoMemberTypeIndependentChecks ();
581 // Accessors modifiers check
583 if (AccessorSecond != null) {
584 if ((Get.ModFlags & Modifiers.AccessibilityMask) != 0 && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) {
585 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
586 GetSignatureForError ());
588 } else if ((ModFlags & Modifiers.OVERRIDE) == 0 &&
589 (Get == null && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) ||
590 (Set == null && (Get.ModFlags & Modifiers.AccessibilityMask) != 0)) {
591 Report.Error (276, Location,
592 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
593 GetSignatureForError ());
597 protected bool DefineAccessors ()
599 first.Define (Parent);
600 if (AccessorSecond != null)
601 AccessorSecond.Define (Parent);
606 protected void DefineBuilders (MemberKind kind, ParametersCompiled parameters)
608 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
609 GetFullName (MemberName), PropertyAttributes.None,
610 #if !BOOTSTRAP_BASIC // Requires trunk version mscorlib
611 IsStatic ? 0 : CallingConventions.HasThis,
613 MemberType.GetMetaInfo (), null, null,
614 parameters.GetMetaInfo (), null, null);
617 if (kind == MemberKind.Indexer)
618 spec = new IndexerSpec (Parent.Definition, this, MemberType, parameters, PropertyBuilder, ModFlags);
620 spec = new PropertySpec (kind, Parent.Definition, this, MemberType, PropertyBuilder, ModFlags);
625 var method = Get.Spec.GetMetaInfo () as MethodBuilder;
626 if (method != null) {
627 PropertyBuilder.SetGetMethod (method);
628 Parent.MemberCache.AddMember (this, method.Name, Get.Spec);
631 CheckMissingAccessor (kind, parameters, true);
637 var method = Set.Spec.GetMetaInfo () as MethodBuilder;
638 if (method != null) {
639 PropertyBuilder.SetSetMethod (method);
640 Parent.MemberCache.AddMember (this, method.Name, Set.Spec);
643 CheckMissingAccessor (kind, parameters, false);
646 Parent.MemberCache.AddMember (this, PropertyBuilder.Name, spec);
649 public override void Emit ()
651 CheckReservedNameConflict (GetMethod.Prefix, get == null ? null : get.Spec);
652 CheckReservedNameConflict (SetMethod.Prefix, set == null ? null : set.Spec);
654 if (OptAttributes != null)
655 OptAttributes.Emit ();
657 if (member_type == InternalType.Dynamic) {
658 PredefinedAttributes.Get.Dynamic.EmitAttribute (PropertyBuilder);
660 var trans_flags = TypeManager.HasDynamicTypeUsed (member_type);
661 if (trans_flags != null) {
662 var pa = PredefinedAttributes.Get.DynamicTransform;
663 if (pa.Constructor != null || pa.ResolveConstructor (Location, ArrayContainer.MakeType (TypeManager.bool_type))) {
664 PropertyBuilder.SetCustomAttribute (
665 new CustomAttributeBuilder (pa.Constructor, new object[] { trans_flags }));
671 if (AccessorSecond != null)
672 AccessorSecond.Emit (Parent);
677 public override bool IsUsed {
682 return Get.IsUsed | Set.IsUsed;
686 protected override void SetMemberName (MemberName new_name)
688 base.SetMemberName (new_name);
691 Get.UpdateName (this);
694 Set.UpdateName (this);
698 // Represents header string for documentation comment.
700 public override string DocCommentHeader {
705 public class Property : PropertyBase
707 public sealed class BackingField : Field
709 readonly Property property;
711 public BackingField (Property p)
712 : base (p.Parent, p.type_expr,
713 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
714 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
719 public string OriginalName {
721 return property.Name;
725 public override string GetSignatureForError ()
727 return property.GetSignatureForError ();
731 const Modifiers AllowedModifiers =
734 Modifiers.PROTECTED |
745 const Modifiers AllowedInterfaceModifiers =
748 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
749 MemberName name, Attributes attrs)
750 : base (parent, type, mod,
751 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
756 void CreateAutomaticProperty ()
758 // Create backing field
759 Field field = new BackingField (this);
760 if (!field.Define ())
763 Parent.PartialContainer.AddField (field);
765 FieldExpr fe = new FieldExpr (field, Location);
766 if ((field.ModFlags & Modifiers.STATIC) == 0)
767 fe.InstanceExpression = new CompilerGeneratedThis (fe.Type, Location);
770 Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
771 Return r = new Return (fe, Location);
772 Get.Block.AddStatement (r);
775 Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location);
776 Assign a = new SimpleAssign (fe, new SimpleName ("value", Location));
777 Set.Block.AddStatement (new StatementExpression (a));
780 public override bool Define ()
785 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
787 if (!IsInterface && (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
788 AccessorSecond != null && Get.Block == null && Set.Block == null) {
789 if (RootContext.Version <= LanguageVersion.ISO_2)
790 Report.FeatureIsNotAvailable (Location, "automatically implemented properties");
792 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
793 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
794 CreateAutomaticProperty ();
797 if (!DefineAccessors ())
803 DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters);
807 public override void Emit ()
809 if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
810 Report.Error (842, Location,
811 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
812 GetSignatureForError ());
820 /// For case when event is declared like property (with add and remove accessors).
822 public class EventProperty: Event {
823 public abstract class AEventPropertyAccessor : AEventAccessor
825 protected AEventPropertyAccessor (EventProperty method, string prefix, Attributes attrs, Location loc)
826 : base (method, prefix, attrs, loc)
830 public override MethodBuilder Define (DeclSpace ds)
832 CheckAbstractAndExtern (block != null);
833 return base.Define (ds);
836 public override string GetSignatureForError ()
838 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
842 public sealed class AddDelegateMethod: AEventPropertyAccessor
844 public AddDelegateMethod (EventProperty method, Attributes attrs, Location loc)
845 : base (method, AddPrefix, attrs, loc)
850 public sealed class RemoveDelegateMethod: AEventPropertyAccessor
852 public RemoveDelegateMethod (EventProperty method, Attributes attrs, Location loc)
853 : base (method, RemovePrefix, attrs, loc)
858 static readonly string[] attribute_targets = new string [] { "event" };
860 public EventProperty (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
861 : base (parent, type, mod_flags, name, attrs)
865 public override bool Define()
874 public override string[] ValidAttributeTargets {
876 return attribute_targets;
882 /// Event is declared like field.
884 public class EventField : Event {
885 abstract class EventFieldAccessor : AEventAccessor
887 protected EventFieldAccessor (EventField method, string prefix)
888 : base (method, prefix, null, Location.Null)
892 public override void Emit (DeclSpace parent)
894 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
895 if (parent is Class) {
896 MethodBuilder mb = method_data.MethodBuilder;
897 mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | MethodImplAttributes.Synchronized);
900 var field_info = ((EventField) method).backing_field;
901 FieldExpr f_expr = new FieldExpr (field_info, Location);
902 if ((method.ModFlags & Modifiers.STATIC) == 0)
903 f_expr.InstanceExpression = new CompilerGeneratedThis (field_info.Spec.MemberType, Location);
905 block = new ToplevelBlock (Compiler, ParameterInfo, Location);
906 block.AddStatement (new StatementExpression (
907 new CompoundAssign (Operation,
909 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 Expression initializer;
949 List<FieldDeclarator> declarators;
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);
960 bool HasBackingField {
962 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
966 public Expression Initializer {
975 public override string[] ValidAttributeTargets {
977 return HasBackingField ? attribute_targets : attribute_targets_interface;
983 public void AddDeclarator (FieldDeclarator declarator)
985 if (declarators == null)
986 declarators = new List<FieldDeclarator> (2);
988 declarators.Add (declarator);
990 // TODO: This will probably break
991 Parent.AddMember (this, declarator.Name.Value);
994 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
996 if (a.Target == AttributeTargets.Field) {
997 backing_field.ApplyAttributeBuilder (a, ctor, cdata, pa);
1001 if (a.Target == AttributeTargets.Method) {
1002 int errors = Report.Errors;
1003 Add.ApplyAttributeBuilder (a, ctor, cdata, pa);
1004 if (errors == Report.Errors)
1005 Remove.ApplyAttributeBuilder (a, ctor, cdata, pa);
1009 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1012 public override bool Define()
1014 if (!base.Define ())
1017 if (declarators != null) {
1018 var t = new TypeExpression (MemberType, TypeExpression.Location);
1019 int index = Parent.PartialContainer.Events.IndexOf (this);
1020 foreach (var d in declarators) {
1021 var ef = new EventField (Parent, t, ModFlags, new MemberName (d.Name.Value, d.Name.Location), OptAttributes);
1023 if (d.Initializer != null)
1024 ef.initializer = d.Initializer;
1026 Parent.PartialContainer.Events.Insert (++index, ef);
1030 if (!HasBackingField) {
1035 if (Add.IsInterfaceImplementation)
1038 backing_field = new Field (Parent,
1039 new TypeExpression (MemberType, Location),
1040 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
1043 Parent.PartialContainer.AddField (backing_field);
1044 backing_field.Initializer = Initializer;
1045 backing_field.ModFlags &= ~Modifiers.COMPILER_GENERATED;
1047 // Call define because we passed fields definition
1048 backing_field.Define ();
1050 // Set backing field for event fields
1051 spec.BackingField = backing_field.Spec;
1057 public abstract class Event : PropertyBasedMember {
1058 public abstract class AEventAccessor : AbstractPropertyEventMethod
1060 protected readonly Event method;
1061 ImplicitParameter param_attr;
1062 ParametersCompiled parameters;
1064 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
1066 public const string AddPrefix = "add_";
1067 public const string RemovePrefix = "remove_";
1069 protected AEventAccessor (Event method, string prefix, Attributes attrs, Location loc)
1070 : base (method, prefix, attrs, loc)
1072 this.method = method;
1073 this.ModFlags = method.ModFlags;
1074 this.parameters = ParametersCompiled.CreateImplicitParameter (method.TypeExpression, loc);;
1077 public bool IsInterfaceImplementation {
1078 get { return method_data.implementing != null; }
1081 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1083 if (a.IsInternalMethodImplAttribute) {
1084 method.is_external_implementation = true;
1087 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1090 protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1092 if (a.Target == AttributeTargets.Parameter) {
1093 if (param_attr == null)
1094 param_attr = new ImplicitParameter (method_data.MethodBuilder);
1096 param_attr.ApplyAttributeBuilder (a, ctor, cdata, pa);
1100 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1103 public override AttributeTargets AttributeTargets {
1105 return AttributeTargets.Method;
1109 public override bool IsClsComplianceRequired ()
1111 return method.IsClsComplianceRequired ();
1114 public virtual MethodBuilder Define (DeclSpace parent)
1116 parameters.Resolve (this);
1118 method_data = new MethodData (method, method.ModFlags,
1119 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
1121 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
1124 MethodBuilder mb = method_data.MethodBuilder;
1125 ParameterInfo.ApplyAttributes (mb);
1126 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, mb, ParameterInfo, method.ModFlags);
1127 Spec.IsAccessor = true;
1132 public override TypeSpec ReturnType {
1134 return TypeManager.void_type;
1138 public override ObsoleteAttribute GetAttributeObsolete ()
1140 return method.GetAttributeObsolete ();
1143 public override string[] ValidAttributeTargets {
1145 return attribute_targets;
1149 public override ParametersCompiled ParameterInfo {
1157 const Modifiers AllowedModifiers =
1160 Modifiers.PROTECTED |
1161 Modifiers.INTERNAL |
1166 Modifiers.OVERRIDE |
1168 Modifiers.ABSTRACT |
1171 const Modifiers AllowedInterfaceModifiers =
1174 AEventAccessor add, remove;
1175 EventBuilder EventBuilder;
1176 protected EventSpec spec;
1178 protected Event (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1179 : base (parent, null, type, mod_flags,
1180 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1187 public override AttributeTargets AttributeTargets {
1189 return AttributeTargets.Event;
1193 public AEventAccessor Add {
1199 Parent.AddMember (value);
1203 public AEventAccessor Remove {
1209 Parent.AddMember (value);
1214 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1216 if ((a.HasSecurityAttribute)) {
1217 a.Error_InvalidSecurityParent ();
1221 EventBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1224 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
1226 var ok = base.CheckOverrideAgainstBase (base_member);
1228 if (!CheckAccessModifiers (this, base_member)) {
1229 Error_CannotChangeAccessModifiers (this, base_member);
1236 public override bool Define ()
1238 if (!base.Define ())
1241 if (!TypeManager.IsDelegateType (MemberType)) {
1242 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
1249 // Now define the accessors
1251 var AddBuilder = Add.Define (Parent);
1252 if (AddBuilder == null)
1255 var RemoveBuilder = remove.Define (Parent);
1256 if (RemoveBuilder == null)
1259 EventBuilder = Parent.TypeBuilder.DefineEvent (Name, EventAttributes.None, MemberType.GetMetaInfo ());
1260 EventBuilder.SetAddOnMethod (AddBuilder);
1261 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
1263 spec = new EventSpec (Parent.Definition, this, MemberType, ModFlags, Add.Spec, remove.Spec);
1265 Parent.MemberCache.AddMember (this, Name, spec);
1266 Parent.MemberCache.AddMember (this, AddBuilder.Name, Add.Spec);
1267 Parent.MemberCache.AddMember (this, RemoveBuilder.Name, remove.Spec);
1272 public override void Emit ()
1274 CheckReservedNameConflict (null, add.Spec);
1275 CheckReservedNameConflict (null, remove.Spec);
1277 if (OptAttributes != null) {
1278 OptAttributes.Emit ();
1282 Remove.Emit (Parent);
1288 // Represents header string for documentation comment.
1290 public override string DocCommentHeader {
1291 get { return "E:"; }
1295 public class EventSpec : MemberSpec, IInterfaceMemberSpec
1297 MethodSpec add, remove;
1298 FieldSpec backing_field;
1300 public EventSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec eventType, Modifiers modifiers, MethodSpec add, MethodSpec remove)
1301 : base (MemberKind.Event, declaringType, definition, modifiers)
1303 this.AccessorAdd = add;
1304 this.AccessorRemove = remove;
1305 this.MemberType = eventType;
1310 public MethodSpec AccessorAdd {
1319 public MethodSpec AccessorRemove {
1328 public FieldSpec BackingField {
1330 return backing_field;
1333 backing_field = value;
1337 public TypeSpec MemberType { get; private set; }
1341 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1343 var es = (EventSpec) base.InflateMember (inflator);
1344 es.MemberType = inflator.Inflate (MemberType);
1349 public class Indexer : PropertyBase, IParametersMember
1351 public class GetIndexerMethod : GetMethod, IParametersMember
1353 ParametersCompiled parameters;
1355 public GetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1356 : base (property, modifiers, attrs, loc)
1358 this.parameters = parameters;
1361 public override MethodBuilder Define (DeclSpace parent)
1363 parameters.Resolve (this);
1364 return base.Define (parent);
1367 public override ParametersCompiled ParameterInfo {
1373 #region IParametersMember Members
1375 AParametersCollection IParametersMember.Parameters {
1381 TypeSpec IInterfaceMemberSpec.MemberType {
1390 public class SetIndexerMethod : SetMethod, IParametersMember
1392 public SetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1393 : base (property, modifiers, parameters, attrs, loc)
1397 #region IParametersMember Members
1399 AParametersCollection IParametersMember.Parameters {
1405 TypeSpec IInterfaceMemberSpec.MemberType {
1414 const Modifiers AllowedModifiers =
1417 Modifiers.PROTECTED |
1418 Modifiers.INTERNAL |
1422 Modifiers.OVERRIDE |
1427 const Modifiers AllowedInterfaceModifiers =
1430 readonly ParametersCompiled parameters;
1432 public Indexer (DeclSpace parent, FullNamedExpression type, MemberName name, Modifiers mod,
1433 ParametersCompiled parameters, Attributes attrs)
1434 : base (parent, type, mod,
1435 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1438 this.parameters = parameters;
1441 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1443 if (a.Type == pa.IndexerName) {
1444 if (IsExplicitImpl) {
1445 Report.Error (415, a.Location,
1446 "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration",
1447 TypeManager.CSharpName (a.Type));
1450 // Attribute was copied to container
1454 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1457 protected override bool CheckForDuplications ()
1459 return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1462 public override bool Define ()
1464 if (!base.Define ())
1467 if (!DefineParameters (parameters))
1470 if (OptAttributes != null) {
1471 Attribute indexer_attr = OptAttributes.Search (PredefinedAttributes.Get.IndexerName);
1472 if (indexer_attr != null) {
1473 var compiling = indexer_attr.Type.MemberDefinition as TypeContainer;
1474 if (compiling != null)
1475 compiling.Define ();
1477 string name = indexer_attr.GetIndexerAttributeValue ();
1478 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1479 Report.Error (609, indexer_attr.Location,
1480 "Cannot set the `IndexerName' attribute on an indexer marked override");
1483 if (!string.IsNullOrEmpty (name))
1488 if (InterfaceType != null) {
1489 string base_IndexerName = InterfaceType.MemberDefinition.GetAttributeDefaultMember ();
1490 if (base_IndexerName != Name)
1491 ShortName = base_IndexerName;
1494 if (!Parent.PartialContainer.AddMember (this))
1497 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1499 if (!DefineAccessors ())
1505 DefineBuilders (MemberKind.Indexer, parameters);
1509 public override bool EnableOverloadChecks (MemberCore overload)
1511 if (overload is Indexer) {
1512 caching_flags |= Flags.MethodOverloadsExist;
1516 return base.EnableOverloadChecks (overload);
1519 public override string GetDocCommentName (DeclSpace ds)
1521 return DocUtil.GetMethodDocCommentName (this, parameters, ds);
1524 public override string GetSignatureForError ()
1526 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
1527 if (MemberName.Left != null) {
1529 sb.Append (MemberName.Left.GetSignatureForError ());
1532 sb.Append (".this");
1533 sb.Append (parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
1534 return sb.ToString ();
1537 public AParametersCollection Parameters {
1543 public ParametersCompiled ParameterInfo {
1549 protected override bool VerifyClsCompliance ()
1551 if (!base.VerifyClsCompliance ())
1554 parameters.VerifyClsCompliance (this);
1559 public class IndexerSpec : PropertySpec, IParametersMember
1561 AParametersCollection parameters;
1563 public IndexerSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, AParametersCollection parameters, PropertyInfo info, Modifiers modifiers)
1564 : base (MemberKind.Indexer, declaringType, definition, memberType, info, modifiers)
1566 this.parameters = parameters;
1570 public AParametersCollection Parameters {
1577 public override string GetSignatureForError ()
1579 return DeclaringType.GetSignatureForError () + ".this" + parameters.GetSignatureForError ("[", "]", parameters.Count);
1582 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1584 var spec = (IndexerSpec) base.InflateMember (inflator);
1585 spec.parameters = parameters.Inflate (inflator);