From dfdc94b6cdfc49215a3d49d0321aa668aea1de1a Mon Sep 17 00:00:00 2001 From: Wonseok Chae Date: Wed, 6 May 2015 10:53:25 -0700 Subject: [PATCH] Setting next statement inside a scope with a lambda cause NRE This happens since setting next statement skips the closure initialization, which marks as hidden sequence point. In this PR, we emit a regular sequence point instead of a hidden sequence point to closure initialization whenever necessary, so IP move won't skip closure initialization. --- .../Lowering/LambdaRewriter/LambdaRewriter.cs | 41 +- .../CSharp/Test/Emit/PDB/PDBAsyncTests.cs | 56 +- .../CSharp/Test/Emit/PDB/PDBIteratorTests.cs | 115 ++-- .../CSharp/Test/Emit/PDB/PDBLambdaTests.cs | 620 +++++++++++++----- .../CSharp/Test/Emit/PDB/PDBTests.cs | 3 +- 5 files changed, 562 insertions(+), 273 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.cs index 0fe2b3cb8dc..6487e304280 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.cs @@ -694,22 +694,49 @@ private BoundBlock RewriteBlock(BoundBlock node, ArrayBuilder p var newStatements = ArrayBuilder.GetInstance(); - if (prologue.Count > 0) - { - newStatements.Add(new BoundSequencePoint(null, null) { WasCompilerGenerated = true }); - } - - InsertAndFreePrologue(newStatements, prologue); - foreach (var statement in node.Statements) { var replacement = (BoundStatement)this.Visit(statement); if (replacement != null) { + if (newStatements.Count == 0 && prologue.Count > 0) + { + for (int i = 0; i < prologue.Count; i++) + { + BoundStatement prologueStatement = new BoundExpressionStatement(prologue[i].Syntax, prologue[i]); + + // transfer the bound sequence point from the first rewritten statement to the first prologue expression statement: + if (i == 0) + { + BoundSequencePoint sequencePoint; + BoundSequencePointWithSpan sequencePointWithSpan; + if ((sequencePointWithSpan = replacement as BoundSequencePointWithSpan) != null) + { + prologueStatement = new BoundSequencePointWithSpan(sequencePointWithSpan.Syntax, prologueStatement, sequencePointWithSpan.Span); + replacement = sequencePointWithSpan.StatementOpt; + } + else if ((sequencePoint = replacement as BoundSequencePoint) != null) + { + prologueStatement = new BoundSequencePoint(sequencePoint.Syntax, prologueStatement); + replacement = sequencePoint.StatementOpt; + } + } + + newStatements.Add(prologueStatement); + } + + if (replacement == null) + { + continue; + } + } + newStatements.Add(replacement); } } + prologue.Free(); + // TODO: we may not need to update if there was nothing to rewrite. return node.Update(newLocals.ToImmutableAndFree(), newStatements.ToImmutableAndFree()); } diff --git a/src/Compilers/CSharp/Test/Emit/PDB/PDBAsyncTests.cs b/src/Compilers/CSharp/Test/Emit/PDB/PDBAsyncTests.cs index 316998c5c4e..0b593409536 100644 --- a/src/Compilers/CSharp/Test/Emit/PDB/PDBAsyncTests.cs +++ b/src/Compilers/CSharp/Test/Emit/PDB/PDBAsyncTests.cs @@ -624,7 +624,7 @@ static async Task M(int b) - - - - - + + + + + @@ -905,25 +896,23 @@ void F()