提交 437dad95 编写于 作者: A AlekseyTs

Improve location of ERR_ParamUnassigned error for local functions.

Fixes #12467.
上级 e362f8b5
......@@ -111,16 +111,26 @@ public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatemen
RestorePending(oldPending2); // process any forward branches within the lambda body
ImmutableArray<PendingBranch> pendingReturns = RemoveReturns();
RestorePending(oldPending);
LeaveParameters(localFunc.Symbol.Parameters, localFunc.Syntax, null);
Location location = null;
if (!localFunc.Symbol.Locations.IsDefaultOrEmpty)
{
location = localFunc.Symbol.Locations[0];
}
LeaveParameters(localFunc.Symbol.Parameters, localFunc.Syntax, location);
LocalState stateAtReturn = this.State;
foreach (PendingBranch pending in pendingReturns)
{
this.State = pending.State;
if (pending.Branch.Kind == BoundKind.ReturnStatement)
BoundNode branch = pending.Branch;
if (branch.Kind == BoundKind.ReturnStatement)
{
// ensure out parameters are definitely assigned at each return
LeaveParameters(localFunc.Symbol.Parameters, pending.Branch.Syntax, null);
LeaveParameters(localFunc.Symbol.Parameters, branch.Syntax,
branch.WasCompilerGenerated ? location : null);
IntersectWith(ref stateAtReturn, ref this.State);
}
else
......
......@@ -1606,5 +1606,139 @@ async Task<async> Test(Task<async> t)
expectedOutput: "async");
}
}
[Fact]
[WorkItem(12467, "https://github.com/dotnet/roslyn/issues/12467")]
public void ParamUnassigned_01()
{
var src = @"
class C
{
public void M1()
{
void TakeOutParam1(out int x)
{
}
int y;
TakeOutParam1(out y);
}
void TakeOutParam2(out int x)
{
}
}";
VerifyDiagnostics(src,
// (6,14): error CS0177: The out parameter 'x' must be assigned to before control leaves the current method
// void TakeOutParam1(out int x)
Diagnostic(ErrorCode.ERR_ParamUnassigned, "TakeOutParam1").WithArguments("x").WithLocation(6, 14),
// (14,14): error CS0177: The out parameter 'x' must be assigned to before control leaves the current method
// void TakeOutParam2(out int x)
Diagnostic(ErrorCode.ERR_ParamUnassigned, "TakeOutParam2").WithArguments("x").WithLocation(14, 14)
);
}
[Fact]
[WorkItem(12467, "https://github.com/dotnet/roslyn/issues/12467")]
public void ParamUnassigned_02()
{
var src = @"
class C
{
public void M1()
{
void TakeOutParam1(out int x)
{
return; // 1
}
int y;
TakeOutParam1(out y);
}
void TakeOutParam2(out int x)
{
return; // 2
}
}";
VerifyDiagnostics(src,
// (8,13): error CS0177: The out parameter 'x' must be assigned to before control leaves the current method
// return; // 1
Diagnostic(ErrorCode.ERR_ParamUnassigned, "return;").WithArguments("x").WithLocation(8, 13),
// (17,13): error CS0177: The out parameter 'x' must be assigned to before control leaves the current method
// return; // 2
Diagnostic(ErrorCode.ERR_ParamUnassigned, "return;").WithArguments("x").WithLocation(17, 13)
);
}
[Fact]
[WorkItem(12467, "https://github.com/dotnet/roslyn/issues/12467")]
public void ParamUnassigned_03()
{
var src = @"
class C
{
public void M1()
{
int TakeOutParam1(out int x)
{
}
int y;
TakeOutParam1(out y);
}
int TakeOutParam2(out int x)
{
}
}";
VerifyDiagnostics(src,
// (6,13): error CS0161: 'TakeOutParam1(out int)': not all code paths return a value
// int TakeOutParam1(out int x)
Diagnostic(ErrorCode.ERR_ReturnExpected, "TakeOutParam1").WithArguments("TakeOutParam1(out int)").WithLocation(6, 13),
// (6,13): error CS0177: The out parameter 'x' must be assigned to before control leaves the current method
// int TakeOutParam1(out int x)
Diagnostic(ErrorCode.ERR_ParamUnassigned, "TakeOutParam1").WithArguments("x").WithLocation(6, 13),
// (14,13): error CS0177: The out parameter 'x' must be assigned to before control leaves the current method
// int TakeOutParam2(out int x)
Diagnostic(ErrorCode.ERR_ParamUnassigned, "TakeOutParam2").WithArguments("x").WithLocation(14, 13),
// (14,13): error CS0161: 'C.TakeOutParam2(out int)': not all code paths return a value
// int TakeOutParam2(out int x)
Diagnostic(ErrorCode.ERR_ReturnExpected, "TakeOutParam2").WithArguments("C.TakeOutParam2(out int)").WithLocation(14, 13)
);
}
[Fact]
[WorkItem(12467, "https://github.com/dotnet/roslyn/issues/12467")]
public void ParamUnassigned_04()
{
var src = @"
class C
{
public void M1()
{
int TakeOutParam1(out int x)
{
return 1;
}
int y;
TakeOutParam1(out y);
}
int TakeOutParam2(out int x)
{
return 2;
}
}";
VerifyDiagnostics(src,
// (8,13): error CS0177: The out parameter 'x' must be assigned to before control leaves the current method
// return 1;
Diagnostic(ErrorCode.ERR_ParamUnassigned, "return 1;").WithArguments("x").WithLocation(8, 13),
// (17,13): error CS0177: The out parameter 'x' must be assigned to before control leaves the current method
// return 2;
Diagnostic(ErrorCode.ERR_ParamUnassigned, "return 2;").WithArguments("x").WithLocation(17, 13)
);
}
}
}
......@@ -17751,9 +17751,9 @@ public static void Main()
// (8,23): error CS0103: The name 'x3' does not exist in the current context
// int c[out var x3] = null; // fatal syntax error - 'out' is skipped
Diagnostic(ErrorCode.ERR_NameNotInContext, "x3").WithArguments("x3").WithLocation(8, 23),
// (7,9): error CS0177: The out parameter 'x2' must be assigned to before control leaves the current method
// (7,13): error CS0177: The out parameter 'x2' must be assigned to before control leaves the current method
// int b(out var x2) = null; // parsed as a local function with syntax error
Diagnostic(ErrorCode.ERR_ParamUnassigned, "int b(out var x2) ").WithArguments("x2").WithLocation(7, 9),
Diagnostic(ErrorCode.ERR_ParamUnassigned, "b").WithArguments("x2").WithLocation(7, 13),
// (6,25): warning CS0219: The variable 'a' is assigned but its value is never used
// int[out var x1] a = null; // fatal syntax error - 'out' is skipped
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "a").WithArguments("a").WithLocation(6, 25),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册