update CFG to properly handle do statements

This commit is contained in:
Vladimir Matveev 2016-10-28 14:17:01 -07:00
parent 3f16f37510
commit fc93e8f6f4
5 changed files with 106 additions and 4 deletions

View File

@ -892,8 +892,13 @@ namespace ts {
function bindDoStatement(node: DoStatement): void {
const preDoLabel = createLoopLabel();
const preConditionLabel = createBranchLabel();
const postDoLabel = createBranchLabel();
const enclosingLabeledStatement = node.parent.kind === SyntaxKind.LabeledStatement
? lastOrUndefined(activeLabels)
: undefined;
// if do statement is wrapped in labeled statement then target labels for break/continue with or without
// label should be the same
const preConditionLabel = enclosingLabeledStatement ? enclosingLabeledStatement.continueTarget : createBranchLabel();
const postDoLabel = enclosingLabeledStatement ? enclosingLabeledStatement.breakTarget : createBranchLabel();
addAntecedent(preDoLabel, currentFlow);
currentFlow = preDoLabel;
bindIterativeStatement(node.statement, postDoLabel, preConditionLabel);
@ -1111,8 +1116,11 @@ namespace ts {
if (!activeLabel.referenced && !options.allowUnusedLabels) {
file.bindDiagnostics.push(createDiagnosticForNode(node.label, Diagnostics.Unused_label));
}
addAntecedent(postStatementLabel, currentFlow);
currentFlow = finishFlowLabel(postStatementLabel);
if (!node.statement || node.statement.kind !== SyntaxKind.DoStatement) {
// do statement sets current flow inside bindDoStatement
addAntecedent(postStatementLabel, currentFlow);
currentFlow = finishFlowLabel(postStatementLabel);
}
}
function bindDestructuringTargetFlow(node: Expression) {

View File

@ -0,0 +1,26 @@
//// [doWhileUnreachableCode.ts]
function test() {
let foo = 0;
testLoop: do {
foo++;
continue testLoop;
} while (function() {
var x = 1;
return false;
}());
return foo;
}
//// [doWhileUnreachableCode.js]
function test() {
var foo = 0;
testLoop: do {
foo++;
continue testLoop;
} while (function () {
var x = 1;
return false;
}());
return foo;
}

View File

@ -0,0 +1,22 @@
=== tests/cases/compiler/doWhileUnreachableCode.ts ===
function test() {
>test : Symbol(test, Decl(doWhileUnreachableCode.ts, 0, 0))
let foo = 0;
>foo : Symbol(foo, Decl(doWhileUnreachableCode.ts, 1, 7))
testLoop: do {
foo++;
>foo : Symbol(foo, Decl(doWhileUnreachableCode.ts, 1, 7))
continue testLoop;
} while (function() {
var x = 1;
>x : Symbol(x, Decl(doWhileUnreachableCode.ts, 6, 11))
return false;
}());
return foo;
>foo : Symbol(foo, Decl(doWhileUnreachableCode.ts, 1, 7))
}

View File

@ -0,0 +1,34 @@
=== tests/cases/compiler/doWhileUnreachableCode.ts ===
function test() {
>test : () => number
let foo = 0;
>foo : number
>0 : 0
testLoop: do {
>testLoop : any
foo++;
>foo++ : number
>foo : number
continue testLoop;
>testLoop : any
} while (function() {
>function() { var x = 1; return false; }() : boolean
>function() { var x = 1; return false; } : () => boolean
var x = 1;
>x : number
>1 : 1
return false;
>false : false
}());
return foo;
>foo : number
}

View File

@ -0,0 +1,12 @@
function test() {
let foo = 0;
testLoop: do {
foo++;
continue testLoop;
} while (function() {
var x = 1;
return false;
}());
return foo;
}