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;
18 using Mono.CompilerServices.SymbolWriter;
21 using XmlElement = System.Object;
25 using IKVM.Reflection;
26 using IKVM.Reflection.Emit;
28 using System.Reflection;
29 using System.Reflection.Emit;
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 (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
39 : base (parent, type, mod, allowed_mod, name, attrs)
43 protected void CheckReservedNameConflict (string prefix, MethodSpec accessor)
46 AParametersCollection parameters;
47 if (accessor != null) {
49 parameters = accessor.Parameters;
51 name = prefix + ShortName;
53 name = MemberName.Left + "." + name;
55 if (this is Indexer) {
56 parameters = ((Indexer) this).ParameterInfo;
57 if (prefix[0] == 's') {
58 var data = new IParameterData[parameters.Count + 1];
59 Array.Copy (parameters.FixedParameters, data, data.Length - 1);
60 data[data.Length - 1] = new ParameterData ("value", Parameter.Modifier.NONE);
61 var types = new TypeSpec[data.Length];
62 Array.Copy (parameters.Types, types, data.Length - 1);
63 types[data.Length - 1] = member_type;
65 parameters = new ParametersImported (data, types, false);
69 parameters = ParametersCompiled.CreateFullyResolved (new[] { member_type });
71 parameters = ParametersCompiled.EmptyReadOnlyParameters;
75 var conflict = MemberCache.FindMember (Parent.Definition,
76 new MemberFilter (name, 0, MemberKind.Method, parameters, null),
77 BindingRestriction.DeclaredOnly | BindingRestriction.NoAccessors);
79 if (conflict != null) {
80 Report.SymbolRelatedToPreviousError (conflict);
81 Report.Error (82, Location, "A member `{0}' is already reserved", conflict.GetSignatureForError ());
85 protected override bool VerifyClsCompliance ()
87 if (!base.VerifyClsCompliance ())
90 if (!MemberType.IsCLSCompliant ()) {
91 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
92 GetSignatureForError ());
99 public class PropertySpec : MemberSpec, IInterfaceMemberSpec
105 public PropertySpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, PropertyInfo info, Modifiers modifiers)
106 : base (kind, declaringType, definition, modifiers)
109 this.memberType = memberType;
114 public MethodSpec Get {
120 get.IsAccessor = true;
124 public MethodSpec Set {
130 set.IsAccessor = true;
134 public bool HasDifferentAccessibility {
136 return HasGet && HasSet &&
137 (Get.Modifiers & Modifiers.AccessibilityMask) != (Set.Modifiers & Modifiers.AccessibilityMask);
153 public PropertyInfo MetaInfo {
155 if ((state & StateFlags.PendingMetaInflate) != 0)
156 throw new NotSupportedException ();
162 public TypeSpec MemberType {
170 public override MemberSpec InflateMember (TypeParameterInflator inflator)
172 var ps = (PropertySpec) base.InflateMember (inflator);
173 ps.memberType = inflator.Inflate (memberType);
177 public override List<TypeSpec> ResolveMissingDependencies ()
179 return memberType.ResolveMissingDependencies ();
184 // Properties and Indexers both generate PropertyBuilders, we use this to share
185 // their common bits.
187 abstract public class PropertyBase : PropertyBasedMember {
189 public class GetMethod : PropertyMethod
191 static readonly string[] attribute_targets = new string [] { "method", "return" };
193 internal const string Prefix = "get_";
195 public GetMethod (PropertyBase method, Modifiers modifiers, Attributes attrs, Location loc)
196 : base (method, Prefix, modifiers, attrs, loc)
200 public override MethodBuilder Define (TypeContainer parent)
202 base.Define (parent);
204 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags);
206 method_data = new MethodData (method, ModFlags, flags, this);
208 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
211 Spec.SetMetaInfo (method_data.MethodBuilder);
213 return method_data.MethodBuilder;
216 public override TypeSpec ReturnType {
218 return method.MemberType;
222 public override ParametersCompiled ParameterInfo {
224 return ParametersCompiled.EmptyReadOnlyParameters;
228 public override string[] ValidAttributeTargets {
230 return attribute_targets;
235 public class SetMethod : PropertyMethod {
237 static readonly string[] attribute_targets = new string[] { "method", "param", "return" };
239 internal const string Prefix = "set_";
241 protected ParametersCompiled parameters;
243 public SetMethod (PropertyBase method, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
244 : base (method, Prefix, modifiers, attrs, loc)
246 this.parameters = parameters;
249 protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
251 if (a.Target == AttributeTargets.Parameter) {
252 parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa);
256 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
259 public override ParametersCompiled ParameterInfo {
265 public override MethodBuilder Define (TypeContainer parent)
267 parameters.Resolve (this);
269 base.Define (parent);
271 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags);
273 method_data = new MethodData (method, ModFlags, flags, this);
275 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
278 Spec.SetMetaInfo (method_data.MethodBuilder);
280 return method_data.MethodBuilder;
283 public override TypeSpec ReturnType {
285 return Parent.Compiler.BuiltinTypes.Void;
289 public override string[] ValidAttributeTargets {
291 return attribute_targets;
296 static readonly string[] attribute_targets = new string[] { "property" };
298 public abstract class PropertyMethod : AbstractPropertyEventMethod
300 const Modifiers AllowedModifiers =
302 Modifiers.PROTECTED |
306 protected readonly PropertyBase method;
307 protected MethodAttributes flags;
309 public PropertyMethod (PropertyBase method, string prefix, Modifiers modifiers, Attributes attrs, Location loc)
310 : base (method, prefix, attrs, loc)
312 this.method = method;
313 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, modifiers, 0, loc, Report);
314 this.ModFlags |= (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
317 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
319 if (a.Type == pa.MethodImpl) {
320 method.is_external_implementation = a.IsInternalCall ();
323 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
326 public override AttributeTargets AttributeTargets {
328 return AttributeTargets.Method;
332 public override bool IsClsComplianceRequired ()
334 return method.IsClsComplianceRequired ();
337 public virtual MethodBuilder Define (TypeContainer parent)
339 var container = parent.PartialContainer;
342 // Check for custom access modifier
344 if ((ModFlags & Modifiers.AccessibilityMask) == 0) {
345 ModFlags |= method.ModFlags;
346 flags = method.flags;
348 if (container.Kind == MemberKind.Interface)
349 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
350 GetSignatureForError ());
351 else if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
352 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
355 CheckModifiers (ModFlags);
356 ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask));
357 ModFlags |= Modifiers.PROPERTY_CUSTOM;
358 flags = ModifiersExtensions.MethodAttr (ModFlags);
359 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
362 CheckAbstractAndExtern (block != null);
363 CheckProtectedModifier ();
365 if (block != null && block.IsIterator)
366 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
371 public bool HasCustomAccessModifier {
373 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
377 public PropertyBase Property {
383 public override ObsoleteAttribute GetAttributeObsolete ()
385 return method.GetAttributeObsolete ();
388 public override string GetSignatureForError()
390 return method.GetSignatureForError () + "." + prefix.Substring (0, 3);
393 void CheckModifiers (Modifiers modflags)
395 if (!ModifiersExtensions.IsRestrictedModifier (modflags & Modifiers.AccessibilityMask, method.ModFlags & Modifiers.AccessibilityMask)) {
396 Report.Error (273, Location,
397 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
398 GetSignatureForError (), method.GetSignatureForError ());
403 PropertyMethod get, set, first;
404 PropertyBuilder PropertyBuilder;
406 public PropertyBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, 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.AddNameToContainer (get, get.MemberName.Basename);
453 public PropertyMethod Set {
462 Parent.AddNameToContainer (set, set.MemberName.Basename);
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);
690 public override void WriteDebugSymbol (MonoSymbolFile file)
693 get.WriteDebugSymbol (file);
696 set.WriteDebugSymbol (file);
700 // Represents header string for documentation comment.
702 public override string DocCommentHeader {
707 public class Property : PropertyBase
709 public sealed class BackingField : Field
711 readonly Property property;
713 public BackingField (Property p)
714 : base (p.Parent, p.type_expr,
715 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
716 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
721 public Property OriginalProperty {
727 public override string GetSignatureForError ()
729 return property.GetSignatureForError ();
733 public Property (TypeDefinition parent, FullNamedExpression type, Modifiers mod,
734 MemberName name, Attributes attrs)
735 : base (parent, type, mod,
736 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
737 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
738 AllowedModifiersClass,
743 public override void Accept (StructuralVisitor visitor)
745 visitor.Visit (this);
749 void CreateAutomaticProperty ()
751 // Create backing field
752 Field field = new BackingField (this);
753 if (!field.Define ())
756 Parent.PartialContainer.Members.Add (field);
758 FieldExpr fe = new FieldExpr (field, Location);
759 if ((field.ModFlags & Modifiers.STATIC) == 0)
760 fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
763 // Create get block but we careful with location to
764 // emit only single sequence point per accessor. This allow
765 // to set a breakpoint on it even with no user code
767 Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location.Null);
768 Return r = new Return (fe, Get.Location);
769 Get.Block.AddStatement (r);
772 Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location.Null);
773 Assign a = new SimpleAssign (fe, new SimpleName ("value", Location.Null), Location.Null);
774 Set.Block.AddStatement (new StatementExpression (a, Set.Location));
777 public override bool Define ()
782 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
784 if (!IsInterface && (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
785 AccessorSecond != null && Get.Block == null && Set.Block == null) {
786 if (Compiler.Settings.Version <= LanguageVersion.ISO_2)
787 Report.FeatureIsNotAvailable (Compiler, Location, "automatically implemented properties");
789 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
790 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
791 CreateAutomaticProperty ();
794 if (!DefineAccessors ())
797 if (AccessorSecond == null) {
799 if (AccessorFirst is GetMethod)
800 pm = new SetMethod (this, 0, ParametersCompiled.EmptyReadOnlyParameters, null, Location);
802 pm = new GetMethod (this, 0, null, Location);
804 Parent.AddNameToContainer (pm, pm.MemberName.Basename);
810 DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters);
814 public override void Emit ()
816 if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
817 Report.Error (842, Location,
818 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
819 GetSignatureForError ());
827 /// For case when event is declared like property (with add and remove accessors).
829 public class EventProperty: Event {
830 public abstract class AEventPropertyAccessor : AEventAccessor
832 protected AEventPropertyAccessor (EventProperty method, string prefix, Attributes attrs, Location loc)
833 : base (method, prefix, attrs, loc)
837 public override MethodBuilder Define (TypeContainer ds)
839 CheckAbstractAndExtern (block != null);
840 return base.Define (ds);
843 public override string GetSignatureForError ()
845 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
849 public sealed class AddDelegateMethod: AEventPropertyAccessor
851 public AddDelegateMethod (EventProperty method, Attributes attrs, Location loc)
852 : base (method, AddPrefix, attrs, loc)
857 public sealed class RemoveDelegateMethod: AEventPropertyAccessor
859 public RemoveDelegateMethod (EventProperty method, Attributes attrs, Location loc)
860 : base (method, RemovePrefix, attrs, loc)
865 static readonly string[] attribute_targets = new string [] { "event" };
867 public EventProperty (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
868 : base (parent, type, mod_flags, name, attrs)
872 public override void Accept (StructuralVisitor visitor)
874 visitor.Visit (this);
877 public override bool Define()
886 public override string[] ValidAttributeTargets {
888 return attribute_targets;
894 /// Event is declared like field.
896 public class EventField : Event
898 abstract class EventFieldAccessor : AEventAccessor
900 protected EventFieldAccessor (EventField method, string prefix)
901 : base (method, prefix, null, method.Location)
905 protected abstract MethodSpec GetOperation (Location loc);
907 public override void Emit (TypeDefinition parent)
909 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
910 block = new ToplevelBlock (Compiler, ParameterInfo, Location) {
911 IsCompilerGenerated = true
913 FabricateBodyStatement ();
919 void FabricateBodyStatement ()
922 // Delegate obj1 = backing_field
924 // Delegate obj2 = obj1;
925 // obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1);
926 // } while ((object)obj1 != (object)obj2)
929 var field_info = ((EventField) method).backing_field;
930 FieldExpr f_expr = new FieldExpr (field_info, Location);
932 f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
934 var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
935 var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
937 block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr)));
939 var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality,
940 new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj1, Location), Location),
941 new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj2, Location), Location),
944 var body = new ExplicitBlock (block, Location, Location);
945 block.AddStatement (new Do (body, cond, Location));
947 body.AddStatement (new StatementExpression (
948 new SimpleAssign (new LocalVariableReference (obj2, Location), new LocalVariableReference (obj1, Location))));
950 var args_oper = new Arguments (2);
951 args_oper.Add (new Argument (new LocalVariableReference (obj2, Location)));
952 args_oper.Add (new Argument (block.GetParameterReference (0, Location)));
954 var op_method = GetOperation (Location);
956 var args = new Arguments (3);
957 args.Add (new Argument (f_expr, Argument.AType.Ref));
958 args.Add (new Argument (new Cast (
959 new TypeExpression (field_info.MemberType, Location),
960 new Invocation (MethodGroupExpr.CreatePredefined (op_method, op_method.DeclaringType, Location), args_oper),
962 args.Add (new Argument (new LocalVariableReference (obj1, Location)));
964 var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location);
968 body.AddStatement (new StatementExpression (new SimpleAssign (
969 new LocalVariableReference (obj1, Location),
970 new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args))));
974 sealed class AddDelegateMethod: EventFieldAccessor
976 public AddDelegateMethod (EventField method):
977 base (method, AddPrefix)
981 protected override MethodSpec GetOperation (Location loc)
983 return Module.PredefinedMembers.DelegateCombine.Resolve (loc);
987 sealed class RemoveDelegateMethod: EventFieldAccessor
989 public RemoveDelegateMethod (EventField method):
990 base (method, RemovePrefix)
994 protected override MethodSpec GetOperation (Location loc)
996 return Module.PredefinedMembers.DelegateRemove.Resolve (loc);
1001 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
1002 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
1004 Expression initializer;
1005 Field backing_field;
1006 List<FieldDeclarator> declarators;
1008 public EventField (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1009 : base (parent, type, mod_flags, name, attrs)
1011 Add = new AddDelegateMethod (this);
1012 Remove = new RemoveDelegateMethod (this);
1017 public List<FieldDeclarator> Declarators {
1019 return this.declarators;
1023 bool HasBackingField {
1025 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
1029 public Expression Initializer {
1034 initializer = value;
1038 public override string[] ValidAttributeTargets {
1040 return HasBackingField ? attribute_targets : attribute_targets_interface;
1047 public override void Accept (StructuralVisitor visitor)
1049 visitor.Visit (this);
1052 public void AddDeclarator (FieldDeclarator declarator)
1054 if (declarators == null)
1055 declarators = new List<FieldDeclarator> (2);
1057 declarators.Add (declarator);
1059 Parent.AddNameToContainer (this, declarator.Name.Value);
1062 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1064 if (a.Target == AttributeTargets.Field) {
1065 backing_field.ApplyAttributeBuilder (a, ctor, cdata, pa);
1069 if (a.Target == AttributeTargets.Method) {
1070 int errors = Report.Errors;
1071 Add.ApplyAttributeBuilder (a, ctor, cdata, pa);
1072 if (errors == Report.Errors)
1073 Remove.ApplyAttributeBuilder (a, ctor, cdata, pa);
1077 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1080 public override bool Define()
1082 var mod_flags_src = ModFlags;
1084 if (!base.Define ())
1087 if (declarators != null) {
1088 if ((mod_flags_src & Modifiers.DEFAULT_ACCESS_MODIFER) != 0)
1089 mod_flags_src &= ~(Modifiers.AccessibilityMask | Modifiers.DEFAULT_ACCESS_MODIFER);
1091 var t = new TypeExpression (MemberType, TypeExpression.Location);
1092 foreach (var d in declarators) {
1093 var ef = new EventField (Parent, t, mod_flags_src, new MemberName (d.Name.Value, d.Name.Location), OptAttributes);
1095 if (d.Initializer != null)
1096 ef.initializer = d.Initializer;
1099 Parent.PartialContainer.Members.Add (ef);
1103 if (!HasBackingField) {
1108 if (Add.IsInterfaceImplementation)
1111 backing_field = new Field (Parent,
1112 new TypeExpression (MemberType, Location),
1113 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
1116 Parent.PartialContainer.Members.Add (backing_field);
1117 backing_field.Initializer = Initializer;
1118 backing_field.ModFlags &= ~Modifiers.COMPILER_GENERATED;
1120 // Call define because we passed fields definition
1121 backing_field.Define ();
1123 // Set backing field for event fields
1124 spec.BackingField = backing_field.Spec;
1130 public abstract class Event : PropertyBasedMember
1132 public abstract class AEventAccessor : AbstractPropertyEventMethod
1134 protected readonly Event method;
1135 readonly ParametersCompiled parameters;
1137 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
1139 public const string AddPrefix = "add_";
1140 public const string RemovePrefix = "remove_";
1142 protected AEventAccessor (Event method, string prefix, Attributes attrs, Location loc)
1143 : base (method, prefix, attrs, loc)
1145 this.method = method;
1146 this.ModFlags = method.ModFlags;
1147 this.parameters = ParametersCompiled.CreateImplicitParameter (method.TypeExpression, loc);
1150 public bool IsInterfaceImplementation {
1151 get { return method_data.implementing != null; }
1154 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1156 if (a.Type == pa.MethodImpl) {
1157 method.is_external_implementation = a.IsInternalCall ();
1160 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1163 protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1165 if (a.Target == AttributeTargets.Parameter) {
1166 parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa);
1170 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1173 public override AttributeTargets AttributeTargets {
1175 return AttributeTargets.Method;
1179 public override bool IsClsComplianceRequired ()
1181 return method.IsClsComplianceRequired ();
1184 public virtual MethodBuilder Define (TypeContainer parent)
1186 // Fill in already resolved event type to speed things up and
1187 // avoid confusing duplicate errors
1188 ((Parameter) parameters.FixedParameters[0]).Type = method.member_type;
1189 parameters.Types = new TypeSpec[] { method.member_type };
1191 method_data = new MethodData (method, method.ModFlags,
1192 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
1194 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
1197 MethodBuilder mb = method_data.MethodBuilder;
1199 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, mb, ParameterInfo, method.ModFlags);
1200 Spec.IsAccessor = true;
1205 public override TypeSpec ReturnType {
1207 return Parent.Compiler.BuiltinTypes.Void;
1211 public override ObsoleteAttribute GetAttributeObsolete ()
1213 return method.GetAttributeObsolete ();
1216 public override string[] ValidAttributeTargets {
1218 return attribute_targets;
1222 public override ParametersCompiled ParameterInfo {
1229 AEventAccessor add, remove;
1230 EventBuilder EventBuilder;
1231 protected EventSpec spec;
1233 protected Event (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1234 : base (parent, type, mod_flags,
1235 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
1236 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
1237 AllowedModifiersClass,
1244 public override AttributeTargets AttributeTargets {
1246 return AttributeTargets.Event;
1250 public AEventAccessor Add {
1256 Parent.AddNameToContainer (value, value.MemberName.Basename);
1260 public override Variance ExpectedMemberTypeVariance {
1262 return Variance.Contravariant;
1266 public AEventAccessor Remove {
1272 Parent.AddNameToContainer (value, value.MemberName.Basename);
1277 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1279 if ((a.HasSecurityAttribute)) {
1280 a.Error_InvalidSecurityParent ();
1284 EventBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1287 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
1289 var ok = base.CheckOverrideAgainstBase (base_member);
1291 if (!CheckAccessModifiers (this, base_member)) {
1292 Error_CannotChangeAccessModifiers (this, base_member);
1299 public override bool Define ()
1301 if (!base.Define ())
1304 if (!MemberType.IsDelegate) {
1305 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
1312 // Now define the accessors
1314 var AddBuilder = Add.Define (Parent);
1315 if (AddBuilder == null)
1318 var RemoveBuilder = remove.Define (Parent);
1319 if (RemoveBuilder == null)
1322 EventBuilder = Parent.TypeBuilder.DefineEvent (GetFullName (MemberName), EventAttributes.None, MemberType.GetMetaInfo ());
1323 EventBuilder.SetAddOnMethod (AddBuilder);
1324 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
1326 spec = new EventSpec (Parent.Definition, this, MemberType, ModFlags, Add.Spec, remove.Spec);
1328 Parent.MemberCache.AddMember (this, GetFullName (MemberName), spec);
1329 Parent.MemberCache.AddMember (this, AddBuilder.Name, Add.Spec);
1330 Parent.MemberCache.AddMember (this, RemoveBuilder.Name, remove.Spec);
1335 public override void Emit ()
1337 CheckReservedNameConflict (null, add.Spec);
1338 CheckReservedNameConflict (null, remove.Spec);
1340 if (OptAttributes != null) {
1341 OptAttributes.Emit ();
1344 ConstraintChecker.Check (this, member_type, type_expr.Location);
1347 Remove.Emit (Parent);
1352 public override void WriteDebugSymbol (MonoSymbolFile file)
1354 add.WriteDebugSymbol (file);
1355 remove.WriteDebugSymbol (file);
1359 // Represents header string for documentation comment.
1361 public override string DocCommentHeader {
1362 get { return "E:"; }
1366 public class EventSpec : MemberSpec, IInterfaceMemberSpec
1368 MethodSpec add, remove;
1369 FieldSpec backing_field;
1371 public EventSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec eventType, Modifiers modifiers, MethodSpec add, MethodSpec remove)
1372 : base (MemberKind.Event, declaringType, definition, modifiers)
1374 this.AccessorAdd = add;
1375 this.AccessorRemove = remove;
1376 this.MemberType = eventType;
1381 public MethodSpec AccessorAdd {
1390 public MethodSpec AccessorRemove {
1399 public FieldSpec BackingField {
1401 return backing_field;
1404 backing_field = value;
1408 public TypeSpec MemberType { get; private set; }
1412 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1414 var es = (EventSpec) base.InflateMember (inflator);
1415 es.MemberType = inflator.Inflate (MemberType);
1417 if (backing_field != null)
1418 es.backing_field = (FieldSpec) backing_field.InflateMember (inflator);
1423 public override List<TypeSpec> ResolveMissingDependencies ()
1425 return MemberType.ResolveMissingDependencies ();
1429 public class Indexer : PropertyBase, IParametersMember
1431 public class GetIndexerMethod : GetMethod, IParametersMember
1433 ParametersCompiled parameters;
1435 public GetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1436 : base (property, modifiers, attrs, loc)
1438 this.parameters = parameters;
1441 public override MethodBuilder Define (TypeContainer parent)
1443 // Disable reporting, parameters are resolved twice
1444 Report.DisableReporting ();
1446 parameters.Resolve (this);
1448 Report.EnableReporting ();
1451 return base.Define (parent);
1454 public override ParametersCompiled ParameterInfo {
1460 #region IParametersMember Members
1462 AParametersCollection IParametersMember.Parameters {
1468 TypeSpec IInterfaceMemberSpec.MemberType {
1477 public class SetIndexerMethod : SetMethod, IParametersMember
1479 public SetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1480 : base (property, modifiers, parameters, attrs, loc)
1484 #region IParametersMember Members
1486 AParametersCollection IParametersMember.Parameters {
1492 TypeSpec IInterfaceMemberSpec.MemberType {
1501 const Modifiers AllowedModifiers =
1504 Modifiers.PROTECTED |
1505 Modifiers.INTERNAL |
1509 Modifiers.OVERRIDE |
1514 const Modifiers AllowedInterfaceModifiers =
1517 readonly ParametersCompiled parameters;
1519 public Indexer (TypeDefinition parent, FullNamedExpression type, MemberName name, Modifiers mod, ParametersCompiled parameters, Attributes attrs)
1520 : base (parent, type, mod,
1521 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1524 this.parameters = parameters;
1529 AParametersCollection IParametersMember.Parameters {
1535 public ParametersCompiled ParameterInfo {
1544 public override void Accept (StructuralVisitor visitor)
1546 visitor.Visit (this);
1549 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1551 if (a.Type == pa.IndexerName) {
1552 // Attribute was copied to container
1556 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1559 protected override bool CheckForDuplications ()
1561 return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1564 public override bool Define ()
1566 if (!base.Define ())
1569 if (!DefineParameters (parameters))
1572 if (OptAttributes != null) {
1573 Attribute indexer_attr = OptAttributes.Search (Module.PredefinedAttributes.IndexerName);
1574 if (indexer_attr != null) {
1575 var compiling = indexer_attr.Type.MemberDefinition as TypeContainer;
1576 if (compiling != null)
1577 compiling.Define ();
1579 if (IsExplicitImpl) {
1580 Report.Error (415, indexer_attr.Location,
1581 "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration",
1582 indexer_attr.Type.GetSignatureForError ());
1583 } else if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1584 Report.Error (609, indexer_attr.Location,
1585 "Cannot set the `IndexerName' attribute on an indexer marked override");
1587 string name = indexer_attr.GetIndexerAttributeValue ();
1589 if (!string.IsNullOrEmpty (name)) {
1590 SetMemberName (new MemberName (MemberName.Left, name, Location));
1596 if (InterfaceType != null) {
1597 string base_IndexerName = InterfaceType.MemberDefinition.GetAttributeDefaultMember ();
1598 if (base_IndexerName != ShortName) {
1599 SetMemberName (new MemberName (MemberName.Left, base_IndexerName, new TypeExpression (InterfaceType, Location), Location));
1603 Parent.AddNameToContainer (this, MemberName.Basename);
1605 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1607 if (!DefineAccessors ())
1613 DefineBuilders (MemberKind.Indexer, parameters);
1617 public override bool EnableOverloadChecks (MemberCore overload)
1619 if (overload is Indexer) {
1620 caching_flags |= Flags.MethodOverloadsExist;
1624 return base.EnableOverloadChecks (overload);
1627 public override void Emit ()
1629 parameters.CheckConstraints (this);
1634 public override string GetSignatureForError ()
1636 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
1637 if (MemberName.ExplicitInterface != null) {
1639 sb.Append (MemberName.ExplicitInterface.GetSignatureForError ());
1642 sb.Append (".this");
1643 sb.Append (parameters.GetSignatureForError ("[", "]", parameters.Count));
1644 return sb.ToString ();
1647 public override string GetSignatureForDocumentation ()
1649 return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1652 protected override bool VerifyClsCompliance ()
1654 if (!base.VerifyClsCompliance ())
1657 parameters.VerifyClsCompliance (this);
1662 public class IndexerSpec : PropertySpec, IParametersMember
1664 AParametersCollection parameters;
1666 public IndexerSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, AParametersCollection parameters, PropertyInfo info, Modifiers modifiers)
1667 : base (MemberKind.Indexer, declaringType, definition, memberType, info, modifiers)
1669 this.parameters = parameters;
1673 public AParametersCollection Parameters {
1680 public override string GetSignatureForDocumentation ()
1682 return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1685 public override string GetSignatureForError ()
1687 return DeclaringType.GetSignatureForError () + ".this" + parameters.GetSignatureForError ("[", "]", parameters.Count);
1690 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1692 var spec = (IndexerSpec) base.InflateMember (inflator);
1693 spec.parameters = parameters.Inflate (inflator);
1697 public override List<TypeSpec> ResolveMissingDependencies ()
1699 var missing = base.ResolveMissingDependencies ();
1700 foreach (var pt in parameters.Types) {
1701 var m = pt.GetMissingDependencies ();
1705 if (missing == null)
1706 missing = new List<TypeSpec> ();
1708 missing.AddRange (m);