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
12 // Copyright 2011 Xamarin Inc
16 using System.Collections.Generic;
20 using XmlElement = System.Object;
24 using IKVM.Reflection;
25 using IKVM.Reflection.Emit;
27 using System.Reflection;
28 using System.Reflection.Emit;
33 // It is used as a base class for all property based members
34 // This includes properties, indexers, and events
35 public abstract class PropertyBasedMember : InterfaceMemberBase
37 public PropertyBasedMember (DeclSpace parent, GenericMethod generic,
38 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
39 MemberName name, Attributes attrs)
40 : base (parent, generic, type, mod, allowed_mod, name, attrs)
44 protected void CheckReservedNameConflict (string prefix, MethodSpec accessor)
47 AParametersCollection parameters;
48 if (accessor != null) {
50 parameters = accessor.Parameters;
52 name = prefix + ShortName;
54 name = MemberName.Left + "." + name;
56 if (this is Indexer) {
57 parameters = ((Indexer) this).ParameterInfo;
58 if (prefix[0] == 's') {
59 var data = new IParameterData[parameters.Count + 1];
60 Array.Copy (parameters.FixedParameters, data, data.Length - 1);
61 data[data.Length - 1] = new ParameterData ("value", Parameter.Modifier.NONE);
62 var types = new TypeSpec[data.Length];
63 Array.Copy (parameters.Types, types, data.Length - 1);
64 types[data.Length - 1] = member_type;
66 parameters = new ParametersImported (data, types, false);
70 parameters = ParametersCompiled.CreateFullyResolved (new[] { member_type });
72 parameters = ParametersCompiled.EmptyReadOnlyParameters;
76 var conflict = MemberCache.FindMember (Parent.Definition,
77 new MemberFilter (name, 0, MemberKind.Method, parameters, null),
78 BindingRestriction.DeclaredOnly | BindingRestriction.NoAccessors);
80 if (conflict != null) {
81 Report.SymbolRelatedToPreviousError (conflict);
82 Report.Error (82, Location, "A member `{0}' is already reserved", conflict.GetSignatureForError ());
86 protected override bool VerifyClsCompliance ()
88 if (!base.VerifyClsCompliance ())
91 if (!MemberType.IsCLSCompliant ()) {
92 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
93 GetSignatureForError ());
100 public class PropertySpec : MemberSpec, IInterfaceMemberSpec
106 public PropertySpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, PropertyInfo info, Modifiers modifiers)
107 : base (kind, declaringType, definition, modifiers)
110 this.memberType = memberType;
115 public MethodSpec Get {
121 get.IsAccessor = true;
125 public MethodSpec Set {
131 set.IsAccessor = true;
135 public bool HasDifferentAccessibility {
137 return HasGet && HasSet &&
138 (Get.Modifiers & Modifiers.AccessibilityMask) != (Set.Modifiers & Modifiers.AccessibilityMask);
154 public PropertyInfo MetaInfo {
156 if ((state & StateFlags.PendingMetaInflate) != 0)
157 throw new NotSupportedException ();
163 public TypeSpec MemberType {
171 public override MemberSpec InflateMember (TypeParameterInflator inflator)
173 var ps = (PropertySpec) base.InflateMember (inflator);
174 ps.memberType = inflator.Inflate (memberType);
178 public override List<TypeSpec> ResolveMissingDependencies ()
180 return memberType.ResolveMissingDependencies ();
185 // Properties and Indexers both generate PropertyBuilders, we use this to share
186 // their common bits.
188 abstract public class PropertyBase : PropertyBasedMember {
190 public class GetMethod : PropertyMethod
192 static readonly string[] attribute_targets = new string [] { "method", "return" };
194 internal const string Prefix = "get_";
196 public GetMethod (PropertyBase method, Modifiers modifiers, Attributes attrs, Location loc)
197 : base (method, Prefix, modifiers, attrs, loc)
201 public override MethodBuilder Define (DeclSpace parent)
203 base.Define (parent);
205 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags);
207 method_data = new MethodData (method, ModFlags, flags, this);
209 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
212 Spec.SetMetaInfo (method_data.MethodBuilder);
214 return method_data.MethodBuilder;
217 public override TypeSpec ReturnType {
219 return method.MemberType;
223 public override ParametersCompiled ParameterInfo {
225 return ParametersCompiled.EmptyReadOnlyParameters;
229 public override string[] ValidAttributeTargets {
231 return attribute_targets;
236 public class SetMethod : PropertyMethod {
238 static readonly string[] attribute_targets = new string[] { "method", "param", "return" };
240 internal const string Prefix = "set_";
242 protected ParametersCompiled parameters;
244 public SetMethod (PropertyBase method, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
245 : base (method, Prefix, modifiers, attrs, loc)
247 this.parameters = parameters;
250 protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
252 if (a.Target == AttributeTargets.Parameter) {
253 parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa);
257 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
260 public override ParametersCompiled ParameterInfo {
266 public override MethodBuilder Define (DeclSpace parent)
268 parameters.Resolve (this);
270 base.Define (parent);
272 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags);
274 method_data = new MethodData (method, ModFlags, flags, this);
276 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
279 Spec.SetMetaInfo (method_data.MethodBuilder);
281 return method_data.MethodBuilder;
284 public override TypeSpec ReturnType {
286 return Parent.Compiler.BuiltinTypes.Void;
290 public override string[] ValidAttributeTargets {
292 return attribute_targets;
297 static readonly string[] attribute_targets = new string[] { "property" };
299 public abstract class PropertyMethod : AbstractPropertyEventMethod
301 const Modifiers AllowedModifiers =
303 Modifiers.PROTECTED |
307 protected readonly PropertyBase method;
308 protected MethodAttributes flags;
310 public PropertyMethod (PropertyBase method, string prefix, Modifiers modifiers, Attributes attrs, Location loc)
311 : base (method, prefix, attrs, loc)
313 this.method = method;
314 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, modifiers, 0, loc, Report);
315 this.ModFlags |= (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
318 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
320 if (a.Type == pa.MethodImpl) {
321 method.is_external_implementation = a.IsInternalCall ();
324 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
327 public override AttributeTargets AttributeTargets {
329 return AttributeTargets.Method;
333 public override bool IsClsComplianceRequired ()
335 return method.IsClsComplianceRequired ();
338 public virtual MethodBuilder Define (DeclSpace parent)
340 TypeContainer container = parent.PartialContainer;
343 // Check for custom access modifier
345 if ((ModFlags & Modifiers.AccessibilityMask) == 0) {
346 ModFlags |= method.ModFlags;
347 flags = method.flags;
349 if (container.Kind == MemberKind.Interface)
350 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
351 GetSignatureForError ());
352 else if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
353 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
356 CheckModifiers (ModFlags);
357 ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask));
358 ModFlags |= Modifiers.PROPERTY_CUSTOM;
359 flags = ModifiersExtensions.MethodAttr (ModFlags);
360 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
363 CheckAbstractAndExtern (block != null);
364 CheckProtectedModifier ();
366 if (block != null && block.IsIterator)
367 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
372 public bool HasCustomAccessModifier {
374 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
378 public PropertyBase Property {
384 public override ObsoleteAttribute GetAttributeObsolete ()
386 return method.GetAttributeObsolete ();
389 public override string GetSignatureForError()
391 return method.GetSignatureForError () + "." + prefix.Substring (0, 3);
394 void CheckModifiers (Modifiers modflags)
396 if (!ModifiersExtensions.IsRestrictedModifier (modflags & Modifiers.AccessibilityMask, method.ModFlags & Modifiers.AccessibilityMask)) {
397 Report.Error (273, Location,
398 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
399 GetSignatureForError (), method.GetSignatureForError ());
404 PropertyMethod get, set, first;
405 PropertyBuilder PropertyBuilder;
407 public PropertyBase (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags,
408 Modifiers allowed_mod, MemberName name, Attributes attrs)
409 : base (parent, null, type, mod_flags, allowed_mod, name, attrs)
415 public override AttributeTargets AttributeTargets {
417 return AttributeTargets.Property;
421 public PropertyMethod AccessorFirst {
427 public PropertyMethod AccessorSecond {
429 return first == get ? set : get;
433 public override Variance ExpectedMemberTypeVariance {
435 return (get != null && set != null) ?
436 Variance.None : set == null ?
438 Variance.Contravariant;
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.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
658 Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder);
659 } else if (member_type.HasDynamicElement) {
660 Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder, member_type, Location);
663 ConstraintChecker.Check (this, member_type, type_expr.Location);
666 if (AccessorSecond != null)
667 AccessorSecond.Emit (Parent);
672 public override bool IsUsed {
677 return Get.IsUsed | Set.IsUsed;
681 protected override void SetMemberName (MemberName new_name)
683 base.SetMemberName (new_name);
686 Get.UpdateName (this);
689 Set.UpdateName (this);
693 // Represents header string for documentation comment.
695 public override string DocCommentHeader {
700 public class Property : PropertyBase
702 public sealed class BackingField : Field
704 readonly Property property;
706 public BackingField (Property p)
707 : base (p.Parent, p.type_expr,
708 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
709 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
714 public string OriginalName {
716 return property.Name;
720 public override string GetSignatureForError ()
722 return property.GetSignatureForError ();
726 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
727 MemberName name, Attributes attrs)
728 : base (parent, type, mod,
729 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
730 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
731 AllowedModifiersClass,
736 public override void Accept (StructuralVisitor visitor)
738 visitor.Visit (this);
742 void CreateAutomaticProperty ()
744 // Create backing field
745 Field field = new BackingField (this);
746 if (!field.Define ())
749 Parent.PartialContainer.AddField (field);
751 FieldExpr fe = new FieldExpr (field, Location);
752 if ((field.ModFlags & Modifiers.STATIC) == 0)
753 fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
756 Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
757 Return r = new Return (fe, Location);
758 Get.Block.AddStatement (r);
761 Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location);
762 Assign a = new SimpleAssign (fe, new SimpleName ("value", Location));
763 Set.Block.AddStatement (new StatementExpression (a));
766 public override bool Define ()
771 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
773 if (!IsInterface && (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
774 AccessorSecond != null && Get.Block == null && Set.Block == null) {
775 if (Compiler.Settings.Version <= LanguageVersion.ISO_2)
776 Report.FeatureIsNotAvailable (Compiler, Location, "automatically implemented properties");
778 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
779 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
780 CreateAutomaticProperty ();
783 if (!DefineAccessors ())
786 if (AccessorSecond == null) {
788 if (AccessorFirst is GetMethod)
789 pm = new SetMethod (this, 0, ParametersCompiled.EmptyReadOnlyParameters, null, Location);
791 pm = new GetMethod (this, 0, null, Location);
793 Parent.AddMember (pm);
799 DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters);
803 public override void Emit ()
805 if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
806 Report.Error (842, Location,
807 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
808 GetSignatureForError ());
816 /// For case when event is declared like property (with add and remove accessors).
818 public class EventProperty: Event {
819 public abstract class AEventPropertyAccessor : AEventAccessor
821 protected AEventPropertyAccessor (EventProperty method, string prefix, Attributes attrs, Location loc)
822 : base (method, prefix, attrs, loc)
826 public override MethodBuilder Define (DeclSpace ds)
828 CheckAbstractAndExtern (block != null);
829 return base.Define (ds);
832 public override string GetSignatureForError ()
834 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
838 public sealed class AddDelegateMethod: AEventPropertyAccessor
840 public AddDelegateMethod (EventProperty method, Attributes attrs, Location loc)
841 : base (method, AddPrefix, attrs, loc)
846 public sealed class RemoveDelegateMethod: AEventPropertyAccessor
848 public RemoveDelegateMethod (EventProperty method, Attributes attrs, Location loc)
849 : base (method, RemovePrefix, attrs, loc)
854 static readonly string[] attribute_targets = new string [] { "event" };
856 public EventProperty (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
857 : base (parent, type, mod_flags, name, attrs)
861 public override void Accept (StructuralVisitor visitor)
863 visitor.Visit (this);
866 public override bool Define()
875 public override string[] ValidAttributeTargets {
877 return attribute_targets;
883 /// Event is declared like field.
885 public class EventField : Event
887 abstract class EventFieldAccessor : AEventAccessor
889 protected EventFieldAccessor (EventField method, string prefix)
890 : base (method, prefix, null, method.Location)
894 protected abstract MethodSpec GetOperation (Location loc);
896 public override void Emit (DeclSpace parent)
898 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
899 block = new ToplevelBlock (Compiler, ParameterInfo, Location);
900 FabricateBodyStatement ();
906 void FabricateBodyStatement ()
909 // Delegate obj1 = backing_field
911 // Delegate obj2 = obj1;
912 // obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1);
913 // } while (obj1 != obj2)
916 var field_info = ((EventField) method).backing_field;
917 FieldExpr f_expr = new FieldExpr (field_info, Location);
919 f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
921 var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
922 var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
924 block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr)));
926 var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality,
927 new LocalVariableReference (obj1, Location), new LocalVariableReference (obj2, Location), Location));
929 var body = new ExplicitBlock (block, Location, Location);
930 block.AddStatement (new Do (body, cond, Location));
932 body.AddStatement (new StatementExpression (
933 new SimpleAssign (new LocalVariableReference (obj2, Location), new LocalVariableReference (obj1, Location))));
935 var args_oper = new Arguments (2);
936 args_oper.Add (new Argument (new LocalVariableReference (obj2, Location)));
937 args_oper.Add (new Argument (block.GetParameterReference (0, Location)));
939 var op_method = GetOperation (Location);
941 var args = new Arguments (3);
942 args.Add (new Argument (f_expr, Argument.AType.Ref));
943 args.Add (new Argument (new Cast (
944 new TypeExpression (field_info.MemberType, Location),
945 new Invocation (MethodGroupExpr.CreatePredefined (op_method, op_method.DeclaringType, Location), args_oper),
947 args.Add (new Argument (new LocalVariableReference (obj1, Location)));
949 var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location);
953 body.AddStatement (new StatementExpression (new SimpleAssign (
954 new LocalVariableReference (obj1, Location),
955 new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args))));
959 sealed class AddDelegateMethod: EventFieldAccessor
961 public AddDelegateMethod (EventField method):
962 base (method, AddPrefix)
966 protected override MethodSpec GetOperation (Location loc)
968 return Module.PredefinedMembers.DelegateCombine.Resolve (loc);
972 sealed class RemoveDelegateMethod: EventFieldAccessor
974 public RemoveDelegateMethod (EventField method):
975 base (method, RemovePrefix)
979 protected override MethodSpec GetOperation (Location loc)
981 return Module.PredefinedMembers.DelegateRemove.Resolve (loc);
986 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
987 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
989 Expression initializer;
991 List<FieldDeclarator> declarators;
993 public EventField (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
994 : base (parent, type, mod_flags, name, attrs)
996 Add = new AddDelegateMethod (this);
997 Remove = new RemoveDelegateMethod (this);
1002 public List<FieldDeclarator> Declarators {
1004 return this.declarators;
1008 bool HasBackingField {
1010 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
1014 public Expression Initializer {
1019 initializer = value;
1023 public override string[] ValidAttributeTargets {
1025 return HasBackingField ? attribute_targets : attribute_targets_interface;
1032 public override void Accept (StructuralVisitor visitor)
1034 visitor.Visit (this);
1037 public void AddDeclarator (FieldDeclarator declarator)
1039 if (declarators == null)
1040 declarators = new List<FieldDeclarator> (2);
1042 declarators.Add (declarator);
1044 // TODO: This will probably break
1045 Parent.AddMember (this, declarator.Name.Value);
1048 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1050 if (a.Target == AttributeTargets.Field) {
1051 backing_field.ApplyAttributeBuilder (a, ctor, cdata, pa);
1055 if (a.Target == AttributeTargets.Method) {
1056 int errors = Report.Errors;
1057 Add.ApplyAttributeBuilder (a, ctor, cdata, pa);
1058 if (errors == Report.Errors)
1059 Remove.ApplyAttributeBuilder (a, ctor, cdata, pa);
1063 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1066 public override bool Define()
1068 var mod_flags_src = ModFlags;
1070 if (!base.Define ())
1073 if (declarators != null) {
1074 if ((mod_flags_src & Modifiers.DEFAULT_ACCESS_MODIFER) != 0)
1075 mod_flags_src &= ~(Modifiers.AccessibilityMask | Modifiers.DEFAULT_ACCESS_MODIFER);
1077 var t = new TypeExpression (MemberType, TypeExpression.Location);
1078 int index = Parent.PartialContainer.Events.IndexOf (this);
1079 foreach (var d in declarators) {
1080 var ef = new EventField (Parent, t, mod_flags_src, new MemberName (d.Name.Value, d.Name.Location), OptAttributes);
1082 if (d.Initializer != null)
1083 ef.initializer = d.Initializer;
1085 Parent.PartialContainer.Events.Insert (++index, ef);
1089 if (!HasBackingField) {
1094 if (Add.IsInterfaceImplementation)
1097 backing_field = new Field (Parent,
1098 new TypeExpression (MemberType, Location),
1099 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
1102 Parent.PartialContainer.AddField (backing_field);
1103 backing_field.Initializer = Initializer;
1104 backing_field.ModFlags &= ~Modifiers.COMPILER_GENERATED;
1106 // Call define because we passed fields definition
1107 backing_field.Define ();
1109 // Set backing field for event fields
1110 spec.BackingField = backing_field.Spec;
1116 public abstract class Event : PropertyBasedMember
1118 public abstract class AEventAccessor : AbstractPropertyEventMethod
1120 protected readonly Event method;
1121 readonly ParametersCompiled parameters;
1123 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
1125 public const string AddPrefix = "add_";
1126 public const string RemovePrefix = "remove_";
1128 protected AEventAccessor (Event method, string prefix, Attributes attrs, Location loc)
1129 : base (method, prefix, attrs, loc)
1131 this.method = method;
1132 this.ModFlags = method.ModFlags;
1133 this.parameters = ParametersCompiled.CreateImplicitParameter (method.TypeExpression, loc);
1136 public bool IsInterfaceImplementation {
1137 get { return method_data.implementing != null; }
1140 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1142 if (a.Type == pa.MethodImpl) {
1143 method.is_external_implementation = a.IsInternalCall ();
1146 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1149 protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1151 if (a.Target == AttributeTargets.Parameter) {
1152 parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa);
1156 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1159 public override AttributeTargets AttributeTargets {
1161 return AttributeTargets.Method;
1165 public override bool IsClsComplianceRequired ()
1167 return method.IsClsComplianceRequired ();
1170 public virtual MethodBuilder Define (DeclSpace parent)
1172 // Fill in already resolved event type to speed things up and
1173 // avoid confusing duplicate errors
1174 ((Parameter) parameters.FixedParameters[0]).Type = method.member_type;
1175 parameters.Types = new TypeSpec[] { method.member_type };
1177 method_data = new MethodData (method, method.ModFlags,
1178 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
1180 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
1183 MethodBuilder mb = method_data.MethodBuilder;
1185 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, mb, ParameterInfo, method.ModFlags);
1186 Spec.IsAccessor = true;
1191 public override TypeSpec ReturnType {
1193 return Parent.Compiler.BuiltinTypes.Void;
1197 public override ObsoleteAttribute GetAttributeObsolete ()
1199 return method.GetAttributeObsolete ();
1202 public override string[] ValidAttributeTargets {
1204 return attribute_targets;
1208 public override ParametersCompiled ParameterInfo {
1215 AEventAccessor add, remove;
1216 EventBuilder EventBuilder;
1217 protected EventSpec spec;
1219 protected Event (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1220 : base (parent, null, type, mod_flags,
1221 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
1222 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
1223 AllowedModifiersClass,
1230 public override AttributeTargets AttributeTargets {
1232 return AttributeTargets.Event;
1236 public AEventAccessor Add {
1242 Parent.AddMember (value);
1246 public override Variance ExpectedMemberTypeVariance {
1248 return Variance.Contravariant;
1252 public AEventAccessor Remove {
1258 Parent.AddMember (value);
1263 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1265 if ((a.HasSecurityAttribute)) {
1266 a.Error_InvalidSecurityParent ();
1270 EventBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1273 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
1275 var ok = base.CheckOverrideAgainstBase (base_member);
1277 if (!CheckAccessModifiers (this, base_member)) {
1278 Error_CannotChangeAccessModifiers (this, base_member);
1285 public override bool Define ()
1287 if (!base.Define ())
1290 if (!MemberType.IsDelegate) {
1291 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
1298 // Now define the accessors
1300 var AddBuilder = Add.Define (Parent);
1301 if (AddBuilder == null)
1304 var RemoveBuilder = remove.Define (Parent);
1305 if (RemoveBuilder == null)
1308 EventBuilder = Parent.TypeBuilder.DefineEvent (GetFullName (MemberName), EventAttributes.None, MemberType.GetMetaInfo ());
1309 EventBuilder.SetAddOnMethod (AddBuilder);
1310 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
1312 spec = new EventSpec (Parent.Definition, this, MemberType, ModFlags, Add.Spec, remove.Spec);
1314 Parent.MemberCache.AddMember (this, Name, spec);
1315 Parent.MemberCache.AddMember (this, AddBuilder.Name, Add.Spec);
1316 Parent.MemberCache.AddMember (this, RemoveBuilder.Name, remove.Spec);
1321 public override void Emit ()
1323 CheckReservedNameConflict (null, add.Spec);
1324 CheckReservedNameConflict (null, remove.Spec);
1326 if (OptAttributes != null) {
1327 OptAttributes.Emit ();
1330 ConstraintChecker.Check (this, member_type, type_expr.Location);
1333 Remove.Emit (Parent);
1339 // Represents header string for documentation comment.
1341 public override string DocCommentHeader {
1342 get { return "E:"; }
1346 public class EventSpec : MemberSpec, IInterfaceMemberSpec
1348 MethodSpec add, remove;
1349 FieldSpec backing_field;
1351 public EventSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec eventType, Modifiers modifiers, MethodSpec add, MethodSpec remove)
1352 : base (MemberKind.Event, declaringType, definition, modifiers)
1354 this.AccessorAdd = add;
1355 this.AccessorRemove = remove;
1356 this.MemberType = eventType;
1361 public MethodSpec AccessorAdd {
1370 public MethodSpec AccessorRemove {
1379 public FieldSpec BackingField {
1381 return backing_field;
1384 backing_field = value;
1388 public TypeSpec MemberType { get; private set; }
1392 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1394 var es = (EventSpec) base.InflateMember (inflator);
1395 es.MemberType = inflator.Inflate (MemberType);
1397 if (backing_field != null)
1398 es.backing_field = (FieldSpec) backing_field.InflateMember (inflator);
1403 public override List<TypeSpec> ResolveMissingDependencies ()
1405 return MemberType.ResolveMissingDependencies ();
1409 public class Indexer : PropertyBase, IParametersMember
1411 public class GetIndexerMethod : GetMethod, IParametersMember
1413 ParametersCompiled parameters;
1415 public GetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1416 : base (property, modifiers, attrs, loc)
1418 this.parameters = parameters;
1421 public override MethodBuilder Define (DeclSpace parent)
1423 parameters.Resolve (this);
1424 return base.Define (parent);
1427 public override ParametersCompiled ParameterInfo {
1433 #region IParametersMember Members
1435 AParametersCollection IParametersMember.Parameters {
1441 TypeSpec IInterfaceMemberSpec.MemberType {
1450 public class SetIndexerMethod : SetMethod, IParametersMember
1452 public SetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1453 : base (property, modifiers, parameters, attrs, loc)
1457 #region IParametersMember Members
1459 AParametersCollection IParametersMember.Parameters {
1465 TypeSpec IInterfaceMemberSpec.MemberType {
1474 const Modifiers AllowedModifiers =
1477 Modifiers.PROTECTED |
1478 Modifiers.INTERNAL |
1482 Modifiers.OVERRIDE |
1487 const Modifiers AllowedInterfaceModifiers =
1490 readonly ParametersCompiled parameters;
1492 public Indexer (DeclSpace parent, FullNamedExpression type, MemberName name, Modifiers mod,
1493 ParametersCompiled parameters, Attributes attrs)
1494 : base (parent, type, mod,
1495 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1498 this.parameters = parameters;
1503 AParametersCollection IParametersMember.Parameters {
1509 public ParametersCompiled ParameterInfo {
1518 public override void Accept (StructuralVisitor visitor)
1520 visitor.Visit (this);
1523 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1525 if (a.Type == pa.IndexerName) {
1526 if (IsExplicitImpl) {
1527 Report.Error (415, a.Location,
1528 "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration",
1529 TypeManager.CSharpName (a.Type));
1532 // Attribute was copied to container
1536 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1539 protected override bool CheckForDuplications ()
1541 return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1544 public override bool Define ()
1546 if (!base.Define ())
1549 if (!DefineParameters (parameters))
1552 if (OptAttributes != null) {
1553 Attribute indexer_attr = OptAttributes.Search (Module.PredefinedAttributes.IndexerName);
1554 if (indexer_attr != null) {
1555 var compiling = indexer_attr.Type.MemberDefinition as TypeContainer;
1556 if (compiling != null)
1557 compiling.Define ();
1559 string name = indexer_attr.GetIndexerAttributeValue ();
1560 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1561 Report.Error (609, indexer_attr.Location,
1562 "Cannot set the `IndexerName' attribute on an indexer marked override");
1565 if (!string.IsNullOrEmpty (name))
1570 if (InterfaceType != null) {
1571 string base_IndexerName = InterfaceType.MemberDefinition.GetAttributeDefaultMember ();
1572 if (base_IndexerName != Name)
1573 ShortName = base_IndexerName;
1576 if (!Parent.PartialContainer.AddMember (this))
1579 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1581 if (!DefineAccessors ())
1587 DefineBuilders (MemberKind.Indexer, parameters);
1591 public override bool EnableOverloadChecks (MemberCore overload)
1593 if (overload is Indexer) {
1594 caching_flags |= Flags.MethodOverloadsExist;
1598 return base.EnableOverloadChecks (overload);
1601 public override void Emit ()
1603 parameters.CheckConstraints (this);
1608 public override string GetSignatureForError ()
1610 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
1611 if (MemberName.Left != null) {
1613 sb.Append (MemberName.Left.GetSignatureForError ());
1616 sb.Append (".this");
1617 sb.Append (parameters.GetSignatureForError ("[", "]", parameters.Count));
1618 return sb.ToString ();
1621 public override string GetSignatureForDocumentation ()
1623 return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1626 protected override bool VerifyClsCompliance ()
1628 if (!base.VerifyClsCompliance ())
1631 parameters.VerifyClsCompliance (this);
1636 public class IndexerSpec : PropertySpec, IParametersMember
1638 AParametersCollection parameters;
1640 public IndexerSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, AParametersCollection parameters, PropertyInfo info, Modifiers modifiers)
1641 : base (MemberKind.Indexer, declaringType, definition, memberType, info, modifiers)
1643 this.parameters = parameters;
1647 public AParametersCollection Parameters {
1654 public override string GetSignatureForDocumentation ()
1656 return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1659 public override string GetSignatureForError ()
1661 return DeclaringType.GetSignatureForError () + ".this" + parameters.GetSignatureForError ("[", "]", parameters.Count);
1664 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1666 var spec = (IndexerSpec) base.InflateMember (inflator);
1667 spec.parameters = parameters.Inflate (inflator);
1671 public override List<TypeSpec> ResolveMissingDependencies ()
1673 var missing = base.ResolveMissingDependencies ();
1674 foreach (var pt in parameters.Types) {
1675 var m = pt.GetMissingDependencies ();
1679 if (missing == null)
1680 missing = new List<TypeSpec> ();
1682 missing.AddRange (m);