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);