提交 9ac1e621 编写于 作者: T Tomas Matousek

Fix syntax associated with bound implicit return statement

上级 5ef9ff2f
......@@ -367,7 +367,7 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType)
}
else
{
block = FlowAnalysisPass.AppendImplicitReturn(block, lambdaSymbol, _unboundLambda.Syntax);
block = FlowAnalysisPass.AppendImplicitReturn(block, lambdaSymbol);
}
}
......
......@@ -634,7 +634,7 @@ private bool ShouldUseIndirectReturn()
private bool CanHandleReturnLabel(BoundReturnStatement boundReturnStatement)
{
return boundReturnStatement.WasCompilerGenerated &&
(boundReturnStatement.Syntax.Kind() == SyntaxKind.Block || (((object)_method != null) && _method.IsImplicitConstructor)) &&
(boundReturnStatement.Syntax.IsKind(SyntaxKind.Block) || _method?.IsImplicitConstructor == true) &&
!_builder.InExceptionHandler;
}
......
......@@ -31,8 +31,7 @@ internal class FlowAnalysisPass
// we don't analyze synthesized void methods.
if (method.IsImplicitlyDeclared || Analyze(compilation, method, block, diagnostics))
{
var sourceMethod = method as SourceMethodSymbol;
block = AppendImplicitReturn(block, method, ((object)sourceMethod != null) ? sourceMethod.BodySyntax as BlockSyntax : null);
block = AppendImplicitReturn(block, method, (CSharpSyntaxNode)(method as SourceMethodSymbol)?.BodySyntax);
}
}
else if (!method.IsScriptInitializer && Analyze(compilation, method, block, diagnostics))
......@@ -56,42 +55,41 @@ internal class FlowAnalysisPass
// insert the implicit "return" statement at the end of the method body
// Normally, we wouldn't bother attaching syntax trees to compiler-generated nodes, but these
// ones are going to have sequence points.
internal static BoundBlock AppendImplicitReturn(BoundStatement node, MethodSymbol method, CSharpSyntaxNode syntax = null)
internal static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol method, CSharpSyntaxNode syntax = null)
{
Debug.Assert(body != null);
Debug.Assert(method != null);
if (syntax == null)
{
syntax = node.Syntax;
syntax = body.Syntax;
}
Debug.Assert(body.WasCompilerGenerated || syntax.IsKind(SyntaxKind.Block) || syntax.IsKind(SyntaxKind.ArrowExpressionClause));
BoundStatement ret = method.IsIterator
? (BoundStatement)BoundYieldBreakStatement.Synthesized(syntax)
: BoundReturnStatement.Synthesized(syntax, null);
if (syntax.Kind() == SyntaxKind.Block)
// Implicitly added return for async method does not need sequence points since lowering would add one.
if (syntax.IsKind(SyntaxKind.Block) && !method.IsAsync)
{
// Implicitly added return for async method does not need sequence points since lowering would add one.
if (!method.IsAsync)
{
var blockSyntax = (BlockSyntax)syntax;
var blockSyntax = (BlockSyntax)syntax;
ret = new BoundSequencePointWithSpan(
blockSyntax,
ret,
blockSyntax.CloseBraceToken.Span)
{ WasCompilerGenerated = true };
}
ret = new BoundSequencePointWithSpan(
blockSyntax,
ret,
blockSyntax.CloseBraceToken.Span)
{ WasCompilerGenerated = true };
}
switch (node.Kind)
switch (body.Kind)
{
case BoundKind.Block:
var block = (BoundBlock)node;
return block.Update(block.Locals, block.Statements.Add(ret));
return body.Update(body.Locals, body.Statements.Add(ret));
default:
return new BoundBlock(syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray.Create(ret, node));
return new BoundBlock(syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray.Create(ret, body));
}
}
......
......@@ -312,8 +312,9 @@ private LambdaFrame GetFrameForScope(BoundNode scope, ArrayBuilder<ClosureDebugI
CompilationState.ModuleBuilderOpt.AddSynthesizedDefinition(this.ContainingType, frame);
CompilationState.AddSynthesizedMethod(
frame.Constructor,
FlowAnalysisPass.AppendImplicitReturn(MethodCompiler.BindMethodBody(frame.Constructor, CompilationState, null),
frame.Constructor));
FlowAnalysisPass.AppendImplicitReturn(
MethodCompiler.BindMethodBody(frame.Constructor, CompilationState, null),
frame.Constructor));
}
return frame;
......@@ -358,8 +359,9 @@ private LambdaFrame GetStaticFrame(DiagnosticBag diagnostics, BoundNode lambda)
// add its ctor
CompilationState.AddSynthesizedMethod(
frame.Constructor,
FlowAnalysisPass.AppendImplicitReturn(MethodCompiler.BindMethodBody(frame.Constructor, CompilationState, null),
frame.Constructor));
FlowAnalysisPass.AppendImplicitReturn(
MethodCompiler.BindMethodBody(frame.Constructor, CompilationState, null),
frame.Constructor));
// associate the frame with the first lambda that caused it to exist.
// we need to associate this with some syntax.
......
......@@ -1289,14 +1289,13 @@ private void F()
// lambda body unchanged:
diff1.VerifyIL("C.<>c.<F>b__2_0", @"
{
// Code size 11 (0xb)
// Code size 9 (0x9)
.maxstack 1
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: call ""void System.Console.WriteLine(int)""
IL_0007: nop
IL_0008: br.s IL_000a
IL_000a: ret
IL_0008: ret
}");
var diff2 = compilation2.EmitDifference(
......@@ -1311,7 +1310,7 @@ .maxstack 1
// lambda body updated:
diff2.VerifyIL("C.<>c.<F>b__2_0", @"
{
// Code size 18 (0x12)
// Code size 16 (0x10)
.maxstack 1
IL_0000: nop
IL_0001: ldc.i4.1
......@@ -1320,8 +1319,7 @@ .maxstack 1
IL_0008: ldc.i4.2
IL_0009: call ""void System.Console.WriteLine(int)""
IL_000e: nop
IL_000f: br.s IL_0011
IL_0011: ret
IL_000f: ret
}");
}
......
......@@ -2722,7 +2722,7 @@ static void M()
var v0 = CompileAndVerify(compilation0);
v0.VerifyIL("C.<>c.<M>b__1_0()", @"
{
// Code size 36 (0x24)
// Code size 34 (0x22)
.maxstack 2
.locals init (object V_0,
bool V_1)
......@@ -2750,8 +2750,7 @@ .maxstack 2
IL_001f: nop
IL_0020: endfinally
}
IL_0021: br.s IL_0023
IL_0023: ret
IL_0021: ret
}");
#if TODO // identify the lambda in a semantic edit
......
......@@ -107,9 +107,9 @@ void M(Action a)
<entry offset=""0x0"" startLine=""10"" startColumn=""9"" endLine=""10"" endColumn=""10"" />
<entry offset=""0x1"" startLine=""12"" startColumn=""13"" endLine=""12"" endColumn=""14"" />
<entry offset=""0x2"" startLine=""14"" startColumn=""13"" endLine=""14"" endColumn=""14"" />
<entry offset=""0x5"" startLine=""15"" startColumn=""9"" endLine=""15"" endColumn=""10"" />
<entry offset=""0x3"" startLine=""15"" startColumn=""9"" endLine=""15"" endColumn=""10"" />
</sequencePoints>
<scope startOffset=""0x0"" endOffset=""0x6"">
<scope startOffset=""0x0"" endOffset=""0x4"">
<constant name=""y"" value=""2"" type=""Int32"" />
<scope startOffset=""0x1"" endOffset=""0x3"">
<constant name=""z"" value=""3"" type=""Int32"" />
......
......@@ -994,10 +994,10 @@ public static void Main(string[] args)
<sequencePoints>
<entry offset=""0x0"" startLine=""10"" startColumn=""32"" endLine=""10"" endColumn=""33"" />
<entry offset=""0x1"" startLine=""10"" startColumn=""46"" endLine=""10"" endColumn=""54"" />
<entry offset=""0x5"" startLine=""10"" startColumn=""55"" endLine=""10"" endColumn=""56"" />
<entry offset=""0x3"" startLine=""10"" startColumn=""55"" endLine=""10"" endColumn=""56"" />
</sequencePoints>
<scope startOffset=""0x0"" endOffset=""0x6"">
<local name=""d5"" il_index=""0"" il_start=""0x0"" il_end=""0x6"" attributes=""0"" />
<scope startOffset=""0x0"" endOffset=""0x4"">
<local name=""d5"" il_index=""0"" il_start=""0x0"" il_end=""0x4"" attributes=""0"" />
</scope>
</method>
<method containingType=""Test+&lt;&gt;c"" name=""&lt;Main&gt;b__2_2"" parameterNames=""d6"">
......
......@@ -1330,5 +1330,89 @@ static void F()
</symbols>
");
}
[Fact]
public void IfStatement1()
{
string source = @"
class C
{
static void F()
{
new System.Action(() =>
{
bool result = false;
if (result)
System.Console.WriteLine(1);
})();
}
}
";
var v = CompileAndVerify(source, options: TestOptions.DebugDll);
v.VerifyIL("C.<>c.<F>b__0_0", @"
{
// Code size 16 (0x10)
.maxstack 1
.locals init (bool V_0, //result
bool V_1)
-IL_0000: nop
-IL_0001: ldc.i4.0
IL_0002: stloc.0
-IL_0003: ldloc.0
IL_0004: stloc.1
~IL_0005: ldloc.1
IL_0006: brfalse.s IL_000f
-IL_0008: ldc.i4.1
IL_0009: call ""void System.Console.WriteLine(int)""
IL_000e: nop
-IL_000f: ret
}
", sequencePoints: "C+<>c.<F>b__0_0");
}
[Fact]
public void IfStatement2()
{
string source = @"
class C
{
static void F()
{
new System.Action(() =>
{
{
bool result = false;
if (result)
System.Console.WriteLine(1);
}
})();
}
}
";
var v = CompileAndVerify(source, options: TestOptions.DebugDll);
v.VerifyIL("C.<>c.<F>b__0_0", @"
{
// Code size 18 (0x12)
.maxstack 1
.locals init (bool V_0, //result
bool V_1)
-IL_0000: nop
-IL_0001: nop
-IL_0002: ldc.i4.0
IL_0003: stloc.0
-IL_0004: ldloc.0
IL_0005: stloc.1
~IL_0006: ldloc.1
IL_0007: brfalse.s IL_0010
-IL_0009: ldc.i4.1
IL_000a: call ""void System.Console.WriteLine(int)""
IL_000f: nop
-IL_0010: nop
-IL_0011: ret
}
", sequencePoints: "C+<>c.<F>b__0_0");
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册