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 ();
366 if (block.IsIterator)
367 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
369 if (Compiler.Settings.WriteMetadataOnly)
376 public bool HasCustomAccessModifier {
378 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
382 public PropertyBase Property {
388 public override ObsoleteAttribute GetAttributeObsolete ()
390 return method.GetAttributeObsolete ();
393 public override string GetSignatureForError()
395 return method.GetSignatureForError () + "." + prefix.Substring (0, 3);
398 void CheckModifiers (Modifiers modflags)
400 if (!ModifiersExtensions.IsRestrictedModifier (modflags & Modifiers.AccessibilityMask, method.ModFlags & Modifiers.AccessibilityMask)) {
401 Report.Error (273, Location,
402 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
403 GetSignatureForError (), method.GetSignatureForError ());
408 PropertyMethod get, set, first;
409 PropertyBuilder PropertyBuilder;
411 public PropertyBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, Modifiers allowed_mod, MemberName name, Attributes attrs)
412 : base (parent, type, mod_flags, allowed_mod, name, attrs)
418 public override AttributeTargets AttributeTargets {
420 return AttributeTargets.Property;
424 public PropertyMethod AccessorFirst {
430 public PropertyMethod AccessorSecond {
432 return first == get ? set : get;
436 public override Variance ExpectedMemberTypeVariance {
438 return (get != null && set != null) ?
439 Variance.None : set == null ?
441 Variance.Contravariant;
445 public PropertyMethod Get {
454 Parent.AddNameToContainer (get, get.MemberName.Basename);
458 public PropertyMethod Set {
467 Parent.AddNameToContainer (set, set.MemberName.Basename);
471 public override string[] ValidAttributeTargets {
473 return attribute_targets;
479 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
481 if (a.HasSecurityAttribute) {
482 a.Error_InvalidSecurityParent ();
486 if (a.Type == pa.Dynamic) {
487 a.Error_MisusedDynamicAttribute ();
491 PropertyBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
494 void CheckMissingAccessor (MemberKind kind, ParametersCompiled parameters, bool get)
496 if (IsExplicitImpl) {
498 if (kind == MemberKind.Indexer)
499 filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, kind, parameters, null);
501 filter = new MemberFilter (MemberName.Name, 0, kind, null, null);
503 var implementing = MemberCache.FindMember (InterfaceType, filter, BindingRestriction.DeclaredOnly) as PropertySpec;
505 if (implementing == null)
508 var accessor = get ? implementing.Get : implementing.Set;
509 if (accessor != null) {
510 Report.SymbolRelatedToPreviousError (accessor);
511 Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
512 GetSignatureForError (), accessor.GetSignatureForError ());
517 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
519 var ok = base.CheckOverrideAgainstBase (base_member);
522 // Check base property accessors conflict
524 var base_prop = (PropertySpec) base_member;
526 if (!base_prop.HasGet) {
528 Report.SymbolRelatedToPreviousError (base_prop);
529 Report.Error (545, Get.Location,
530 "`{0}': cannot override because `{1}' does not have an overridable get accessor",
531 Get.GetSignatureForError (), base_prop.GetSignatureForError ());
534 } else if (Get.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
535 if (!CheckAccessModifiers (Get, base_prop.Get)) {
536 Error_CannotChangeAccessModifiers (Get, base_prop.Get);
543 if (!base_prop.HasSet) {
545 Report.SymbolRelatedToPreviousError (base_prop);
546 Report.Error (546, Set.Location,
547 "`{0}': cannot override because `{1}' does not have an overridable set accessor",
548 Set.GetSignatureForError (), base_prop.GetSignatureForError ());
551 } else if (Set.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
552 if (!CheckAccessModifiers (Set, base_prop.Set)) {
553 Error_CannotChangeAccessModifiers (Set, base_prop.Set);
559 if ((Set == null || !Set.HasCustomAccessModifier) && (Get == null || !Get.HasCustomAccessModifier)) {
560 if (!CheckAccessModifiers (this, base_prop)) {
561 Error_CannotChangeAccessModifiers (this, base_prop);
569 protected override void DoMemberTypeDependentChecks ()
571 base.DoMemberTypeDependentChecks ();
575 if (MemberType.IsStatic)
576 Error_StaticReturnType ();
579 protected override void DoMemberTypeIndependentChecks ()
581 base.DoMemberTypeIndependentChecks ();
584 // Accessors modifiers check
586 if (AccessorSecond != null) {
587 if ((Get.ModFlags & Modifiers.AccessibilityMask) != 0 && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) {
588 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
589 GetSignatureForError ());
591 } else if ((ModFlags & Modifiers.OVERRIDE) == 0 &&
592 (Get == null && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) ||
593 (Set == null && (Get.ModFlags & Modifiers.AccessibilityMask) != 0)) {
594 Report.Error (276, Location,
595 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
596 GetSignatureForError ());
600 protected bool DefineAccessors ()
602 first.Define (Parent);
603 if (AccessorSecond != null)
604 AccessorSecond.Define (Parent);
609 protected void DefineBuilders (MemberKind kind, ParametersCompiled parameters)
611 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
612 GetFullName (MemberName), PropertyAttributes.None,
613 #if !BOOTSTRAP_BASIC // Requires trunk version mscorlib
614 IsStatic ? 0 : CallingConventions.HasThis,
616 MemberType.GetMetaInfo (), null, null,
617 parameters.GetMetaInfo (), null, null);
620 if (kind == MemberKind.Indexer)
621 spec = new IndexerSpec (Parent.Definition, this, MemberType, parameters, PropertyBuilder, ModFlags);
623 spec = new PropertySpec (kind, Parent.Definition, this, MemberType, PropertyBuilder, ModFlags);
628 var method = Get.Spec.GetMetaInfo () as MethodBuilder;
629 if (method != null) {
630 PropertyBuilder.SetGetMethod (method);
631 Parent.MemberCache.AddMember (this, method.Name, Get.Spec);
634 CheckMissingAccessor (kind, parameters, true);
640 var method = Set.Spec.GetMetaInfo () as MethodBuilder;
641 if (method != null) {
642 PropertyBuilder.SetSetMethod (method);
643 Parent.MemberCache.AddMember (this, method.Name, Set.Spec);
646 CheckMissingAccessor (kind, parameters, false);
649 Parent.MemberCache.AddMember (this, PropertyBuilder.Name, spec);
652 public override void Emit ()
654 CheckReservedNameConflict (GetMethod.Prefix, get == null ? null : get.Spec);
655 CheckReservedNameConflict (SetMethod.Prefix, set == null ? null : set.Spec);
657 if (OptAttributes != null)
658 OptAttributes.Emit ();
660 if (member_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
661 Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder);
662 } else if (member_type.HasDynamicElement) {
663 Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder, member_type, Location);
666 ConstraintChecker.Check (this, member_type, type_expr.Location);
669 if (AccessorSecond != null)
670 AccessorSecond.Emit (Parent);
675 public override bool IsUsed {
680 return Get.IsUsed | Set.IsUsed;
684 protected override void SetMemberName (MemberName new_name)
686 base.SetMemberName (new_name);
689 Get.UpdateName (this);
692 Set.UpdateName (this);
695 public override void WriteDebugSymbol (MonoSymbolFile file)
698 get.WriteDebugSymbol (file);
701 set.WriteDebugSymbol (file);
705 // Represents header string for documentation comment.
707 public override string DocCommentHeader {
712 public class Property : PropertyBase
714 public sealed class BackingField : Field
716 readonly Property property;
718 public BackingField (Property p)
719 : base (p.Parent, p.type_expr,
720 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
721 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
726 public Property OriginalProperty {
732 public override string GetSignatureForError ()
734 return property.GetSignatureForError ();
738 public Property (TypeDefinition parent, FullNamedExpression type, Modifiers mod,
739 MemberName name, Attributes attrs)
740 : base (parent, type, mod,
741 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
742 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
743 AllowedModifiersClass,
748 public override void Accept (StructuralVisitor visitor)
750 visitor.Visit (this);
754 void CreateAutomaticProperty ()
756 // Create backing field
757 Field field = new BackingField (this);
758 if (!field.Define ())
761 Parent.PartialContainer.Members.Add (field);
763 FieldExpr fe = new FieldExpr (field, Location);
764 if ((field.ModFlags & Modifiers.STATIC) == 0)
765 fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
768 // Create get block but we careful with location to
769 // emit only single sequence point per accessor. This allow
770 // to set a breakpoint on it even with no user code
772 Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location.Null);
773 Return r = new Return (fe, Get.Location);
774 Get.Block.AddStatement (r);
777 Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location.Null);
778 Assign a = new SimpleAssign (fe, new SimpleName ("value", Location.Null), Location.Null);
779 Set.Block.AddStatement (new StatementExpression (a, Set.Location));
782 public override bool Define ()
787 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
789 if (!IsInterface && (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
790 AccessorSecond != null && Get.Block == null && Set.Block == null) {
791 if (Compiler.Settings.Version <= LanguageVersion.ISO_2)
792 Report.FeatureIsNotAvailable (Compiler, Location, "automatically implemented properties");
794 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
795 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
796 CreateAutomaticProperty ();
799 if (!DefineAccessors ())
802 if (AccessorSecond == null) {
804 if (AccessorFirst is GetMethod)
805 pm = new SetMethod (this, 0, ParametersCompiled.EmptyReadOnlyParameters, null, Location);
807 pm = new GetMethod (this, 0, null, Location);
809 Parent.AddNameToContainer (pm, pm.MemberName.Basename);
815 DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters);
819 public override void Emit ()
821 if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
822 Report.Error (842, Location,
823 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
824 GetSignatureForError ());
832 /// For case when event is declared like property (with add and remove accessors).
834 public class EventProperty: Event {
835 public abstract class AEventPropertyAccessor : AEventAccessor
837 protected AEventPropertyAccessor (EventProperty method, string prefix, Attributes attrs, Location loc)
838 : base (method, prefix, attrs, loc)
842 public override MethodBuilder Define (TypeContainer ds)
844 CheckAbstractAndExtern (block != null);
845 return base.Define (ds);
848 public override string GetSignatureForError ()
850 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
854 public sealed class AddDelegateMethod: AEventPropertyAccessor
856 public AddDelegateMethod (EventProperty method, Attributes attrs, Location loc)
857 : base (method, AddPrefix, attrs, loc)
862 public sealed class RemoveDelegateMethod: AEventPropertyAccessor
864 public RemoveDelegateMethod (EventProperty method, Attributes attrs, Location loc)
865 : base (method, RemovePrefix, attrs, loc)
870 static readonly string[] attribute_targets = new string [] { "event" };
872 public EventProperty (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
873 : base (parent, type, mod_flags, name, attrs)
877 public override void Accept (StructuralVisitor visitor)
879 visitor.Visit (this);
882 public override bool Define()
891 public override string[] ValidAttributeTargets {
893 return attribute_targets;
899 /// Event is declared like field.
901 public class EventField : Event
903 abstract class EventFieldAccessor : AEventAccessor
905 protected EventFieldAccessor (EventField method, string prefix)
906 : base (method, prefix, null, method.Location)
910 protected abstract MethodSpec GetOperation (Location loc);
912 public override void Emit (TypeDefinition parent)
914 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 && !Compiler.Settings.WriteMetadataOnly) {
915 block = new ToplevelBlock (Compiler, ParameterInfo, Location) {
916 IsCompilerGenerated = true
918 FabricateBodyStatement ();
924 void FabricateBodyStatement ()
927 // Delegate obj1 = backing_field
929 // Delegate obj2 = obj1;
930 // obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1);
931 // } while ((object)obj1 != (object)obj2)
934 var field_info = ((EventField) method).backing_field;
935 FieldExpr f_expr = new FieldExpr (field_info, Location);
937 f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
939 var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
940 var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
942 block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr)));
944 var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality,
945 new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj1, Location), Location),
946 new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj2, Location), Location)));
948 var body = new ExplicitBlock (block, Location, Location);
949 block.AddStatement (new Do (body, cond, Location, Location));
951 body.AddStatement (new StatementExpression (
952 new SimpleAssign (new LocalVariableReference (obj2, Location), new LocalVariableReference (obj1, Location))));
954 var args_oper = new Arguments (2);
955 args_oper.Add (new Argument (new LocalVariableReference (obj2, Location)));
956 args_oper.Add (new Argument (block.GetParameterReference (0, Location)));
958 var op_method = GetOperation (Location);
960 var args = new Arguments (3);
961 args.Add (new Argument (f_expr, Argument.AType.Ref));
962 args.Add (new Argument (new Cast (
963 new TypeExpression (field_info.MemberType, Location),
964 new Invocation (MethodGroupExpr.CreatePredefined (op_method, op_method.DeclaringType, Location), args_oper),
966 args.Add (new Argument (new LocalVariableReference (obj1, Location)));
968 var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location);
972 body.AddStatement (new StatementExpression (new SimpleAssign (
973 new LocalVariableReference (obj1, Location),
974 new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args))));
978 sealed class AddDelegateMethod: EventFieldAccessor
980 public AddDelegateMethod (EventField method):
981 base (method, AddPrefix)
985 protected override MethodSpec GetOperation (Location loc)
987 return Module.PredefinedMembers.DelegateCombine.Resolve (loc);
991 sealed class RemoveDelegateMethod: EventFieldAccessor
993 public RemoveDelegateMethod (EventField method):
994 base (method, RemovePrefix)
998 protected override MethodSpec GetOperation (Location loc)
1000 return Module.PredefinedMembers.DelegateRemove.Resolve (loc);
1005 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
1006 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
1008 Expression initializer;
1009 Field backing_field;
1010 List<FieldDeclarator> declarators;
1012 public EventField (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1013 : base (parent, type, mod_flags, name, attrs)
1015 Add = new AddDelegateMethod (this);
1016 Remove = new RemoveDelegateMethod (this);
1021 public List<FieldDeclarator> Declarators {
1023 return this.declarators;
1027 bool HasBackingField {
1029 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
1033 public Expression Initializer {
1038 initializer = value;
1042 public override string[] ValidAttributeTargets {
1044 return HasBackingField ? attribute_targets : attribute_targets_interface;
1051 public override void Accept (StructuralVisitor visitor)
1053 visitor.Visit (this);
1056 public void AddDeclarator (FieldDeclarator declarator)
1058 if (declarators == null)
1059 declarators = new List<FieldDeclarator> (2);
1061 declarators.Add (declarator);
1063 Parent.AddNameToContainer (this, declarator.Name.Value);
1066 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1068 if (a.Target == AttributeTargets.Field) {
1069 backing_field.ApplyAttributeBuilder (a, ctor, cdata, pa);
1073 if (a.Target == AttributeTargets.Method) {
1074 int errors = Report.Errors;
1075 Add.ApplyAttributeBuilder (a, ctor, cdata, pa);
1076 if (errors == Report.Errors)
1077 Remove.ApplyAttributeBuilder (a, ctor, cdata, pa);
1081 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1084 public override bool Define()
1086 var mod_flags_src = ModFlags;
1088 if (!base.Define ())
1091 if (declarators != null) {
1092 if ((mod_flags_src & Modifiers.DEFAULT_ACCESS_MODIFER) != 0)
1093 mod_flags_src &= ~(Modifiers.AccessibilityMask | Modifiers.DEFAULT_ACCESS_MODIFER);
1095 var t = new TypeExpression (MemberType, TypeExpression.Location);
1096 foreach (var d in declarators) {
1097 var ef = new EventField (Parent, t, mod_flags_src, new MemberName (d.Name.Value, d.Name.Location), OptAttributes);
1099 if (d.Initializer != null)
1100 ef.initializer = d.Initializer;
1103 Parent.PartialContainer.Members.Add (ef);
1107 if (!HasBackingField) {
1112 if (Add.IsInterfaceImplementation)
1115 backing_field = new Field (Parent,
1116 new TypeExpression (MemberType, Location),
1117 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
1120 Parent.PartialContainer.Members.Add (backing_field);
1121 backing_field.Initializer = Initializer;
1122 backing_field.ModFlags &= ~Modifiers.COMPILER_GENERATED;
1124 // Call define because we passed fields definition
1125 backing_field.Define ();
1127 // Set backing field for event fields
1128 spec.BackingField = backing_field.Spec;
1134 public abstract class Event : PropertyBasedMember
1136 public abstract class AEventAccessor : AbstractPropertyEventMethod
1138 protected readonly Event method;
1139 readonly ParametersCompiled parameters;
1141 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
1143 public const string AddPrefix = "add_";
1144 public const string RemovePrefix = "remove_";
1146 protected AEventAccessor (Event method, string prefix, Attributes attrs, Location loc)
1147 : base (method, prefix, attrs, loc)
1149 this.method = method;
1150 this.ModFlags = method.ModFlags;
1151 this.parameters = ParametersCompiled.CreateImplicitParameter (method.TypeExpression, loc);
1154 public bool IsInterfaceImplementation {
1155 get { return method_data.implementing != null; }
1158 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1160 if (a.Type == pa.MethodImpl) {
1161 method.is_external_implementation = a.IsInternalCall ();
1164 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1167 protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1169 if (a.Target == AttributeTargets.Parameter) {
1170 parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa);
1174 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1177 public override AttributeTargets AttributeTargets {
1179 return AttributeTargets.Method;
1183 public override bool IsClsComplianceRequired ()
1185 return method.IsClsComplianceRequired ();
1188 public virtual MethodBuilder Define (TypeContainer parent)
1190 // Fill in already resolved event type to speed things up and
1191 // avoid confusing duplicate errors
1192 ((Parameter) parameters.FixedParameters[0]).Type = method.member_type;
1193 parameters.Types = new TypeSpec[] { method.member_type };
1195 method_data = new MethodData (method, method.ModFlags,
1196 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
1198 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
1201 if (Compiler.Settings.WriteMetadataOnly)
1204 MethodBuilder mb = method_data.MethodBuilder;
1206 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, mb, ParameterInfo, method.ModFlags);
1207 Spec.IsAccessor = true;
1212 public override TypeSpec ReturnType {
1214 return Parent.Compiler.BuiltinTypes.Void;
1218 public override ObsoleteAttribute GetAttributeObsolete ()
1220 return method.GetAttributeObsolete ();
1223 public override string[] ValidAttributeTargets {
1225 return attribute_targets;
1229 public override ParametersCompiled ParameterInfo {
1236 AEventAccessor add, remove;
1237 EventBuilder EventBuilder;
1238 protected EventSpec spec;
1240 protected Event (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1241 : base (parent, type, mod_flags,
1242 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
1243 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
1244 AllowedModifiersClass,
1251 public override AttributeTargets AttributeTargets {
1253 return AttributeTargets.Event;
1257 public AEventAccessor Add {
1263 Parent.AddNameToContainer (value, value.MemberName.Basename);
1267 public override Variance ExpectedMemberTypeVariance {
1269 return Variance.Contravariant;
1273 public AEventAccessor Remove {
1279 Parent.AddNameToContainer (value, value.MemberName.Basename);
1284 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1286 if ((a.HasSecurityAttribute)) {
1287 a.Error_InvalidSecurityParent ();
1291 EventBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1294 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
1296 var ok = base.CheckOverrideAgainstBase (base_member);
1298 if (!CheckAccessModifiers (this, base_member)) {
1299 Error_CannotChangeAccessModifiers (this, base_member);
1306 public override bool Define ()
1308 if (!base.Define ())
1311 if (!MemberType.IsDelegate) {
1312 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
1319 // Now define the accessors
1321 var AddBuilder = Add.Define (Parent);
1322 if (AddBuilder == null)
1325 var RemoveBuilder = remove.Define (Parent);
1326 if (RemoveBuilder == null)
1329 EventBuilder = Parent.TypeBuilder.DefineEvent (GetFullName (MemberName), EventAttributes.None, MemberType.GetMetaInfo ());
1330 EventBuilder.SetAddOnMethod (AddBuilder);
1331 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
1333 spec = new EventSpec (Parent.Definition, this, MemberType, ModFlags, Add.Spec, remove.Spec);
1335 Parent.MemberCache.AddMember (this, GetFullName (MemberName), spec);
1336 Parent.MemberCache.AddMember (this, AddBuilder.Name, Add.Spec);
1337 Parent.MemberCache.AddMember (this, RemoveBuilder.Name, remove.Spec);
1342 public override void Emit ()
1344 CheckReservedNameConflict (null, add.Spec);
1345 CheckReservedNameConflict (null, remove.Spec);
1347 if (OptAttributes != null) {
1348 OptAttributes.Emit ();
1351 ConstraintChecker.Check (this, member_type, type_expr.Location);
1354 Remove.Emit (Parent);
1359 public override void WriteDebugSymbol (MonoSymbolFile file)
1361 add.WriteDebugSymbol (file);
1362 remove.WriteDebugSymbol (file);
1366 // Represents header string for documentation comment.
1368 public override string DocCommentHeader {
1369 get { return "E:"; }
1373 public class EventSpec : MemberSpec, IInterfaceMemberSpec
1375 MethodSpec add, remove;
1376 FieldSpec backing_field;
1378 public EventSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec eventType, Modifiers modifiers, MethodSpec add, MethodSpec remove)
1379 : base (MemberKind.Event, declaringType, definition, modifiers)
1381 this.AccessorAdd = add;
1382 this.AccessorRemove = remove;
1383 this.MemberType = eventType;
1388 public MethodSpec AccessorAdd {
1397 public MethodSpec AccessorRemove {
1406 public FieldSpec BackingField {
1408 return backing_field;
1411 backing_field = value;
1415 public TypeSpec MemberType { get; private set; }
1419 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1421 var es = (EventSpec) base.InflateMember (inflator);
1422 es.MemberType = inflator.Inflate (MemberType);
1424 if (backing_field != null)
1425 es.backing_field = (FieldSpec) backing_field.InflateMember (inflator);
1430 public override List<TypeSpec> ResolveMissingDependencies ()
1432 return MemberType.ResolveMissingDependencies ();
1436 public class Indexer : PropertyBase, IParametersMember
1438 public class GetIndexerMethod : GetMethod, IParametersMember
1440 ParametersCompiled parameters;
1442 public GetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1443 : base (property, modifiers, attrs, loc)
1445 this.parameters = parameters;
1448 public override MethodBuilder Define (TypeContainer parent)
1450 // Disable reporting, parameters are resolved twice
1451 Report.DisableReporting ();
1453 parameters.Resolve (this);
1455 Report.EnableReporting ();
1458 return base.Define (parent);
1461 public override ParametersCompiled ParameterInfo {
1467 #region IParametersMember Members
1469 AParametersCollection IParametersMember.Parameters {
1475 TypeSpec IInterfaceMemberSpec.MemberType {
1484 public class SetIndexerMethod : SetMethod, IParametersMember
1486 public SetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1487 : base (property, modifiers, parameters, attrs, loc)
1491 #region IParametersMember Members
1493 AParametersCollection IParametersMember.Parameters {
1499 TypeSpec IInterfaceMemberSpec.MemberType {
1508 const Modifiers AllowedModifiers =
1511 Modifiers.PROTECTED |
1512 Modifiers.INTERNAL |
1516 Modifiers.OVERRIDE |
1521 const Modifiers AllowedInterfaceModifiers =
1524 readonly ParametersCompiled parameters;
1526 public Indexer (TypeDefinition parent, FullNamedExpression type, MemberName name, Modifiers mod, ParametersCompiled parameters, Attributes attrs)
1527 : base (parent, type, mod,
1528 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1531 this.parameters = parameters;
1536 AParametersCollection IParametersMember.Parameters {
1542 public ParametersCompiled ParameterInfo {
1551 public override void Accept (StructuralVisitor visitor)
1553 visitor.Visit (this);
1556 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1558 if (a.Type == pa.IndexerName) {
1559 // Attribute was copied to container
1563 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1566 protected override bool CheckForDuplications ()
1568 return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1571 public override bool Define ()
1573 if (!base.Define ())
1576 if (!DefineParameters (parameters))
1579 if (OptAttributes != null) {
1580 Attribute indexer_attr = OptAttributes.Search (Module.PredefinedAttributes.IndexerName);
1581 if (indexer_attr != null) {
1582 var compiling = indexer_attr.Type.MemberDefinition as TypeContainer;
1583 if (compiling != null)
1584 compiling.Define ();
1586 if (IsExplicitImpl) {
1587 Report.Error (415, indexer_attr.Location,
1588 "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration",
1589 indexer_attr.Type.GetSignatureForError ());
1590 } else if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1591 Report.Error (609, indexer_attr.Location,
1592 "Cannot set the `IndexerName' attribute on an indexer marked override");
1594 string name = indexer_attr.GetIndexerAttributeValue ();
1596 if (!string.IsNullOrEmpty (name)) {
1597 SetMemberName (new MemberName (MemberName.Left, name, Location));
1603 if (InterfaceType != null) {
1604 string base_IndexerName = InterfaceType.MemberDefinition.GetAttributeDefaultMember ();
1605 if (base_IndexerName != ShortName) {
1606 SetMemberName (new MemberName (MemberName.Left, base_IndexerName, new TypeExpression (InterfaceType, Location), Location));
1610 Parent.AddNameToContainer (this, MemberName.Basename);
1612 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1614 if (!DefineAccessors ())
1620 DefineBuilders (MemberKind.Indexer, parameters);
1624 public override bool EnableOverloadChecks (MemberCore overload)
1626 if (overload is Indexer) {
1627 caching_flags |= Flags.MethodOverloadsExist;
1631 return base.EnableOverloadChecks (overload);
1634 public override void Emit ()
1636 parameters.CheckConstraints (this);
1641 public override string GetSignatureForError ()
1643 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
1644 if (MemberName.ExplicitInterface != null) {
1646 sb.Append (MemberName.ExplicitInterface.GetSignatureForError ());
1649 sb.Append (".this");
1650 sb.Append (parameters.GetSignatureForError ("[", "]", parameters.Count));
1651 return sb.ToString ();
1654 public override string GetSignatureForDocumentation ()
1656 return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1659 protected override bool VerifyClsCompliance ()
1661 if (!base.VerifyClsCompliance ())
1664 parameters.VerifyClsCompliance (this);
1669 public class IndexerSpec : PropertySpec, IParametersMember
1671 AParametersCollection parameters;
1673 public IndexerSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, AParametersCollection parameters, PropertyInfo info, Modifiers modifiers)
1674 : base (MemberKind.Indexer, declaringType, definition, memberType, info, modifiers)
1676 this.parameters = parameters;
1680 public AParametersCollection Parameters {
1687 public override string GetSignatureForDocumentation ()
1689 return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1692 public override string GetSignatureForError ()
1694 return DeclaringType.GetSignatureForError () + ".this" + parameters.GetSignatureForError ("[", "]", parameters.Count);
1697 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1699 var spec = (IndexerSpec) base.InflateMember (inflator);
1700 spec.parameters = parameters.Inflate (inflator);
1704 public override List<TypeSpec> ResolveMissingDependencies ()
1706 var missing = base.ResolveMissingDependencies ();
1707 foreach (var pt in parameters.Types) {
1708 var m = pt.GetMissingDependencies ();
1712 if (missing == null)
1713 missing = new List<TypeSpec> ();
1715 missing.AddRange (m);