--- /dev/null
+// CS0728: Possibly incorrect assignment to `d' which is the argument to a using or lock statement
+// Line: 12
+// Compiler options: -warnaserror
+
+using System;
+
+public class Foo
+{
+ public static void Test (IDisposable d)
+ {
+ using (d) {
+ d = null;
+ }
+ }
+}
--- /dev/null
+// CS0728: Possibly incorrect assignment to `s' which is the argument to a using or lock statement
+// Line: 12
+// Compiler options: -warnaserror
+
+public class Foo
+{
+ public static void Test (ref string s)
+ {
+ lock (s) {
+ lock (s) {}
+ s = null;
+ }
+ }
+}
--- /dev/null
+// CS0728: Possibly incorrect assignment to `token' which is the argument to a using or lock statement
+// Line: 11
+// Compiler options: -warnaserror
+
+public class Foo
+{
+ public static void Main ()
+ {
+ object token = new object ();
+ lock (token)
+ {
+ Foo2 (ref token);
+ }
+ }
+
+ static void Foo2 (ref object o)
+ {
+ }
+}
this.loc = loc;
}
+ public override bool IsLockedByStatement {
+ get {
+ return false;
+ }
+ set {
+ }
+ }
+
public LocalVariable LocalInfo {
get {
return li;
#region Abstract
public abstract HoistedVariable GetHoistedVariable (AnonymousExpression ae);
+
+ public abstract bool IsLockedByStatement { get; set; }
+
public abstract bool IsFixed { get; }
public abstract bool IsRef { get; }
public abstract string Name { get; }
Variable.EmitAddressOf (ec);
}
- public HoistedVariable GetHoistedVariable (ResolveContext rc)
- {
- return GetHoistedVariable (rc.CurrentAnonymousMethod);
- }
-
- public HoistedVariable GetHoistedVariable (EmitContext ec)
+ public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
{
- return GetHoistedVariable (ec.CurrentAnonymousMethod);
- }
+ if (IsLockedByStatement) {
+ rc.Report.Warning (728, 2, loc,
+ "Possibly incorrect assignment to `{0}' which is the argument to a using or lock statement",
+ Name);
+ }
- public override string GetSignatureForError ()
- {
- return Name;
+ return this;
}
public override void Emit (EmitContext ec)
}
}
+
+ public HoistedVariable GetHoistedVariable (ResolveContext rc)
+ {
+ return GetHoistedVariable (rc.CurrentAnonymousMethod);
+ }
+
+ public HoistedVariable GetHoistedVariable (EmitContext ec)
+ {
+ return GetHoistedVariable (ec.CurrentAnonymousMethod);
+ }
+
+ public override string GetSignatureForError ()
+ {
+ return Name;
+ }
+
public bool IsHoisted {
get { return GetHoistedVariable ((AnonymousExpression) null) != null; }
}
return local_info.HoistedVariant;
}
+ #region Properties
+
//
// A local variable is always fixed
//
public override bool IsFixed {
- get { return true; }
+ get {
+ return true;
+ }
+ }
+
+ public override bool IsLockedByStatement {
+ get {
+ return local_info.IsLocked;
+ }
+ set {
+ local_info.IsLocked = value;
+ }
}
public override bool IsRef {
get { return local_info.Name; }
}
+ #endregion
+
public bool VerifyAssigned (ResolveContext ec)
{
VariableInfo variable_info = local_info.VariableInfo;
return CreateExpressionFactoryCall (ec, "Constant", arg);
}
- Expression DoResolveBase (ResolveContext ec)
+ void DoResolveBase (ResolveContext ec)
{
VerifyAssigned (ec);
eclass = ExprClass.Variable;
type = local_info.Type;
- return this;
}
protected override Expression DoResolve (ResolveContext ec)
{
local_info.SetIsUsed ();
- return DoResolveBase (ec);
+ DoResolveBase (ec);
+ return this;
}
public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
VariableInfo.SetAssigned (ec);
}
- return DoResolveBase (ec);
+ DoResolveBase (ec);
+
+ return base.DoResolveLValue (ec, right_side);
}
public override int GetHashCode ()
#region Properties
+ public override bool IsLockedByStatement {
+ get {
+ return pi.IsLocked;
+ }
+ set {
+ pi.IsLocked = value;
+ }
+ }
+
public override bool IsRef {
get { return (pi.Parameter.ModFlags & Parameter.Modifier.ISBYREF) != 0; }
}
return this;
}
- override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
+ public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
{
if (!DoResolveBase (ec))
return null;
SetAssigned (ec);
- return this;
+ return base.DoResolveLValue (ec, right_side);
}
static public void EmitLdArg (EmitContext ec, int x)
get { return "this"; }
}
+ public override bool IsLockedByStatement {
+ get {
+ return false;
+ }
+ set {
+ }
+ }
+
public override bool IsRef {
get { return type.IsStruct; }
}
219, 251, 252, 253, 278, 282,
402, 414, 419, 420, 429, 436, 440, 458, 464, 465, 467, 469, 472,
612, 618, 626, 628, 642, 649, 652, 658, 659, 660, 661, 665, 672, 675, 693,
+ 728,
809,
1030, 1058, 1066,
1522, 1570, 1571, 1572, 1573, 1574, 1580, 1581, 1584, 1587, 1589, 1590, 1591, 1592,
FixedVariable = 1 << 6,
UsingVariable = 1 << 7,
// DefinitelyAssigned = 1 << 8,
+ IsLocked = 1 << 9,
ReadonlyMask = ForeachVariable | FixedVariable | UsingVariable
}
#region Properties
+ public bool AddressTaken {
+ get { return (flags & Flags.AddressTaken) != 0; }
+ set { flags |= Flags.AddressTaken; }
+ }
+
public Block Block {
get {
return block;
}
}
+ public bool IsLocked {
+ get {
+ return (flags & Flags.IsLocked) != 0;
+ }
+ set {
+ flags = value ? flags | Flags.IsLocked : flags & ~Flags.IsLocked;
+ }
+ }
+
public bool IsThis {
get {
return (flags & Flags.IsThis) != 0;
ec.Emit (OpCodes.Ldloca, builder);
}
+ public string GetReadOnlyContext ()
+ {
+ switch (flags & Flags.ReadonlyMask) {
+ case Flags.FixedVariable:
+ return "fixed variable";
+ case Flags.ForeachVariable:
+ return "foreach iteration variable";
+ case Flags.UsingVariable:
+ return "using variable";
+ }
+
+ throw new InternalErrorException ("Variable is not readonly");
+ }
+
public bool IsThisAssigned (BlockContext ec, Block block)
{
if (VariableInfo == null)
flags |= Flags.Used;
}
- public bool AddressTaken {
- get { return (flags & Flags.AddressTaken) != 0; }
- set { flags |= Flags.AddressTaken; }
- }
-
public override string ToString ()
{
return string.Format ("LocalInfo ({0},{1},{2},{3})", name, type, VariableInfo, Location);
}
-
- public string GetReadOnlyContext ()
- {
- switch (flags & Flags.ReadonlyMask) {
- case Flags.FixedVariable:
- return "fixed variable";
- case Flags.ForeachVariable:
- return "foreach iteration variable";
- case Flags.UsingVariable:
- return "using variable";
- }
-
- throw new InternalErrorException ("Variable is not readonly");
- }
}
/// <summary>
readonly ParametersBlock block;
readonly int index;
public VariableInfo VariableInfo;
+ bool is_locked;
public ParameterInfo (ParametersBlock block, int index)
{
}
}
+ public bool IsLocked {
+ get {
+ return is_locked;
+ }
+ set {
+ is_locked = value;
+ }
+ }
+
public Location Location {
get {
return Parameter.Location;
expr.Type.GetSignatureForError ());
}
+ VariableReference lv = expr as VariableReference;
+ bool locked;
+ if (lv != null) {
+ locked = lv.IsLockedByStatement;
+ lv.IsLockedByStatement = true;
+ } else {
+ lv = null;
+ locked = false;
+ }
+
ec.StartFlowBranching (this);
- bool ok = Statement.Resolve (ec);
+ Statement.Resolve (ec);
ec.EndFlowBranching ();
- ok &= base.Resolve (ec);
+ if (lv != null) {
+ lv.IsLockedByStatement = locked;
+ }
+
+ base.Resolve (ec);
//
// Have to keep original lock value around to unlock same location
lock_taken.Resolve (ec);
}
- return ok;
+ return true;
}
protected override void EmitPreTryBody (EmitContext ec)
return base.Resolve (bc);
}
- public void ResolveExpression (BlockContext bc)
+ public Expression ResolveExpression (BlockContext bc)
{
var e = Initializer.Resolve (bc);
if (e == null)
- return;
+ return null;
li = LocalVariable.CreateCompilerGenerated (e.Type, bc.CurrentBlock, loc);
Initializer = ResolveInitializer (bc, Variable, e);
+ return e;
}
protected override Expression ResolveInitializer (BlockContext bc, LocalVariable li, Expression initializer)
public override bool Resolve (BlockContext ec)
{
+ VariableReference vr;
+ bool vr_locked = false;
+
using (ec.Set (ResolveContext.Options.UsingInitializerScope)) {
if (decl.Variable == null) {
- decl.ResolveExpression (ec);
+ vr = decl.ResolveExpression (ec) as VariableReference;
+ if (vr != null) {
+ vr_locked = vr.IsLockedByStatement;
+ vr.IsLockedByStatement = true;
+ }
} else {
if (!decl.Resolve (ec))
return false;
if (decl.Declarators != null) {
stmt = decl.RewriteForDeclarators (ec, stmt);
}
+
+ vr = null;
}
}
ec.StartFlowBranching (this);
- bool ok = stmt.Resolve (ec);
+ stmt.Resolve (ec);
ec.EndFlowBranching ();
- ok &= base.Resolve (ec);
+ if (vr != null)
+ vr.IsLockedByStatement = vr_locked;
- return ok;
+ base.Resolve (ec);
+
+ return true;
}
protected override void CloneTo (CloneContext clonectx, Statement t)