using System.Text;
using Mono.CompilerServices.SymbolWriter;
-#if NET_2_1
+#if MOBILE
using XmlElement = System.Object;
#endif
}
}
- public abstract void PrepareEmit ();
-
protected override bool VerifyClsCompliance ()
{
if (!base.VerifyClsCompliance ())
protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
{
if (a.Target == AttributeTargets.Parameter) {
- parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa);
+ parameters[parameters.Count - 1].ApplyAttributeBuilder (a, ctor, cdata, pa);
return;
}
ModFlags |= method.ModFlags;
flags = method.flags;
} else {
- if (container.Kind == MemberKind.Interface)
+ CheckModifiers (ModFlags);
+ ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask));
+ ModFlags |= Modifiers.PROPERTY_CUSTOM;
+
+ if (container.Kind == MemberKind.Interface) {
Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
GetSignatureForError ());
- else if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
- Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
+ } else if ((ModFlags & Modifiers.PRIVATE) != 0) {
+ if ((method.ModFlags & Modifiers.ABSTRACT) != 0) {
+ Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
+ }
+
+ ModFlags &= ~Modifiers.VIRTUAL;
}
- CheckModifiers (ModFlags);
- ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask));
- ModFlags |= Modifiers.PROPERTY_CUSTOM;
- flags = ModifiersExtensions.MethodAttr (ModFlags);
- flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
+ flags = ModifiersExtensions.MethodAttr (ModFlags) | MethodAttributes.SpecialName;
}
CheckAbstractAndExtern (block != null);
ok = false;
}
} else if (Get.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
- if (!CheckAccessModifiers (Get, base_prop.Get)) {
+ if (!base_prop.Get.IsAccessible (this)) {
+ // Same as csc but it should be different error code
+ Report.Error (115, Get.Location, "`{0}' is marked as an override but no accessible `get' accessor found to override",
+ GetSignatureForError ());
+ ok = false;
+ } else if (!CheckAccessModifiers (Get, base_prop.Get)) {
Error_CannotChangeAccessModifiers (Get, base_prop.Get);
ok = false;
}
}
if (Set == null) {
- if ((ModFlags & Modifiers.SEALED) != 0 && base_prop.HasSet && !base_prop.Set.IsAccessible (this)) {
- // TODO: Should be different error code but csc uses for some reason same
- Report.SymbolRelatedToPreviousError (base_prop);
- Report.Error (546, Location,
- "`{0}': cannot override because `{1}' does not have accessible set accessor",
- GetSignatureForError (), base_prop.GetSignatureForError ());
- ok = false;
+ if (base_prop.HasSet) {
+ if ((ModFlags & Modifiers.SEALED) != 0 && !base_prop.Set.IsAccessible (this)) {
+ // TODO: Should be different error code but csc uses for some reason same
+ Report.SymbolRelatedToPreviousError (base_prop);
+ Report.Error (546, Location,
+ "`{0}': cannot override because `{1}' does not have accessible set accessor",
+ GetSignatureForError (), base_prop.GetSignatureForError ());
+ ok = false;
+ }
+
+ if ((ModFlags & Modifiers.AutoProperty) != 0) {
+ Report.Error (8080, Location, "`{0}': Auto-implemented properties must override all accessors of the overridden property",
+ GetSignatureForError ());
+ ok = false;
+ }
}
} else {
if (!base_prop.HasSet) {
ok = false;
}
} else if (Set.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
- if (!CheckAccessModifiers (Set, base_prop.Set)) {
+ if (!base_prop.Set.IsAccessible (this)) {
+ // Same as csc but it should be different error code
+ Report.Error (115, Set.Location, "`{0}' is marked as an override but no accessible `set' accessor found to override",
+ GetSignatureForError ());
+ ok = false;
+ } else if (!CheckAccessModifiers (Set, base_prop.Set)) {
Error_CannotChangeAccessModifiers (Set, base_prop.Set);
ok = false;
}
GetSignatureForError ());
}
} else if ((ModFlags & Modifiers.OVERRIDE) == 0 &&
- (Get == null && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) ||
- (Set == null && (Get.ModFlags & Modifiers.AccessibilityMask) != 0)) {
+ ((Get == null && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) || (Set == null && (Get.ModFlags & Modifiers.AccessibilityMask) != 0))) {
Report.Error (276, Location,
"`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
GetSignatureForError ());
Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder, member_type, Location);
}
+ if (member_type.HasNamedTupleElement) {
+ Module.PredefinedAttributes.TupleElementNames.EmitAttribute (PropertyBuilder, member_type, Location);
+ }
+
ConstraintChecker.Check (this, member_type, type_expr.Location);
first.Emit (Parent);
public class Property : PropertyBase
{
- public sealed class BackingField : Field
+ public sealed class BackingFieldDeclaration : Field
{
readonly Property property;
+ const Modifiers DefaultModifiers = Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | Modifiers.DEBUGGER_HIDDEN;
- public BackingField (Property p)
- : base (p.Parent, p.type_expr,
- Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
+ public BackingFieldDeclaration (Property p, bool readOnly)
+ : base (p.Parent, p.type_expr, DefaultModifiers | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
{
this.property = p;
+ if (readOnly)
+ ModFlags |= Modifiers.READONLY;
}
public Property OriginalProperty {
static readonly string[] attribute_target_auto = new string[] { "property", "field" };
- Field backing_field;
-
public Property (TypeDefinition parent, FullNamedExpression type, Modifiers mod,
MemberName name, Attributes attrs)
: base (parent, type, mod,
{
}
+ public BackingFieldDeclaration BackingField { get; private set; }
+
+ public Expression Initializer { get; set; }
+
public override void Accept (StructuralVisitor visitor)
{
visitor.Visit (this);
public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
{
if (a.Target == AttributeTargets.Field) {
- backing_field.ApplyAttributeBuilder (a, ctor, cdata, pa);
+ BackingField.ApplyAttributeBuilder (a, ctor, cdata, pa);
return;
}
void CreateAutomaticProperty ()
{
// Create backing field
- backing_field = new BackingField (this);
- if (!backing_field.Define ())
+ BackingField = new BackingFieldDeclaration (this, Initializer == null && Set == null);
+ if (!BackingField.Define ())
return;
- Parent.PartialContainer.Members.Add (backing_field);
+ if (Initializer != null) {
+ BackingField.Initializer = Initializer;
+ Parent.RegisterFieldForInitialization (BackingField, new FieldInitializer (BackingField, Initializer, Location));
+ BackingField.ModFlags |= Modifiers.READONLY;
+ }
- FieldExpr fe = new FieldExpr (backing_field, Location);
- if ((backing_field.ModFlags & Modifiers.STATIC) == 0)
+ Parent.PartialContainer.Members.Add (BackingField);
+
+ FieldExpr fe = new FieldExpr (BackingField, Location);
+ if ((BackingField.ModFlags & Modifiers.STATIC) == 0) {
fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
+ Parent.PartialContainer.HasInstanceField = true;
+ }
//
// Create get block but we careful with location to
Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location.Null);
Return r = new Return (fe, Get.Location);
Get.Block.AddStatement (r);
+ Get.ModFlags |= Modifiers.COMPILER_GENERATED;
// Create set block
- Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location.Null);
- Assign a = new SimpleAssign (fe, new SimpleName ("value", Location.Null), Location.Null);
- Set.Block.AddStatement (new StatementExpression (a, Set.Location));
+ if (Set != null) {
+ Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location.Null);
+ Assign a = new SimpleAssign (fe, new SimpleName ("value", Location.Null), Location.Null);
+ Set.Block.AddStatement (new StatementExpression (a, Set.Location));
+ Set.ModFlags |= Modifiers.COMPILER_GENERATED;
+ }
}
public override bool Define ()
flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
- if (!IsInterface && (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
- AccessorSecond != null && Get.Block == null && Set.Block == null) {
- if (Compiler.Settings.Version <= LanguageVersion.ISO_2)
- Report.FeatureIsNotAvailable (Compiler, Location, "automatically implemented properties");
+ bool auto = AccessorFirst.Block == null && (AccessorSecond == null || AccessorSecond.Block == null) &&
+ (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0;
+
+ if (Initializer != null) {
+ if (!auto)
+ Report.Error (8050, Location, "`{0}': Only auto-implemented properties can have initializers",
+ GetSignatureForError ());
+
+ if (IsInterface)
+ Report.Error (8052, Location, "`{0}': Properties inside interfaces cannot have initializers",
+ GetSignatureForError ());
+
+ if (Compiler.Settings.Version < LanguageVersion.V_6)
+ Report.FeatureIsNotAvailable (Compiler, Location, "auto-implemented property initializer");
+ }
+
+ if (auto) {
+ ModFlags |= Modifiers.AutoProperty;
+ if (Get == null) {
+ Report.Error (8051, Location, "Auto-implemented property `{0}' must have get accessor",
+ GetSignatureForError ());
+ return false;
+ }
+
+ if (MemberType.Kind == MemberKind.ByRef) {
+ Report.Error (8145, Location, "Auto-implemented properties cannot return by reference");
+ return false;
+ }
+
+ if (Compiler.Settings.Version < LanguageVersion.V_3 && Initializer == null)
+ Report.FeatureIsNotAvailable (Compiler, Location, "auto-implemented properties");
- Get.ModFlags |= Modifiers.COMPILER_GENERATED;
- Set.ModFlags |= Modifiers.COMPILER_GENERATED;
CreateAutomaticProperty ();
}
public override void Emit ()
{
- if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
+ if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.AutoProperty)) == Modifiers.AutoProperty && Parent.PartialContainer.HasExplicitLayout) {
Report.Error (842, Location,
"Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
GetSignatureForError ());
Location)));
args.Add (new Argument (new LocalVariableReference (obj1, Location)));
- var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location);
- if (cas == null)
- return;
-
- body.AddStatement (new StatementExpression (new SimpleAssign (
- new LocalVariableReference (obj1, Location),
- new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args))));
+ var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Get ();
+ if (cas == null) {
+ if (Module.PredefinedMembers.MonitorEnter_v4.Get () != null || Module.PredefinedMembers.MonitorEnter.Get () != null) {
+ // Workaround for cripled (e.g. microframework) mscorlib without CompareExchange
+ body.AddStatement (new Lock (
+ block.GetParameterReference (0, Location),
+ new StatementExpression (new SimpleAssign (
+ f_expr, args [1].Expr, Location), Location), Location));
+ } else {
+ Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location);
+ }
+ } else {
+ body.AddStatement (new StatementExpression (new SimpleAssign (
+ new LocalVariableReference (obj1, Location),
+ new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args))));
+ }
}
}
backing_field = new Field (Parent,
new TypeExpression (MemberType, Location),
- Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
+ Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
MemberName, null);
Parent.PartialContainer.Members.Add (backing_field);
backing_field.Initializer = Initializer;
- backing_field.ModFlags &= ~Modifiers.COMPILER_GENERATED;
// Call define because we passed fields definition
backing_field.Define ();
public override void PrepareEmit ()
{
+ base.PrepareEmit ();
+
add.PrepareEmit ();
remove.PrepareEmit ();
return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
}
+ public override void PrepareEmit ()
+ {
+ base.PrepareEmit ();
+ parameters.ResolveDefaultValues (this);
+ }
+
protected override bool VerifyClsCompliance ()
{
if (!base.VerifyClsCompliance ())
}
#endregion
+ public static ParametersImported CreateParametersFromSetter (MethodSpec setter, int set_param_count)
+ {
+ //
+ // Creates indexer parameters based on setter method parameters (the last parameter has to be removed)
+ //
+ var data = new IParameterData [set_param_count];
+ var types = new TypeSpec [set_param_count];
+ Array.Copy (setter.Parameters.FixedParameters, data, set_param_count);
+ Array.Copy (setter.Parameters.Types, types, set_param_count);
+ return new ParametersImported (data, types, setter.Parameters.HasParams);
+ }
+
public override string GetSignatureForDocumentation ()
{
return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();