2010-06-21 Atsushi Enomoto <atsushi@ximian.com>
[mcs.git] / mcs / property.cs
blob2a0fe6aea050def887cc5319001cd2447dc27ae9
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 void CheckReservedNameConflict (string prefix, MethodSpec accessor)
47 string name;
48 AParametersCollection parameters;
49 if (accessor != null) {
50 name = accessor.Name;
51 parameters = accessor.Parameters;
52 } else {
53 name = prefix + ShortName;
54 if (IsExplicitImpl)
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);
69 } else {
70 if (prefix[0] == 's')
71 parameters = ParametersCompiled.CreateFullyResolved (new[] { member_type });
72 else
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 ())
90 return false;
92 if (!MemberType.IsCLSCompliant ()) {
93 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
94 GetSignatureForError ());
96 return true;
101 public class PropertySpec : MemberSpec, IInterfaceMemberSpec
103 PropertyInfo info;
104 TypeSpec memberType;
105 MethodSpec set, get;
107 public PropertySpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, PropertyInfo info, Modifiers modifiers)
108 : base (kind, declaringType, definition, modifiers)
110 this.info = info;
111 this.memberType = memberType;
114 #region Properties
116 public MethodSpec Get {
117 get {
118 return get;
120 set {
121 get = value;
122 get.IsAccessor = true;
126 public MethodSpec Set {
127 get {
128 return set;
130 set {
131 set = value;
132 set.IsAccessor = true;
136 public bool IsNotRealProperty {
137 get {
138 return (state & StateFlags.IsNotRealProperty) != 0;
140 set {
141 state |= StateFlags.IsNotRealProperty;
145 public bool HasDifferentAccessibility {
146 get {
147 return HasGet && HasSet &&
148 (Get.Modifiers & Modifiers.AccessibilityMask) != (Set.Modifiers & Modifiers.AccessibilityMask);
152 public bool HasGet {
153 get {
154 return Get != null;
158 public bool HasSet {
159 get {
160 return Set != null;
164 public PropertyInfo MetaInfo {
165 get {
166 if ((state & StateFlags.PendingMetaInflate) != 0)
167 throw new NotSupportedException ();
169 return info;
173 public TypeSpec MemberType {
174 get {
175 return memberType;
179 #endregion
181 public override MemberSpec InflateMember (TypeParameterInflator inflator)
183 var ps = (PropertySpec) base.InflateMember (inflator);
184 ps.memberType = inflator.Inflate (memberType);
185 return ps;
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))
215 return null;
217 Spec.SetMetaInfo (method_data.MethodBuilder);
219 return method_data.MethodBuilder;
222 public override TypeSpec ReturnType {
223 get {
224 return method.MemberType;
228 public override ParametersCompiled ParameterInfo {
229 get {
230 return ParametersCompiled.EmptyReadOnlyParameters;
234 public override string[] ValidAttributeTargets {
235 get {
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);
263 return;
266 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
269 public override ParametersCompiled ParameterInfo {
270 get {
271 return parameters;
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))
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 public const Modifiers AllowedModifiers =
311 Modifiers.PUBLIC |
312 Modifiers.PROTECTED |
313 Modifiers.INTERNAL |
314 Modifiers.PRIVATE;
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 {
336 get {
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;
356 } else {
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);
378 return null;
381 public bool HasCustomAccessModifier {
382 get {
383 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
387 public PropertyBase Property {
388 get {
389 return method;
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)
422 #region Properties
424 public override AttributeTargets AttributeTargets {
425 get {
426 return AttributeTargets.Property;
430 public PropertyMethod AccessorFirst {
431 get {
432 return first;
436 public PropertyMethod AccessorSecond {
437 get {
438 return first == get ? set : get;
442 public PropertyMethod Get {
443 get {
444 return get;
446 set {
447 get = value;
448 if (first == null)
449 first = value;
451 Parent.AddMember (get);
455 public PropertyMethod Set {
456 get {
457 return set;
459 set {
460 set = value;
461 if (first == null)
462 first = value;
464 Parent.AddMember (set);
468 public override string[] ValidAttributeTargets {
469 get {
470 return attribute_targets;
474 #endregion
476 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
478 if (a.HasSecurityAttribute) {
479 a.Error_InvalidSecurityParent ();
480 return;
483 if (a.Type == pa.Dynamic) {
484 a.Error_MisusedDynamicAttribute ();
485 return;
488 PropertyBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
491 void CheckMissingAccessor (MemberKind kind, ParametersCompiled parameters, bool get)
493 if (IsExplicitImpl) {
494 MemberFilter filter;
495 if (kind == MemberKind.Indexer)
496 filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, kind, parameters, null);
497 else
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)
503 return;
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;
522 if (Get != null) {
523 if (!base_prop.HasGet) {
524 Report.SymbolRelatedToPreviousError (base_prop);
525 Report.Error (545, Get.Location,
526 "`{0}': cannot override because `{1}' does not have an overridable get accessor",
527 Get.GetSignatureForError (), base_prop.GetSignatureForError ());
528 ok = false;
529 } else if (Get.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
530 if (!CheckAccessModifiers (Get, base_prop.Get)) {
531 Error_CannotChangeAccessModifiers (Get, base_prop.Get);
532 ok = false;
537 if (Set != null) {
538 if (!base_prop.HasSet) {
539 Report.SymbolRelatedToPreviousError (base_prop);
540 Report.Error (546, Set.Location,
541 "`{0}': cannot override because `{1}' does not have an overridable set accessor",
542 Set.GetSignatureForError (), base_prop.GetSignatureForError ());
543 ok = false;
544 } else if (Set.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
545 if (!CheckAccessModifiers (Set, base_prop.Set)) {
546 Error_CannotChangeAccessModifiers (Set, base_prop.Set);
547 ok = false;
552 if ((Set == null || !Set.HasCustomAccessModifier) && (Get == null || !Get.HasCustomAccessModifier)) {
553 if (!CheckAccessModifiers (this, base_prop)) {
554 Error_CannotChangeAccessModifiers (this, base_prop);
555 ok = false;
559 return ok;
562 protected override void DoMemberTypeDependentChecks ()
564 base.DoMemberTypeDependentChecks ();
566 IsTypePermitted ();
568 if (MemberType.IsStatic)
569 Error_StaticReturnType ();
572 protected override void DoMemberTypeIndependentChecks ()
574 base.DoMemberTypeIndependentChecks ();
577 // Accessors modifiers check
579 if (AccessorSecond != null) {
580 if ((Get.ModFlags & Modifiers.AccessibilityMask) != 0 && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) {
581 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
582 GetSignatureForError ());
584 } else if ((ModFlags & Modifiers.OVERRIDE) == 0 &&
585 (Get == null && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) ||
586 (Set == null && (Get.ModFlags & Modifiers.AccessibilityMask) != 0)) {
587 Report.Error (276, Location,
588 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
589 GetSignatureForError ());
593 protected bool DefineAccessors ()
595 first.Define (Parent);
596 if (AccessorSecond != null)
597 AccessorSecond.Define (Parent);
599 return true;
602 protected void DefineBuilders (MemberKind kind, ParametersCompiled parameters)
604 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
605 GetFullName (MemberName), PropertyAttributes.None,
606 #if !BOOTSTRAP_BASIC // Requires trunk version mscorlib
607 IsStatic ? 0 : CallingConventions.HasThis,
608 #endif
609 MemberType.GetMetaInfo (), null, null,
610 parameters.GetMetaInfo (), null, null);
612 PropertySpec spec;
613 if (kind == MemberKind.Indexer)
614 spec = new IndexerSpec (Parent.Definition, this, MemberType, parameters, PropertyBuilder, ModFlags);
615 else
616 spec = new PropertySpec (kind, Parent.Definition, this, MemberType, PropertyBuilder, ModFlags);
618 if (Get != null) {
619 spec.Get = Get.Spec;
621 var method = Get.Spec.GetMetaInfo () as MethodBuilder;
622 if (method != null) {
623 PropertyBuilder.SetGetMethod (method);
624 Parent.MemberCache.AddMember (this, method.Name, Get.Spec);
626 } else {
627 CheckMissingAccessor (kind, parameters, true);
630 if (Set != null) {
631 spec.Set = Set.Spec;
633 var method = Set.Spec.GetMetaInfo () as MethodBuilder;
634 if (method != null) {
635 PropertyBuilder.SetSetMethod (method);
636 Parent.MemberCache.AddMember (this, method.Name, Set.Spec);
638 } else {
639 CheckMissingAccessor (kind, parameters, false);
642 Parent.MemberCache.AddMember (this, PropertyBuilder.Name, spec);
645 public override void Emit ()
647 CheckReservedNameConflict (GetMethod.Prefix, get == null ? null : get.Spec);
648 CheckReservedNameConflict (SetMethod.Prefix, set == null ? null : set.Spec);
650 if (OptAttributes != null)
651 OptAttributes.Emit ();
653 if (member_type == InternalType.Dynamic) {
654 PredefinedAttributes.Get.Dynamic.EmitAttribute (PropertyBuilder);
655 } else {
656 var trans_flags = TypeManager.HasDynamicTypeUsed (member_type);
657 if (trans_flags != null) {
658 var pa = PredefinedAttributes.Get.DynamicTransform;
659 if (pa.Constructor != null || pa.ResolveConstructor (Location, ArrayContainer.MakeType (TypeManager.bool_type))) {
660 PropertyBuilder.SetCustomAttribute (
661 new CustomAttributeBuilder (pa.Constructor, new object[] { trans_flags }));
666 first.Emit (Parent);
667 if (AccessorSecond != null)
668 AccessorSecond.Emit (Parent);
670 base.Emit ();
673 public override bool IsUsed {
674 get {
675 if (IsExplicitImpl)
676 return true;
678 return Get.IsUsed | Set.IsUsed;
682 protected override void SetMemberName (MemberName new_name)
684 base.SetMemberName (new_name);
686 if (Get != null)
687 Get.UpdateName (this);
689 if (Set != null)
690 Set.UpdateName (this);
694 // Represents header string for documentation comment.
696 public override string DocCommentHeader {
697 get { return "P:"; }
701 public class Property : PropertyBase
703 public sealed class BackingField : Field
705 readonly Property property;
707 public BackingField (Property p)
708 : base (p.Parent, p.type_expr,
709 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
710 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
712 this.property = p;
715 public string OriginalName {
716 get {
717 return property.Name;
721 public override string GetSignatureForError ()
723 return property.GetSignatureForError ();
727 const Modifiers AllowedModifiers =
728 Modifiers.NEW |
729 Modifiers.PUBLIC |
730 Modifiers.PROTECTED |
731 Modifiers.INTERNAL |
732 Modifiers.PRIVATE |
733 Modifiers.STATIC |
734 Modifiers.SEALED |
735 Modifiers.OVERRIDE |
736 Modifiers.ABSTRACT |
737 Modifiers.UNSAFE |
738 Modifiers.EXTERN |
739 Modifiers.VIRTUAL;
741 const Modifiers AllowedInterfaceModifiers =
742 Modifiers.NEW;
744 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
745 MemberName name, Attributes attrs)
746 : base (parent, type, mod,
747 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
748 name, attrs)
752 void CreateAutomaticProperty ()
754 // Create backing field
755 Field field = new BackingField (this);
756 if (!field.Define ())
757 return;
759 Parent.PartialContainer.AddField (field);
761 FieldExpr fe = new FieldExpr (field, Location);
762 if ((field.ModFlags & Modifiers.STATIC) == 0)
763 fe.InstanceExpression = new CompilerGeneratedThis (fe.Type, Location);
765 // Create get block
766 Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
767 Return r = new Return (fe, Location);
768 Get.Block.AddStatement (r);
770 // Create set block
771 Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location);
772 Assign a = new SimpleAssign (fe, new SimpleName ("value", Location));
773 Set.Block.AddStatement (new StatementExpression (a));
776 public override bool Define ()
778 if (!base.Define ())
779 return false;
781 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
783 if (!IsInterface && (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
784 AccessorSecond != null && Get.Block == null && Set.Block == null) {
785 if (RootContext.Version <= LanguageVersion.ISO_2)
786 Report.FeatureIsNotAvailable (Location, "automatically implemented properties");
788 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
789 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
790 CreateAutomaticProperty ();
793 if (!DefineAccessors ())
794 return false;
796 if (!CheckBase ())
797 return false;
799 DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters);
800 return true;
803 public override void Emit ()
805 if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
806 Report.Error (842, Location,
807 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
808 GetSignatureForError ());
811 base.Emit ();
815 /// <summary>
816 /// For case when event is declared like property (with add and remove accessors).
817 /// </summary>
818 public class EventProperty: Event {
819 public abstract class AEventPropertyAccessor : AEventAccessor
821 protected AEventPropertyAccessor (EventProperty method, string prefix, Attributes attrs, Location loc)
822 : base (method, prefix, attrs, loc)
826 public override MethodBuilder Define (DeclSpace ds)
828 CheckAbstractAndExtern (block != null);
829 return base.Define (ds);
832 public override string GetSignatureForError ()
834 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
838 public sealed class AddDelegateMethod: AEventPropertyAccessor
840 public AddDelegateMethod (EventProperty method, Attributes attrs, Location loc)
841 : base (method, AddPrefix, attrs, loc)
846 public sealed class RemoveDelegateMethod: AEventPropertyAccessor
848 public RemoveDelegateMethod (EventProperty method, Attributes attrs, Location loc)
849 : base (method, RemovePrefix, attrs, loc)
854 static readonly string[] attribute_targets = new string [] { "event" };
856 public EventProperty (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
857 : base (parent, type, mod_flags, name, attrs)
861 public override bool Define()
863 if (!base.Define ())
864 return false;
866 SetIsUsed ();
867 return true;
870 public override string[] ValidAttributeTargets {
871 get {
872 return attribute_targets;
877 /// <summary>
878 /// Event is declared like field.
879 /// </summary>
880 public class EventField : Event {
881 abstract class EventFieldAccessor : AEventAccessor
883 protected EventFieldAccessor (EventField method, string prefix)
884 : base (method, prefix, null, Location.Null)
888 public override void Emit (DeclSpace parent)
890 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
891 if (parent is Class) {
892 MethodBuilder mb = method_data.MethodBuilder;
893 mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | MethodImplAttributes.Synchronized);
896 var field_info = ((EventField) method).BackingField;
897 FieldExpr f_expr = new FieldExpr (field_info, Location);
898 if ((method.ModFlags & Modifiers.STATIC) == 0)
899 f_expr.InstanceExpression = new CompilerGeneratedThis (field_info.Spec.MemberType, Location);
901 block = new ToplevelBlock (Compiler, ParameterInfo, Location);
902 block.AddStatement (new StatementExpression (
903 new CompoundAssign (Operation,
904 f_expr,
905 block.GetParameterReference (ParameterInfo[0].Name, Location),
906 Location)));
909 base.Emit (parent);
912 protected abstract Binary.Operator Operation { get; }
915 sealed class AddDelegateMethod: EventFieldAccessor
917 public AddDelegateMethod (EventField method):
918 base (method, AddPrefix)
922 protected override Binary.Operator Operation {
923 get { return Binary.Operator.Addition; }
927 sealed class RemoveDelegateMethod: EventFieldAccessor
929 public RemoveDelegateMethod (EventField method):
930 base (method, RemovePrefix)
934 protected override Binary.Operator Operation {
935 get { return Binary.Operator.Subtraction; }
940 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
941 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
943 public Field BackingField;
944 public Expression Initializer;
946 public EventField (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
947 : base (parent, type, mod_flags, name, attrs)
949 Add = new AddDelegateMethod (this);
950 Remove = new RemoveDelegateMethod (this);
953 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
955 if (a.Target == AttributeTargets.Field) {
956 BackingField.ApplyAttributeBuilder (a, ctor, cdata, pa);
957 return;
960 if (a.Target == AttributeTargets.Method) {
961 int errors = Report.Errors;
962 Add.ApplyAttributeBuilder (a, ctor, cdata, pa);
963 if (errors == Report.Errors)
964 Remove.ApplyAttributeBuilder (a, ctor, cdata, pa);
965 return;
968 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
971 public override bool Define()
973 if (!base.Define ())
974 return false;
976 if (Initializer != null && (ModFlags & Modifiers.ABSTRACT) != 0) {
977 Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
978 GetSignatureForError ());
981 if (!HasBackingField) {
982 SetIsUsed ();
983 return true;
986 // FIXME: We are unable to detect whether generic event is used because
987 // we are using FieldExpr instead of EventExpr for event access in that
988 // case. When this issue will be fixed this hack can be removed.
989 if (TypeManager.IsGenericType (MemberType) || Parent.IsGeneric)
990 SetIsUsed ();
992 if (Add.IsInterfaceImplementation)
993 SetIsUsed ();
995 BackingField = new Field (Parent,
996 new TypeExpression (MemberType, Location),
997 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
998 MemberName, null);
1000 Parent.PartialContainer.AddField (BackingField);
1001 BackingField.Initializer = Initializer;
1002 BackingField.ModFlags &= ~Modifiers.COMPILER_GENERATED;
1004 // Call define because we passed fields definition
1005 return BackingField.Define ();
1008 public bool HasBackingField {
1009 get {
1010 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
1014 public override string[] ValidAttributeTargets {
1015 get {
1016 return HasBackingField ? attribute_targets : attribute_targets_interface;
1021 public abstract class Event : PropertyBasedMember {
1022 public abstract class AEventAccessor : AbstractPropertyEventMethod
1024 protected readonly Event method;
1025 ImplicitParameter param_attr;
1026 ParametersCompiled parameters;
1028 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
1030 public const string AddPrefix = "add_";
1031 public const string RemovePrefix = "remove_";
1033 protected AEventAccessor (Event method, string prefix, Attributes attrs, Location loc)
1034 : base (method, prefix, attrs, loc)
1036 this.method = method;
1037 this.ModFlags = method.ModFlags;
1038 this.parameters = ParametersCompiled.CreateImplicitParameter (method.TypeExpression, loc);;
1041 public bool IsInterfaceImplementation {
1042 get { return method_data.implementing != null; }
1045 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1047 if (a.IsInternalMethodImplAttribute) {
1048 method.is_external_implementation = true;
1051 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1054 protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1056 if (a.Target == AttributeTargets.Parameter) {
1057 if (param_attr == null)
1058 param_attr = new ImplicitParameter (method_data.MethodBuilder);
1060 param_attr.ApplyAttributeBuilder (a, ctor, cdata, pa);
1061 return;
1064 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1067 public override AttributeTargets AttributeTargets {
1068 get {
1069 return AttributeTargets.Method;
1073 public override bool IsClsComplianceRequired ()
1075 return method.IsClsComplianceRequired ();
1078 public virtual MethodBuilder Define (DeclSpace parent)
1080 parameters.Resolve (this);
1082 method_data = new MethodData (method, method.ModFlags,
1083 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
1085 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
1086 return null;
1088 MethodBuilder mb = method_data.MethodBuilder;
1089 ParameterInfo.ApplyAttributes (mb);
1090 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, mb, ParameterInfo, method.ModFlags);
1091 Spec.IsAccessor = true;
1093 return mb;
1096 public override TypeSpec ReturnType {
1097 get {
1098 return TypeManager.void_type;
1102 public override ObsoleteAttribute GetAttributeObsolete ()
1104 return method.GetAttributeObsolete ();
1107 public override string[] ValidAttributeTargets {
1108 get {
1109 return attribute_targets;
1113 public override ParametersCompiled ParameterInfo {
1114 get {
1115 return parameters;
1121 const Modifiers AllowedModifiers =
1122 Modifiers.NEW |
1123 Modifiers.PUBLIC |
1124 Modifiers.PROTECTED |
1125 Modifiers.INTERNAL |
1126 Modifiers.PRIVATE |
1127 Modifiers.STATIC |
1128 Modifiers.VIRTUAL |
1129 Modifiers.SEALED |
1130 Modifiers.OVERRIDE |
1131 Modifiers.UNSAFE |
1132 Modifiers.ABSTRACT |
1133 Modifiers.EXTERN;
1135 const Modifiers AllowedInterfaceModifiers =
1136 Modifiers.NEW;
1138 AEventAccessor add, remove;
1139 EventBuilder EventBuilder;
1141 protected Event (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1142 : base (parent, null, type, mod_flags,
1143 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1144 name, attrs)
1148 #region Properties
1150 public override AttributeTargets AttributeTargets {
1151 get {
1152 return AttributeTargets.Event;
1156 public AEventAccessor Add {
1157 get {
1158 return this.add;
1160 set {
1161 add = value;
1162 Parent.AddMember (value);
1166 public AEventAccessor Remove {
1167 get {
1168 return this.remove;
1170 set {
1171 remove = value;
1172 Parent.AddMember (value);
1175 #endregion
1177 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1179 if ((a.HasSecurityAttribute)) {
1180 a.Error_InvalidSecurityParent ();
1181 return;
1184 EventBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1187 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
1189 var ok = base.CheckOverrideAgainstBase (base_member);
1191 if (!CheckAccessModifiers (this, base_member)) {
1192 Error_CannotChangeAccessModifiers (this, base_member);
1193 ok = false;
1196 return ok;
1199 public override bool Define ()
1201 if (!base.Define ())
1202 return false;
1204 if (!TypeManager.IsDelegateType (MemberType)) {
1205 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
1208 if (!CheckBase ())
1209 return false;
1212 // Now define the accessors
1214 var AddBuilder = Add.Define (Parent);
1215 if (AddBuilder == null)
1216 return false;
1218 var RemoveBuilder = remove.Define (Parent);
1219 if (RemoveBuilder == null)
1220 return false;
1222 EventBuilder = Parent.TypeBuilder.DefineEvent (Name, EventAttributes.None, MemberType.GetMetaInfo ());
1223 EventBuilder.SetAddOnMethod (AddBuilder);
1224 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
1226 var spec = new EventSpec (Parent.Definition, this, MemberType, ModFlags, Add.Spec, remove.Spec);
1228 Parent.MemberCache.AddMember (this, Name, spec);
1229 Parent.MemberCache.AddMember (this, AddBuilder.Name, Add.Spec);
1230 Parent.MemberCache.AddMember (this, RemoveBuilder.Name, remove.Spec);
1232 return true;
1235 public override void Emit ()
1237 CheckReservedNameConflict (null, add.Spec);
1238 CheckReservedNameConflict (null, remove.Spec);
1240 if (OptAttributes != null) {
1241 OptAttributes.Emit ();
1244 Add.Emit (Parent);
1245 Remove.Emit (Parent);
1247 base.Emit ();
1251 // Represents header string for documentation comment.
1253 public override string DocCommentHeader {
1254 get { return "E:"; }
1258 public class EventSpec : MemberSpec, IInterfaceMemberSpec
1260 MethodSpec add, remove;
1262 public EventSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec eventType, Modifiers modifiers, MethodSpec add, MethodSpec remove)
1263 : base (MemberKind.Event, declaringType, definition, modifiers)
1265 this.AccessorAdd = add;
1266 this.AccessorRemove = remove;
1267 this.MemberType = eventType;
1270 #region Properties
1272 public MethodSpec AccessorAdd {
1273 get {
1274 return add;
1276 set {
1277 add = value;
1281 public MethodSpec AccessorRemove {
1282 get {
1283 return remove;
1285 set {
1286 remove = value;
1290 public TypeSpec MemberType { get; private set; }
1292 #endregion
1294 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1296 var es = (EventSpec) base.InflateMember (inflator);
1297 es.MemberType = inflator.Inflate (MemberType);
1298 return es;
1302 public class Indexer : PropertyBase, IParametersMember
1304 public class GetIndexerMethod : GetMethod, IParametersMember
1306 ParametersCompiled parameters;
1308 public GetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1309 : base (property, modifiers, attrs, loc)
1311 this.parameters = parameters;
1314 public override MethodBuilder Define (DeclSpace parent)
1316 parameters.Resolve (this);
1317 return base.Define (parent);
1320 public override ParametersCompiled ParameterInfo {
1321 get {
1322 return parameters;
1326 #region IParametersMember Members
1328 AParametersCollection IParametersMember.Parameters {
1329 get {
1330 return parameters;
1334 TypeSpec IInterfaceMemberSpec.MemberType {
1335 get {
1336 return ReturnType;
1340 #endregion
1343 public class SetIndexerMethod : SetMethod, IParametersMember
1345 public SetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1346 : base (property, modifiers, parameters, attrs, loc)
1350 #region IParametersMember Members
1352 AParametersCollection IParametersMember.Parameters {
1353 get {
1354 return parameters;
1358 TypeSpec IInterfaceMemberSpec.MemberType {
1359 get {
1360 return ReturnType;
1364 #endregion
1367 const Modifiers AllowedModifiers =
1368 Modifiers.NEW |
1369 Modifiers.PUBLIC |
1370 Modifiers.PROTECTED |
1371 Modifiers.INTERNAL |
1372 Modifiers.PRIVATE |
1373 Modifiers.VIRTUAL |
1374 Modifiers.SEALED |
1375 Modifiers.OVERRIDE |
1376 Modifiers.UNSAFE |
1377 Modifiers.EXTERN |
1378 Modifiers.ABSTRACT;
1380 const Modifiers AllowedInterfaceModifiers =
1381 Modifiers.NEW;
1383 readonly ParametersCompiled parameters;
1385 public Indexer (DeclSpace parent, FullNamedExpression type, MemberName name, Modifiers mod,
1386 ParametersCompiled parameters, Attributes attrs)
1387 : base (parent, type, mod,
1388 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1389 name, attrs)
1391 this.parameters = parameters;
1394 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1396 if (a.Type == pa.IndexerName) {
1397 if (IsExplicitImpl) {
1398 Report.Error (415, a.Location,
1399 "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration",
1400 TypeManager.CSharpName (a.Type));
1403 // Attribute was copied to container
1404 return;
1407 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1410 protected override bool CheckForDuplications ()
1412 return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1415 public override bool Define ()
1417 if (!base.Define ())
1418 return false;
1420 if (!DefineParameters (parameters))
1421 return false;
1423 if (OptAttributes != null) {
1424 Attribute indexer_attr = OptAttributes.Search (PredefinedAttributes.Get.IndexerName);
1425 if (indexer_attr != null) {
1426 var compiling = indexer_attr.Type.MemberDefinition as TypeContainer;
1427 if (compiling != null)
1428 compiling.Define ();
1430 string name = indexer_attr.GetIndexerAttributeValue ();
1431 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1432 Report.Error (609, indexer_attr.Location,
1433 "Cannot set the `IndexerName' attribute on an indexer marked override");
1436 if (!string.IsNullOrEmpty (name))
1437 ShortName = name;
1441 if (InterfaceType != null) {
1442 string base_IndexerName = InterfaceType.MemberDefinition.GetAttributeDefaultMember ();
1443 if (base_IndexerName != Name)
1444 ShortName = base_IndexerName;
1447 if (!Parent.PartialContainer.AddMember (this))
1448 return false;
1450 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1452 if (!DefineAccessors ())
1453 return false;
1455 if (!CheckBase ())
1456 return false;
1458 DefineBuilders (MemberKind.Indexer, parameters);
1459 return true;
1462 public override bool EnableOverloadChecks (MemberCore overload)
1464 if (overload is Indexer) {
1465 caching_flags |= Flags.MethodOverloadsExist;
1466 return true;
1469 return base.EnableOverloadChecks (overload);
1472 public override string GetDocCommentName (DeclSpace ds)
1474 return DocUtil.GetMethodDocCommentName (this, parameters, ds);
1477 public override string GetSignatureForError ()
1479 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
1480 if (MemberName.Left != null) {
1481 sb.Append ('.');
1482 sb.Append (MemberName.Left.GetSignatureForError ());
1485 sb.Append (".this");
1486 sb.Append (parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
1487 return sb.ToString ();
1490 public AParametersCollection Parameters {
1491 get {
1492 return parameters;
1496 public ParametersCompiled ParameterInfo {
1497 get {
1498 return parameters;
1502 protected override bool VerifyClsCompliance ()
1504 if (!base.VerifyClsCompliance ())
1505 return false;
1507 parameters.VerifyClsCompliance (this);
1508 return true;
1512 public class IndexerSpec : PropertySpec, IParametersMember
1514 AParametersCollection parameters;
1516 public IndexerSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, AParametersCollection parameters, PropertyInfo info, Modifiers modifiers)
1517 : base (MemberKind.Indexer, declaringType, definition, memberType, info, modifiers)
1519 this.parameters = parameters;
1522 public override string GetSignatureForError ()
1524 return DeclaringType.GetSignatureForError () + ".this" + parameters.GetSignatureForError ("[", "]", parameters.Count);
1527 public AParametersCollection Parameters {
1528 get {
1529 return parameters;