2010-05-27 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / property.cs
blobec2067d7e23b37bd79b424ce3cf9cb910368e896
1 //
2 // property.cs: Property based handlers
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
7 //
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
14 using System;
15 using System.Collections.Generic;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Runtime.CompilerServices;
19 using System.Runtime.InteropServices;
20 using System.Security;
21 using System.Security.Permissions;
22 using System.Text;
24 #if NET_2_1
25 using XmlElement = System.Object;
26 #else
27 using System.Xml;
28 #endif
30 using Mono.CompilerServices.SymbolWriter;
32 namespace Mono.CSharp
34 // It is used as a base class for all property based members
35 // This includes properties, indexers, and events
36 public abstract class PropertyBasedMember : InterfaceMemberBase
38 public PropertyBasedMember (DeclSpace parent, GenericMethod generic,
39 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
40 MemberName name, Attributes attrs)
41 : base (parent, generic, type, mod, allowed_mod, name, attrs)
45 protected override bool VerifyClsCompliance ()
47 if (!base.VerifyClsCompliance ())
48 return false;
50 if (!MemberType.IsCLSCompliant ()) {
51 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
52 GetSignatureForError ());
54 return true;
60 // `set' and `get' accessors are represented with an Accessor.
61 //
62 public class Accessor {
64 // Null if the accessor is empty, or a Block if not
66 public const Modifiers AllowedModifiers =
67 Modifiers.PUBLIC |
68 Modifiers.PROTECTED |
69 Modifiers.INTERNAL |
70 Modifiers.PRIVATE;
72 public ToplevelBlock Block;
73 public Attributes Attributes;
74 public Location Location;
75 public Modifiers ModFlags;
76 public ParametersCompiled Parameters;
78 public Accessor (ToplevelBlock b, Modifiers mod, Attributes attrs, ParametersCompiled p, Location loc)
80 Block = b;
81 Attributes = attrs;
82 Location = loc;
83 Parameters = p;
84 ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, 0, loc, RootContext.ToplevelTypes.Compiler.Report);
88 public class PropertySpec : MemberSpec, IInterfaceMemberSpec
90 PropertyInfo info;
91 TypeSpec memberType;
92 MethodSpec set, get;
94 public PropertySpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, PropertyInfo info, Modifiers modifiers)
95 : base (kind, declaringType, definition, modifiers)
97 this.info = info;
98 this.memberType = memberType;
101 #region Properties
103 public MethodSpec Get {
104 get {
105 return get;
107 set {
108 get = value;
109 get.IsAccessor = true;
113 public MethodSpec Set {
114 get {
115 return set;
117 set {
118 set = value;
119 set.IsAccessor = true;
123 public bool IsNotRealProperty {
124 get {
125 return (state & StateFlags.IsNotRealProperty) != 0;
127 set {
128 state |= StateFlags.IsNotRealProperty;
132 public bool HasDifferentAccessibility {
133 get {
134 return HasGet && HasSet &&
135 (Get.Modifiers & Modifiers.AccessibilityMask) != (Set.Modifiers & Modifiers.AccessibilityMask);
139 public bool HasGet {
140 get {
141 return Get != null && Get.Kind != MemberKind.FakeMethod;
145 public bool HasSet {
146 get {
147 return Set != null && Set.Kind != MemberKind.FakeMethod;
151 public PropertyInfo MetaInfo {
152 get {
153 if ((state & StateFlags.PendingMetaInflate) != 0)
154 throw new NotSupportedException ();
156 return info;
160 public TypeSpec MemberType {
161 get {
162 return memberType;
166 #endregion
168 public override MemberSpec InflateMember (TypeParameterInflator inflator)
170 var ps = (PropertySpec) base.InflateMember (inflator);
171 ps.memberType = inflator.Inflate (memberType);
172 return ps;
177 // Properties and Indexers both generate PropertyBuilders, we use this to share
178 // their common bits.
180 abstract public class PropertyBase : PropertyBasedMember {
182 public class GetMethod : PropertyMethod
184 static string[] attribute_targets = new string [] { "method", "return" };
186 public GetMethod (PropertyBase method):
187 base (method, "get_")
191 public GetMethod (PropertyBase method, Accessor accessor):
192 base (method, accessor, "get_")
196 public override MethodBuilder Define (DeclSpace parent)
198 base.Define (parent);
200 Spec = new MethodSpec (IsDummy ? MemberKind.FakeMethod : MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags);
202 if (IsDummy)
203 return null;
205 method_data = new MethodData (method, ModFlags, flags, this);
207 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
208 return null;
210 Spec.SetMetaInfo (method_data.MethodBuilder);
212 return method_data.MethodBuilder;
215 public override TypeSpec ReturnType {
216 get {
217 return method.MemberType;
221 public override ParametersCompiled ParameterInfo {
222 get {
223 return ParametersCompiled.EmptyReadOnlyParameters;
227 public override string[] ValidAttributeTargets {
228 get {
229 return attribute_targets;
234 public class SetMethod : PropertyMethod {
236 static string[] attribute_targets = new string [] { "method", "param", "return" };
237 ImplicitParameter param_attr;
238 protected ParametersCompiled parameters;
240 public SetMethod (PropertyBase method) :
241 base (method, "set_")
243 parameters = 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);
260 return;
263 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
266 public override ParametersCompiled ParameterInfo {
267 get {
268 return parameters;
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);
280 if (IsDummy)
281 return null;
283 method_data = new MethodData (method, ModFlags, flags, this);
285 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
286 return null;
288 Spec.SetMetaInfo (method_data.MethodBuilder);
290 return method_data.MethodBuilder;
293 public override TypeSpec ReturnType {
294 get {
295 return TypeManager.void_type;
299 public override string[] ValidAttributeTargets {
300 get {
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,
321 string prefix)
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 {
342 get {
343 return AttributeTargets.Method;
347 public override bool IsClsComplianceRequired ()
349 return method.IsClsComplianceRequired ();
352 public virtual MethodBuilder Define (DeclSpace parent)
354 CheckForDuplications ();
356 if (IsDummy) {
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));
360 if (mi != null) {
361 Report.SymbolRelatedToPreviousError (mi);
362 Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
363 method.GetSignatureForError (), mi.GetSignatureForError ());
366 return null;
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;
377 } else {
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);
399 return null;
402 public bool HasCustomAccessModifier {
403 get {
404 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
408 public PropertyBase Property {
409 get {
410 return method;
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)
436 return true;
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 ();
460 return;
463 if (a.Type == pa.Dynamic) {
464 a.Error_MisusedDynamicAttribute ();
465 return;
468 PropertyBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
471 public override AttributeTargets AttributeTargets {
472 get {
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;
485 if (!Get.IsDummy) {
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 ());
491 ok = false;
492 } else if (Get.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
493 if (!CheckAccessModifiers (Get, base_prop.Get)) {
494 Error_CannotChangeAccessModifiers (Get, base_prop.Get);
495 ok = false;
500 if (!Set.IsDummy) {
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 ());
506 ok = false;
507 } else if (Set.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
508 if (!CheckAccessModifiers (Set, base_prop.Set)) {
509 Error_CannotChangeAccessModifiers (Set, base_prop.Set);
510 ok = false;
515 if (!Set.HasCustomAccessModifier && !Get.HasCustomAccessModifier) {
516 if (!CheckAccessModifiers (this, base_prop)) {
517 Error_CannotChangeAccessModifiers (this, base_prop);
518 ok = false;
522 return ok;
525 protected override void DoMemberTypeDependentChecks ()
527 base.DoMemberTypeDependentChecks ();
529 IsTypePermitted ();
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 ());
557 bool DefineGet ()
559 GetBuilder = Get.Define (Parent);
560 return (Get.IsDummy) ? true : GetBuilder != null;
563 bool DefineSet (bool define)
565 if (!define)
566 return true;
568 SetBuilder = Set.Define (Parent);
569 return (Set.IsDummy) ? true : SetBuilder != null;
572 protected bool DefineAccessors ()
574 return DefineSet (define_set_first) &&
575 DefineGet () &&
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 ());
586 PropertySpec spec;
587 if (kind == MemberKind.Indexer)
588 spec = new IndexerSpec (Parent.Definition, this, MemberType, parameters, PropertyBuilder, ModFlags);
589 else
590 spec = new PropertySpec (kind, Parent.Definition, this, MemberType, PropertyBuilder, ModFlags);
592 spec.Get = Get.Spec;
593 spec.Set = Set.Spec;
595 if (!Get.IsDummy) {
596 PropertyBuilder.SetGetMethod (GetBuilder);
599 if (!Set.IsDummy) {
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
613 // put the attribute
615 if (PropertyBuilder != null) {
616 if (OptAttributes != null)
617 OptAttributes.Emit ();
619 if (member_type == InternalType.Dynamic) {
620 PredefinedAttributes.Get.Dynamic.EmitAttribute (PropertyBuilder);
621 } else {
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 }));
633 if (!Get.IsDummy)
634 Get.Emit (Parent);
636 if (!Set.IsDummy)
637 Set.Emit (Parent);
639 base.Emit ();
642 /// <summary>
643 /// Tests whether accessors are not in collision with some method (CS0111)
644 /// </summary>
645 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
647 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
650 public override bool IsUsed {
651 get {
652 if (IsExplicitImpl)
653 return true;
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 {
668 get {
669 return attribute_targets;
674 // Represents header string for documentation comment.
676 public override string DocCommentHeader {
677 get { return "P:"; }
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)
692 this.property = p;
695 public string OriginalName {
696 get {
697 return property.Name;
701 public override string GetSignatureForError ()
703 return property.GetSignatureForError ();
707 const Modifiers AllowedModifiers =
708 Modifiers.NEW |
709 Modifiers.PUBLIC |
710 Modifiers.PROTECTED |
711 Modifiers.INTERNAL |
712 Modifiers.PRIVATE |
713 Modifiers.STATIC |
714 Modifiers.SEALED |
715 Modifiers.OVERRIDE |
716 Modifiers.ABSTRACT |
717 Modifiers.UNSAFE |
718 Modifiers.EXTERN |
719 Modifiers.VIRTUAL;
721 const Modifiers AllowedInterfaceModifiers =
722 Modifiers.NEW;
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);
741 else
742 Get = new GetMethod (this, get_block);
744 if (set_block == null)
745 Set = new SetMethod (this);
746 else
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 ())
765 return;
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);
773 // Create get block
774 Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
775 Return r = new Return (fe, Location);
776 Get.Block.AddStatement (r);
778 // Create set block
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 ()
786 if (!base.Define ())
787 return false;
789 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
791 if ((Get.ModFlags & Modifiers.COMPILER_GENERATED) != 0)
792 CreateAutomaticProperty ();
794 if (!DefineAccessors ())
795 return false;
797 if (!CheckBase ())
798 return false;
800 DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters);
801 return true;
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 ());
812 base.Emit ();
816 /// <summary>
817 /// For case when event is declared like property (with add and remove accessors).
818 /// </summary>
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,
859 MemberName name,
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()
869 if (!base.Define ())
870 return false;
872 SetIsUsed ();
873 return true;
876 public override string[] ValidAttributeTargets {
877 get {
878 return attribute_targets;
883 /// <summary>
884 /// Event is declared like field.
885 /// </summary>
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,
910 f_expr,
911 block.GetParameterReference (ParameterInfo[0].Name, Location))));
914 base.Emit (parent);
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);
962 return;
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);
970 return;
973 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
976 public override bool Define()
978 if (!base.Define ())
979 return false;
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) {
987 SetIsUsed ();
988 return true;
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)
995 SetIsUsed ();
997 if (Add.IsInterfaceImplementation)
998 SetIsUsed ();
1000 BackingField = new Field (Parent,
1001 new TypeExpression (MemberType, Location),
1002 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
1003 MemberName, null);
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 {
1014 get {
1015 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
1019 public override string[] ValidAttributeTargets {
1020 get {
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);
1071 return;
1074 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1077 public override AttributeTargets AttributeTargets {
1078 get {
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))
1094 return null;
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;
1101 return mb;
1104 public override TypeSpec ReturnType {
1105 get {
1106 return TypeManager.void_type;
1110 public override ObsoleteAttribute GetAttributeObsolete ()
1112 return method.GetAttributeObsolete ();
1115 public override string[] ValidAttributeTargets {
1116 get {
1117 return attribute_targets;
1121 public override ParametersCompiled ParameterInfo {
1122 get {
1123 return method.parameters;
1129 const Modifiers AllowedModifiers =
1130 Modifiers.NEW |
1131 Modifiers.PUBLIC |
1132 Modifiers.PROTECTED |
1133 Modifiers.INTERNAL |
1134 Modifiers.PRIVATE |
1135 Modifiers.STATIC |
1136 Modifiers.VIRTUAL |
1137 Modifiers.SEALED |
1138 Modifiers.OVERRIDE |
1139 Modifiers.UNSAFE |
1140 Modifiers.ABSTRACT |
1141 Modifiers.EXTERN;
1143 const Modifiers AllowedInterfaceModifiers =
1144 Modifiers.NEW;
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,
1155 name, attrs)
1159 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1161 if ((a.HasSecurityAttribute)) {
1162 a.Error_InvalidSecurityParent ();
1163 return;
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 {
1175 get {
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);
1186 ok = false;
1189 return ok;
1192 public override bool Define ()
1194 if (!base.Define ())
1195 return false;
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);
1204 if (!CheckBase ())
1205 return false;
1208 // Now define the accessors
1210 AddBuilder = Add.Define (Parent);
1211 if (AddBuilder == null)
1212 return false;
1214 RemoveBuilder = Remove.Define (Parent);
1215 if (RemoveBuilder == null)
1216 return false;
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);
1228 return true;
1231 public override void Emit ()
1233 if (OptAttributes != null) {
1234 OptAttributes.Emit ();
1237 Add.Emit (Parent);
1238 Remove.Emit (Parent);
1240 base.Emit ();
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;
1263 #region Properties
1265 public MethodSpec AccessorAdd {
1266 get {
1267 return add;
1269 set {
1270 add = value;
1274 public MethodSpec AccessorRemove {
1275 get {
1276 return remove;
1278 set {
1279 remove = value;
1283 public TypeSpec MemberType { get; private set; }
1285 #endregion
1287 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1289 var es = (EventSpec) base.InflateMember (inflator);
1290 es.MemberType = inflator.Inflate (MemberType);
1291 return es;
1295 public class Indexer : PropertyBase, IParametersMember
1297 public class GetIndexerMethod : GetMethod, IParametersMember
1299 ParametersCompiled parameters;
1301 public GetIndexerMethod (Indexer method):
1302 base (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;
1323 return true;
1326 return false;
1329 public override ParametersCompiled ParameterInfo {
1330 get {
1331 return parameters;
1335 #region IParametersMember Members
1337 AParametersCollection IParametersMember.Parameters {
1338 get {
1339 return parameters;
1343 TypeSpec IInterfaceMemberSpec.MemberType {
1344 get {
1345 return ReturnType;
1349 #endregion
1352 public class SetIndexerMethod : SetMethod, IParametersMember
1354 public SetIndexerMethod (Indexer method):
1355 base (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;
1370 return true;
1373 return false;
1376 #region IParametersMember Members
1378 AParametersCollection IParametersMember.Parameters {
1379 get {
1380 return parameters;
1384 TypeSpec IInterfaceMemberSpec.MemberType {
1385 get {
1386 return ReturnType;
1390 #endregion
1393 const Modifiers AllowedModifiers =
1394 Modifiers.NEW |
1395 Modifiers.PUBLIC |
1396 Modifiers.PROTECTED |
1397 Modifiers.INTERNAL |
1398 Modifiers.PRIVATE |
1399 Modifiers.VIRTUAL |
1400 Modifiers.SEALED |
1401 Modifiers.OVERRIDE |
1402 Modifiers.UNSAFE |
1403 Modifiers.EXTERN |
1404 Modifiers.ABSTRACT;
1406 const Modifiers AllowedInterfaceModifiers =
1407 Modifiers.NEW;
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);
1422 else
1423 Get = new GetIndexerMethod (this, get_block);
1425 if (set_block == null)
1426 Set = new SetIndexerMethod (this);
1427 else
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
1441 return;
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 ())
1455 return false;
1457 if (!DefineParameters (parameters))
1458 return false;
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))
1474 ShortName = 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))
1486 return false;
1488 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1490 if (!DefineAccessors ())
1491 return false;
1493 if (!CheckBase ())
1494 return false;
1496 DefineBuilders (MemberKind.Indexer, parameters);
1497 return true;
1500 public override bool EnableOverloadChecks (MemberCore overload)
1502 if (overload is Indexer) {
1503 caching_flags |= Flags.MethodOverloadsExist;
1504 return true;
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) {
1519 sb.Append ('.');
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 {
1529 get {
1530 return parameters;
1534 public ParametersCompiled ParameterInfo {
1535 get {
1536 return parameters;
1540 protected override bool VerifyClsCompliance ()
1542 if (!base.VerifyClsCompliance ())
1543 return false;
1545 parameters.VerifyClsCompliance (this);
1546 return true;
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 {
1566 get {
1567 return parameters;