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