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, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
38 : base (parent, type, mod, allowed_mod, name, attrs)
42 protected void CheckReservedNameConflict (string prefix, MethodSpec accessor)
45 AParametersCollection parameters;
46 if (accessor != null) {
48 parameters = accessor.Parameters;
50 name = prefix + ShortName;
52 name = MemberName.Left + "." + name;
54 if (this is Indexer) {
55 parameters = ((Indexer) this).ParameterInfo;
56 if (prefix[0] == 's') {
57 var data = new IParameterData[parameters.Count + 1];
58 Array.Copy (parameters.FixedParameters, data, data.Length - 1);
59 data[data.Length - 1] = new ParameterData ("value", Parameter.Modifier.NONE);
60 var types = new TypeSpec[data.Length];
61 Array.Copy (parameters.Types, types, data.Length - 1);
62 types[data.Length - 1] = member_type;
64 parameters = new ParametersImported (data, types, false);
68 parameters = ParametersCompiled.CreateFullyResolved (new[] { member_type });
70 parameters = ParametersCompiled.EmptyReadOnlyParameters;
74 var conflict = MemberCache.FindMember (Parent.Definition,
75 new MemberFilter (name, 0, MemberKind.Method, parameters, null),
76 BindingRestriction.DeclaredOnly | BindingRestriction.NoAccessors);
78 if (conflict != null) {
79 Report.SymbolRelatedToPreviousError (conflict);
80 Report.Error (82, Location, "A member `{0}' is already reserved", conflict.GetSignatureForError ());
84 protected override bool VerifyClsCompliance ()
86 if (!base.VerifyClsCompliance ())
89 if (!MemberType.IsCLSCompliant ()) {
90 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
91 GetSignatureForError ());
98 public class PropertySpec : MemberSpec, IInterfaceMemberSpec
104 public PropertySpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, PropertyInfo info, Modifiers modifiers)
105 : base (kind, declaringType, definition, modifiers)
108 this.memberType = memberType;
113 public MethodSpec Get {
119 get.IsAccessor = true;
123 public MethodSpec Set {
129 set.IsAccessor = true;
133 public bool HasDifferentAccessibility {
135 return HasGet && HasSet &&
136 (Get.Modifiers & Modifiers.AccessibilityMask) != (Set.Modifiers & Modifiers.AccessibilityMask);
152 public PropertyInfo MetaInfo {
154 if ((state & StateFlags.PendingMetaInflate) != 0)
155 throw new NotSupportedException ();
161 public TypeSpec MemberType {
169 public override MemberSpec InflateMember (TypeParameterInflator inflator)
171 var ps = (PropertySpec) base.InflateMember (inflator);
172 ps.memberType = inflator.Inflate (memberType);
176 public override List<TypeSpec> ResolveMissingDependencies ()
178 return memberType.ResolveMissingDependencies ();
183 // Properties and Indexers both generate PropertyBuilders, we use this to share
184 // their common bits.
186 abstract public class PropertyBase : PropertyBasedMember {
188 public class GetMethod : PropertyMethod
190 static readonly string[] attribute_targets = new string [] { "method", "return" };
192 internal const string Prefix = "get_";
194 public GetMethod (PropertyBase method, Modifiers modifiers, Attributes attrs, Location loc)
195 : base (method, Prefix, modifiers, attrs, loc)
199 public override MethodBuilder Define (DeclSpace parent)
201 base.Define (parent);
203 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags);
205 method_data = new MethodData (method, ModFlags, flags, this);
207 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
210 Spec.SetMetaInfo (method_data.MethodBuilder);
212 return method_data.MethodBuilder;
215 public override TypeSpec ReturnType {
217 return method.MemberType;
221 public override ParametersCompiled ParameterInfo {
223 return ParametersCompiled.EmptyReadOnlyParameters;
227 public override string[] ValidAttributeTargets {
229 return attribute_targets;
234 public class SetMethod : PropertyMethod {
236 static readonly string[] attribute_targets = new string[] { "method", "param", "return" };
238 internal const string Prefix = "set_";
240 protected ParametersCompiled parameters;
242 public SetMethod (PropertyBase method, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
243 : base (method, Prefix, modifiers, attrs, loc)
245 this.parameters = parameters;
248 protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
250 if (a.Target == AttributeTargets.Parameter) {
251 parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa);
255 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
258 public override ParametersCompiled ParameterInfo {
264 public override MethodBuilder Define (DeclSpace parent)
266 parameters.Resolve (this);
268 base.Define (parent);
270 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags);
272 method_data = new MethodData (method, ModFlags, flags, this);
274 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
277 Spec.SetMetaInfo (method_data.MethodBuilder);
279 return method_data.MethodBuilder;
282 public override TypeSpec ReturnType {
284 return Parent.Compiler.BuiltinTypes.Void;
288 public override string[] ValidAttributeTargets {
290 return attribute_targets;
295 static readonly string[] attribute_targets = new string[] { "property" };
297 public abstract class PropertyMethod : AbstractPropertyEventMethod
299 const Modifiers AllowedModifiers =
301 Modifiers.PROTECTED |
305 protected readonly PropertyBase method;
306 protected MethodAttributes flags;
308 public PropertyMethod (PropertyBase method, string prefix, Modifiers modifiers, Attributes attrs, Location loc)
309 : base (method, prefix, attrs, loc)
311 this.method = method;
312 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, modifiers, 0, loc, Report);
313 this.ModFlags |= (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
316 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
318 if (a.Type == pa.MethodImpl) {
319 method.is_external_implementation = a.IsInternalCall ();
322 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
325 public override AttributeTargets AttributeTargets {
327 return AttributeTargets.Method;
331 public override bool IsClsComplianceRequired ()
333 return method.IsClsComplianceRequired ();
336 public virtual MethodBuilder Define (DeclSpace parent)
338 TypeContainer container = parent.PartialContainer;
341 // Check for custom access modifier
343 if ((ModFlags & Modifiers.AccessibilityMask) == 0) {
344 ModFlags |= method.ModFlags;
345 flags = method.flags;
347 if (container.Kind == MemberKind.Interface)
348 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
349 GetSignatureForError ());
350 else if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
351 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
354 CheckModifiers (ModFlags);
355 ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask));
356 ModFlags |= Modifiers.PROPERTY_CUSTOM;
357 flags = ModifiersExtensions.MethodAttr (ModFlags);
358 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
361 CheckAbstractAndExtern (block != null);
362 CheckProtectedModifier ();
364 if (block != null && block.IsIterator)
365 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
370 public bool HasCustomAccessModifier {
372 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
376 public PropertyBase Property {
382 public override ObsoleteAttribute GetAttributeObsolete ()
384 return method.GetAttributeObsolete ();
387 public override string GetSignatureForError()
389 return method.GetSignatureForError () + "." + prefix.Substring (0, 3);
392 void CheckModifiers (Modifiers modflags)
394 if (!ModifiersExtensions.IsRestrictedModifier (modflags & Modifiers.AccessibilityMask, method.ModFlags & Modifiers.AccessibilityMask)) {
395 Report.Error (273, Location,
396 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
397 GetSignatureForError (), method.GetSignatureForError ());
402 PropertyMethod get, set, first;
403 PropertyBuilder PropertyBuilder;
405 public PropertyBase (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags,
406 Modifiers allowed_mod, MemberName name, Attributes attrs)
407 : base (parent, type, mod_flags, allowed_mod, name, attrs)
413 public override AttributeTargets AttributeTargets {
415 return AttributeTargets.Property;
419 public PropertyMethod AccessorFirst {
425 public PropertyMethod AccessorSecond {
427 return first == get ? set : get;
431 public override Variance ExpectedMemberTypeVariance {
433 return (get != null && set != null) ?
434 Variance.None : set == null ?
436 Variance.Contravariant;
440 public PropertyMethod Get {
449 Parent.AddMember (get);
453 public PropertyMethod Set {
462 Parent.AddMember (set);
466 public override string[] ValidAttributeTargets {
468 return attribute_targets;
474 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
476 if (a.HasSecurityAttribute) {
477 a.Error_InvalidSecurityParent ();
481 if (a.Type == pa.Dynamic) {
482 a.Error_MisusedDynamicAttribute ();
486 PropertyBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
489 void CheckMissingAccessor (MemberKind kind, ParametersCompiled parameters, bool get)
491 if (IsExplicitImpl) {
493 if (kind == MemberKind.Indexer)
494 filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, kind, parameters, null);
496 filter = new MemberFilter (MemberName.Name, 0, kind, null, null);
498 var implementing = MemberCache.FindMember (InterfaceType, filter, BindingRestriction.DeclaredOnly) as PropertySpec;
500 if (implementing == null)
503 var accessor = get ? implementing.Get : implementing.Set;
504 if (accessor != null) {
505 Report.SymbolRelatedToPreviousError (accessor);
506 Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
507 GetSignatureForError (), accessor.GetSignatureForError ());
512 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
514 var ok = base.CheckOverrideAgainstBase (base_member);
517 // Check base property accessors conflict
519 var base_prop = (PropertySpec) base_member;
521 if (!base_prop.HasGet) {
523 Report.SymbolRelatedToPreviousError (base_prop);
524 Report.Error (545, Get.Location,
525 "`{0}': cannot override because `{1}' does not have an overridable get accessor",
526 Get.GetSignatureForError (), base_prop.GetSignatureForError ());
529 } else if (Get.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
530 if (!CheckAccessModifiers (Get, base_prop.Get)) {
531 Error_CannotChangeAccessModifiers (Get, base_prop.Get);
538 if (!base_prop.HasSet) {
540 Report.SymbolRelatedToPreviousError (base_prop);
541 Report.Error (546, Set.Location,
542 "`{0}': cannot override because `{1}' does not have an overridable set accessor",
543 Set.GetSignatureForError (), base_prop.GetSignatureForError ());
546 } else if (Set.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
547 if (!CheckAccessModifiers (Set, base_prop.Set)) {
548 Error_CannotChangeAccessModifiers (Set, base_prop.Set);
554 if ((Set == null || !Set.HasCustomAccessModifier) && (Get == null || !Get.HasCustomAccessModifier)) {
555 if (!CheckAccessModifiers (this, base_prop)) {
556 Error_CannotChangeAccessModifiers (this, base_prop);
564 protected override void DoMemberTypeDependentChecks ()
566 base.DoMemberTypeDependentChecks ();
570 if (MemberType.IsStatic)
571 Error_StaticReturnType ();
574 protected override void DoMemberTypeIndependentChecks ()
576 base.DoMemberTypeIndependentChecks ();
579 // Accessors modifiers check
581 if (AccessorSecond != null) {
582 if ((Get.ModFlags & Modifiers.AccessibilityMask) != 0 && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) {
583 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
584 GetSignatureForError ());
586 } else if ((ModFlags & Modifiers.OVERRIDE) == 0 &&
587 (Get == null && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) ||
588 (Set == null && (Get.ModFlags & Modifiers.AccessibilityMask) != 0)) {
589 Report.Error (276, Location,
590 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
591 GetSignatureForError ());
595 protected bool DefineAccessors ()
597 first.Define (Parent);
598 if (AccessorSecond != null)
599 AccessorSecond.Define (Parent);
604 protected void DefineBuilders (MemberKind kind, ParametersCompiled parameters)
606 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
607 GetFullName (MemberName), PropertyAttributes.None,
608 #if !BOOTSTRAP_BASIC // Requires trunk version mscorlib
609 IsStatic ? 0 : CallingConventions.HasThis,
611 MemberType.GetMetaInfo (), null, null,
612 parameters.GetMetaInfo (), null, null);
615 if (kind == MemberKind.Indexer)
616 spec = new IndexerSpec (Parent.Definition, this, MemberType, parameters, PropertyBuilder, ModFlags);
618 spec = new PropertySpec (kind, Parent.Definition, this, MemberType, PropertyBuilder, ModFlags);
623 var method = Get.Spec.GetMetaInfo () as MethodBuilder;
624 if (method != null) {
625 PropertyBuilder.SetGetMethod (method);
626 Parent.MemberCache.AddMember (this, method.Name, Get.Spec);
629 CheckMissingAccessor (kind, parameters, true);
635 var method = Set.Spec.GetMetaInfo () as MethodBuilder;
636 if (method != null) {
637 PropertyBuilder.SetSetMethod (method);
638 Parent.MemberCache.AddMember (this, method.Name, Set.Spec);
641 CheckMissingAccessor (kind, parameters, false);
644 Parent.MemberCache.AddMember (this, PropertyBuilder.Name, spec);
647 public override void Emit ()
649 CheckReservedNameConflict (GetMethod.Prefix, get == null ? null : get.Spec);
650 CheckReservedNameConflict (SetMethod.Prefix, set == null ? null : set.Spec);
652 if (OptAttributes != null)
653 OptAttributes.Emit ();
655 if (member_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
656 Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder);
657 } else if (member_type.HasDynamicElement) {
658 Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder, member_type, Location);
661 ConstraintChecker.Check (this, member_type, type_expr.Location);
664 if (AccessorSecond != null)
665 AccessorSecond.Emit (Parent);
670 public override bool IsUsed {
675 return Get.IsUsed | Set.IsUsed;
679 protected override void SetMemberName (MemberName new_name)
681 base.SetMemberName (new_name);
684 Get.UpdateName (this);
687 Set.UpdateName (this);
691 // Represents header string for documentation comment.
693 public override string DocCommentHeader {
698 public class Property : PropertyBase
700 public sealed class BackingField : Field
702 readonly Property property;
704 public BackingField (Property p)
705 : base (p.Parent, p.type_expr,
706 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
707 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
712 public Property OriginalProperty {
718 public override string GetSignatureForError ()
720 return property.GetSignatureForError ();
724 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
725 MemberName name, Attributes attrs)
726 : base (parent, type, mod,
727 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
728 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
729 AllowedModifiersClass,
734 public override void Accept (StructuralVisitor visitor)
736 visitor.Visit (this);
740 void CreateAutomaticProperty ()
742 // Create backing field
743 Field field = new BackingField (this);
744 if (!field.Define ())
747 Parent.PartialContainer.AddField (field);
749 FieldExpr fe = new FieldExpr (field, Location);
750 if ((field.ModFlags & Modifiers.STATIC) == 0)
751 fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
754 Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
755 Return r = new Return (fe, Location);
756 Get.Block.AddStatement (r);
759 Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location);
760 Assign a = new SimpleAssign (fe, new SimpleName ("value", Location));
761 Set.Block.AddStatement (new StatementExpression (a));
764 public override bool Define ()
769 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
771 if (!IsInterface && (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
772 AccessorSecond != null && Get.Block == null && Set.Block == null) {
773 if (Compiler.Settings.Version <= LanguageVersion.ISO_2)
774 Report.FeatureIsNotAvailable (Compiler, Location, "automatically implemented properties");
776 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
777 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
778 CreateAutomaticProperty ();
781 if (!DefineAccessors ())
784 if (AccessorSecond == null) {
786 if (AccessorFirst is GetMethod)
787 pm = new SetMethod (this, 0, ParametersCompiled.EmptyReadOnlyParameters, null, Location);
789 pm = new GetMethod (this, 0, null, Location);
791 Parent.AddMember (pm);
797 DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters);
801 public override void Emit ()
803 if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
804 Report.Error (842, Location,
805 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
806 GetSignatureForError ());
814 /// For case when event is declared like property (with add and remove accessors).
816 public class EventProperty: Event {
817 public abstract class AEventPropertyAccessor : AEventAccessor
819 protected AEventPropertyAccessor (EventProperty method, string prefix, Attributes attrs, Location loc)
820 : base (method, prefix, attrs, loc)
824 public override MethodBuilder Define (DeclSpace ds)
826 CheckAbstractAndExtern (block != null);
827 return base.Define (ds);
830 public override string GetSignatureForError ()
832 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
836 public sealed class AddDelegateMethod: AEventPropertyAccessor
838 public AddDelegateMethod (EventProperty method, Attributes attrs, Location loc)
839 : base (method, AddPrefix, attrs, loc)
844 public sealed class RemoveDelegateMethod: AEventPropertyAccessor
846 public RemoveDelegateMethod (EventProperty method, Attributes attrs, Location loc)
847 : base (method, RemovePrefix, attrs, loc)
852 static readonly string[] attribute_targets = new string [] { "event" };
854 public EventProperty (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
855 : base (parent, type, mod_flags, name, attrs)
859 public override void Accept (StructuralVisitor visitor)
861 visitor.Visit (this);
864 public override bool Define()
873 public override string[] ValidAttributeTargets {
875 return attribute_targets;
881 /// Event is declared like field.
883 public class EventField : Event
885 abstract class EventFieldAccessor : AEventAccessor
887 protected EventFieldAccessor (EventField method, string prefix)
888 : base (method, prefix, null, method.Location)
892 protected abstract MethodSpec GetOperation (Location loc);
894 public override void Emit (DeclSpace parent)
896 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
897 block = new ToplevelBlock (Compiler, ParameterInfo, Location);
898 FabricateBodyStatement ();
904 void FabricateBodyStatement ()
907 // Delegate obj1 = backing_field
909 // Delegate obj2 = obj1;
910 // obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1);
911 // } while ((object)obj1 != (object)obj2)
914 var field_info = ((EventField) method).backing_field;
915 FieldExpr f_expr = new FieldExpr (field_info, Location);
917 f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
919 var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
920 var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
922 block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr)));
924 var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality,
925 new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj1, Location), Location),
926 new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, 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, 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, GetFullName (MemberName), 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 // Attribute was copied to container
1530 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1533 protected override bool CheckForDuplications ()
1535 return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1538 public override bool Define ()
1540 if (!base.Define ())
1543 if (!DefineParameters (parameters))
1546 if (OptAttributes != null) {
1547 Attribute indexer_attr = OptAttributes.Search (Module.PredefinedAttributes.IndexerName);
1548 if (indexer_attr != null) {
1549 var compiling = indexer_attr.Type.MemberDefinition as TypeContainer;
1550 if (compiling != null)
1551 compiling.Define ();
1553 if (IsExplicitImpl) {
1554 Report.Error (415, indexer_attr.Location,
1555 "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration",
1556 indexer_attr.Type.GetSignatureForError ());
1557 } else if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1558 Report.Error (609, indexer_attr.Location,
1559 "Cannot set the `IndexerName' attribute on an indexer marked override");
1561 string name = indexer_attr.GetIndexerAttributeValue ();
1563 if (!string.IsNullOrEmpty (name)) {
1564 SetMemberName (new MemberName (MemberName.Left, name, Location));
1570 if (InterfaceType != null) {
1571 string base_IndexerName = InterfaceType.MemberDefinition.GetAttributeDefaultMember ();
1572 if (base_IndexerName != ShortName) {
1573 SetMemberName (new MemberName (MemberName.Left, base_IndexerName, new TypeExpression (InterfaceType, Location), Location));
1577 if (!Parent.PartialContainer.AddMember (this))
1580 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1582 if (!DefineAccessors ())
1588 DefineBuilders (MemberKind.Indexer, parameters);
1592 public override bool EnableOverloadChecks (MemberCore overload)
1594 if (overload is Indexer) {
1595 caching_flags |= Flags.MethodOverloadsExist;
1599 return base.EnableOverloadChecks (overload);
1602 public override void Emit ()
1604 parameters.CheckConstraints (this);
1609 public override string GetSignatureForError ()
1611 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
1612 if (MemberName.ExplicitInterface != null) {
1614 sb.Append (MemberName.ExplicitInterface.GetSignatureForError ());
1617 sb.Append (".this");
1618 sb.Append (parameters.GetSignatureForError ("[", "]", parameters.Count));
1619 return sb.ToString ();
1622 public override string GetSignatureForDocumentation ()
1624 return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1627 protected override bool VerifyClsCompliance ()
1629 if (!base.VerifyClsCompliance ())
1632 parameters.VerifyClsCompliance (this);
1637 public class IndexerSpec : PropertySpec, IParametersMember
1639 AParametersCollection parameters;
1641 public IndexerSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, AParametersCollection parameters, PropertyInfo info, Modifiers modifiers)
1642 : base (MemberKind.Indexer, declaringType, definition, memberType, info, modifiers)
1644 this.parameters = parameters;
1648 public AParametersCollection Parameters {
1655 public override string GetSignatureForDocumentation ()
1657 return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1660 public override string GetSignatureForError ()
1662 return DeclaringType.GetSignatureForError () + ".this" + parameters.GetSignatureForError ("[", "]", parameters.Count);
1665 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1667 var spec = (IndexerSpec) base.InflateMember (inflator);
1668 spec.parameters = parameters.Inflate (inflator);
1672 public override List<TypeSpec> ResolveMissingDependencies ()
1674 var missing = base.ResolveMissingDependencies ();
1675 foreach (var pt in parameters.Types) {
1676 var m = pt.GetMissingDependencies ();
1680 if (missing == null)
1681 missing = new List<TypeSpec> ();
1683 missing.AddRange (m);