// This includes properties, indexers, and events
public abstract class PropertyBasedMember : InterfaceMemberBase
{
- public PropertyBasedMember (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
+ protected PropertyBasedMember (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
: base (parent, type, mod, allowed_mod, name, attrs)
{
}
}
}
+ public abstract void PrepareEmit ();
+
protected override bool VerifyClsCompliance ()
{
if (!base.VerifyClsCompliance ())
return ps;
}
- public override List<TypeSpec> ResolveMissingDependencies ()
+ public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
{
- return memberType.ResolveMissingDependencies ();
+ return memberType.ResolveMissingDependencies (this);
}
}
{
}
- public override MethodBuilder Define (TypeContainer parent)
+ public override void Define (TypeContainer parent)
{
base.Define (parent);
method_data = new MethodData (method, ModFlags, flags, this);
- if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
- return null;
-
- method_data.DefineMethodBuilder (parent.PartialContainer, ParameterInfo);
-
- return method_data.MethodBuilder;
+ method_data.Define (parent.PartialContainer, method.GetFullName (MemberName));
}
public override TypeSpec ReturnType {
return;
}
- base.ApplyAttributeBuilder (a, ctor, cdata, pa);
+ base.ApplyToExtraTarget (a, ctor, cdata, pa);
}
public override ParametersCompiled ParameterInfo {
}
}
- public override MethodBuilder Define (TypeContainer parent)
+ public override void Define (TypeContainer parent)
{
parameters.Resolve (this);
method_data = new MethodData (method, ModFlags, flags, this);
- if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
- return null;
-
- method_data.DefineMethodBuilder (parent.PartialContainer, ParameterInfo);
-
- return method_data.MethodBuilder;
+ method_data.Define (parent.PartialContainer, method.GetFullName (MemberName));
}
public override TypeSpec ReturnType {
return method.IsClsComplianceRequired ();
}
- public virtual MethodBuilder Define (TypeContainer parent)
+ public virtual void Define (TypeContainer parent)
{
var container = parent.PartialContainer;
if (Compiler.Settings.WriteMetadataOnly)
block = null;
}
-
- return null;
}
public bool HasCustomAccessModifier {
PropertyMethod get, set, first;
PropertyBuilder PropertyBuilder;
- public PropertyBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, Modifiers allowed_mod, MemberName name, Attributes attrs)
+ protected PropertyBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, Modifiers allowed_mod, MemberName name, Attributes attrs)
: base (parent, type, mod_flags, allowed_mod, name, attrs)
{
}
// Check base property accessors conflict
//
var base_prop = (PropertySpec) base_member;
- if (Get != null) {
+ if (Get == null) {
+ if ((ModFlags & Modifiers.SEALED) != 0 && base_prop.HasGet && !base_prop.Get.IsAccessible (this)) {
+ // TODO: Should be different error code but csc uses for some reason same
+ Report.SymbolRelatedToPreviousError (base_prop);
+ Report.Error (545, Location,
+ "`{0}': cannot override because `{1}' does not have accessible get accessor",
+ GetSignatureForError (), base_prop.GetSignatureForError ());
+ ok = false;
+ }
+ } else {
if (!base_prop.HasGet) {
if (ok) {
Report.SymbolRelatedToPreviousError (base_prop);
}
}
- if (Set != null) {
+ 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;
+ }
+ } else {
if (!base_prop.HasSet) {
if (ok) {
Report.SymbolRelatedToPreviousError (base_prop);
if (Get != null) {
spec.Get = Get.Spec;
-
- var method = Get.Spec.GetMetaInfo () as MethodBuilder;
- if (method != null) {
- PropertyBuilder.SetGetMethod (method);
- Parent.MemberCache.AddMember (this, method.Name, Get.Spec);
- }
+ Parent.MemberCache.AddMember (this, Get.Spec.Name, Get.Spec);
} else {
CheckMissingAccessor (kind, parameters, true);
}
if (Set != null) {
spec.Set = Set.Spec;
-
- var method = Set.Spec.GetMetaInfo () as MethodBuilder;
- if (method != null) {
- PropertyBuilder.SetSetMethod (method);
- Parent.MemberCache.AddMember (this, method.Name, Set.Spec);
- }
+ Parent.MemberCache.AddMember (this, Set.Spec.Name, Set.Spec);
} else {
CheckMissingAccessor (kind, parameters, false);
}
}
}
+ public override void PrepareEmit ()
+ {
+ AccessorFirst.PrepareEmit ();
+ if (AccessorSecond != null)
+ AccessorSecond.PrepareEmit ();
+
+ if (get != null) {
+ var method = Get.Spec.GetMetaInfo () as MethodBuilder;
+ if (method != null)
+ PropertyBuilder.SetGetMethod (method);
+ }
+
+ if (set != null) {
+ var method = Set.Spec.GetMetaInfo () as MethodBuilder;
+ if (method != null)
+ PropertyBuilder.SetSetMethod (method);
+ }
+ }
+
protected override void SetMemberName (MemberName new_name)
{
base.SetMemberName (new_name);
public sealed class BackingField : 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 BackingField (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 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);
+ return;
+ }
+
+ base.ApplyAttributeBuilder (a, ctor, cdata, pa);
+ }
void CreateAutomaticProperty ()
{
// Create backing field
- Field field = new BackingField (this);
- if (!field.Define ())
+ backing_field = new BackingField (this, Initializer != null && Set == null);
+ if (!backing_field.Define ())
return;
- Parent.PartialContainer.Members.Add (field);
+ if (Initializer != null) {
+ backing_field.Initializer = Initializer;
+ Parent.RegisterFieldForInitialization (backing_field, new FieldInitializer (backing_field, Initializer, Location));
+ backing_field.ModFlags |= Modifiers.READONLY;
+ }
- FieldExpr fe = new FieldExpr (field, Location);
- if ((field.ModFlags & Modifiers.STATIC) == 0)
+ Parent.PartialContainer.Members.Add (backing_field);
+
+ FieldExpr fe = new FieldExpr (backing_field, Location);
+ if ((backing_field.ModFlags & Modifiers.STATIC) == 0)
fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
//
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 (8053, 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) {
+ if (Get == null) {
+ Report.Error (8052, Location, "Auto-implemented property `{0}' must have get accessor",
+ GetSignatureForError ());
+ return false;
+ }
+
+ if (Initializer == null && AccessorSecond == null) {
+ Report.Error (8051, Location, "Auto-implemented property `{0}' must have set accessor or initializer",
+ GetSignatureForError ());
+ }
+
+ 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 ();
}
base.Emit ();
}
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return Get != null && ((Get.ModFlags & Modifiers.COMPILER_GENERATED) != 0) ?
+ attribute_target_auto : base.ValidAttributeTargets;
+ }
+ }
}
/// <summary>
{
}
- public override MethodBuilder Define (TypeContainer ds)
+ public override void Define (TypeContainer ds)
{
CheckAbstractAndExtern (block != null);
- return base.Define (ds);
+ base.Define (ds);
}
public override string 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) {
+ // 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 {
+ body.AddStatement (new StatementExpression (new SimpleAssign (
+ new LocalVariableReference (obj1, Location),
+ new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args))));
+ }
}
}
return false;
if (declarators != null) {
- if ((mod_flags_src & Modifiers.DEFAULT_ACCESS_MODIFER) != 0)
- mod_flags_src &= ~(Modifiers.AccessibilityMask | Modifiers.DEFAULT_ACCESS_MODIFER);
+ if ((mod_flags_src & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0)
+ mod_flags_src &= ~(Modifiers.AccessibilityMask | Modifiers.DEFAULT_ACCESS_MODIFIER);
var t = new TypeExpression (MemberType, TypeExpression.Location);
foreach (var d in declarators) {
return true;
}
- if (Add.IsInterfaceImplementation)
- SetIsUsed ();
-
backing_field = new Field (Parent,
new TypeExpression (MemberType, Location),
Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
return;
}
- base.ApplyAttributeBuilder (a, ctor, cdata, pa);
+ base.ApplyToExtraTarget (a, ctor, cdata, pa);
}
public override AttributeTargets AttributeTargets {
return method.IsClsComplianceRequired ();
}
- public virtual MethodBuilder Define (TypeContainer parent)
+ public virtual void Define (TypeContainer parent)
{
// Fill in already resolved event type to speed things up and
// avoid confusing duplicate errors
method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
- return null;
-
- method_data.DefineMethodBuilder (parent.PartialContainer, ParameterInfo);
+ return;
if (Compiler.Settings.WriteMetadataOnly)
block = null;
Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, ParameterInfo, method.ModFlags);
Spec.IsAccessor = true;
-
- return method_data.MethodBuilder;
}
public override TypeSpec ReturnType {
return method.GetAttributeObsolete ();
}
+ public MethodData MethodData {
+ get {
+ return method_data;
+ }
+ }
+
public override string[] ValidAttributeTargets {
get {
return attribute_targets;
//
// Now define the accessors
//
- var AddBuilder = Add.Define (Parent);
- if (AddBuilder == null)
- return false;
-
- var RemoveBuilder = remove.Define (Parent);
- if (RemoveBuilder == null)
- return false;
+ add.Define (Parent);
+ remove.Define (Parent);
EventBuilder = Parent.TypeBuilder.DefineEvent (GetFullName (MemberName), EventAttributes.None, MemberType.GetMetaInfo ());
- EventBuilder.SetAddOnMethod (AddBuilder);
- EventBuilder.SetRemoveOnMethod (RemoveBuilder);
spec = new EventSpec (Parent.Definition, this, MemberType, ModFlags, Add.Spec, remove.Spec);
Parent.MemberCache.AddMember (this, GetFullName (MemberName), spec);
- Parent.MemberCache.AddMember (this, AddBuilder.Name, Add.Spec);
- Parent.MemberCache.AddMember (this, RemoveBuilder.Name, remove.Spec);
+ Parent.MemberCache.AddMember (this, Add.Spec.Name, Add.Spec);
+ Parent.MemberCache.AddMember (this, Remove.Spec.Name, remove.Spec);
return true;
}
base.Emit ();
}
+ public override void PrepareEmit ()
+ {
+ add.PrepareEmit ();
+ remove.PrepareEmit ();
+
+ EventBuilder.SetAddOnMethod (add.MethodData.MethodBuilder);
+ EventBuilder.SetRemoveOnMethod (remove.MethodData.MethodBuilder);
+ }
+
public override void WriteDebugSymbol (MonoSymbolFile file)
{
add.WriteDebugSymbol (file);
return es;
}
- public override List<TypeSpec> ResolveMissingDependencies ()
+ public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
{
- return MemberType.ResolveMissingDependencies ();
+ return MemberType.ResolveMissingDependencies (this);
}
}
this.parameters = parameters;
}
- public override MethodBuilder Define (TypeContainer parent)
+ public override void Define (TypeContainer parent)
{
// Disable reporting, parameters are resolved twice
Report.DisableReporting ();
Report.EnableReporting ();
}
- return base.Define (parent);
+ base.Define (parent);
}
public override ParametersCompiled ParameterInfo {
return spec;
}
- public override List<TypeSpec> ResolveMissingDependencies ()
+ public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
{
- var missing = base.ResolveMissingDependencies ();
+ var missing = base.ResolveMissingDependencies (caller);
+
foreach (var pt in parameters.Types) {
- var m = pt.GetMissingDependencies ();
+ var m = pt.GetMissingDependencies (caller);
if (m == null)
continue;
if (missing == null)
- missing = new List<TypeSpec> ();
+ missing = new List<MissingTypeSpecReference> ();
missing.AddRange (m);
}