Skip to content

Commit fc93e8f

Browse files
committed
update CFG to properly handle do statements
1 parent 3f16f37 commit fc93e8f

5 files changed

Lines changed: 106 additions & 4 deletions

File tree

src/compiler/binder.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -892,8 +892,13 @@ namespace ts {
892892

893893
function bindDoStatement(node: DoStatement): void {
894894
const preDoLabel = createLoopLabel();
895-
const preConditionLabel = createBranchLabel();
896-
const postDoLabel = createBranchLabel();
895+
const enclosingLabeledStatement = node.parent.kind === SyntaxKind.LabeledStatement
896+
? lastOrUndefined(activeLabels)
897+
: undefined;
898+
// if do statement is wrapped in labeled statement then target labels for break/continue with or without
899+
// label should be the same
900+
const preConditionLabel = enclosingLabeledStatement ? enclosingLabeledStatement.continueTarget : createBranchLabel();
901+
const postDoLabel = enclosingLabeledStatement ? enclosingLabeledStatement.breakTarget : createBranchLabel();
897902
addAntecedent(preDoLabel, currentFlow);
898903
currentFlow = preDoLabel;
899904
bindIterativeStatement(node.statement, postDoLabel, preConditionLabel);
@@ -1111,8 +1116,11 @@ namespace ts {
11111116
if (!activeLabel.referenced && !options.allowUnusedLabels) {
11121117
file.bindDiagnostics.push(createDiagnosticForNode(node.label, Diagnostics.Unused_label));
11131118
}
1114-
addAntecedent(postStatementLabel, currentFlow);
1115-
currentFlow = finishFlowLabel(postStatementLabel);
1119+
if (!node.statement || node.statement.kind !== SyntaxKind.DoStatement) {
1120+
// do statement sets current flow inside bindDoStatement
1121+
addAntecedent(postStatementLabel, currentFlow);
1122+
currentFlow = finishFlowLabel(postStatementLabel);
1123+
}
11161124
}
11171125

11181126
function bindDestructuringTargetFlow(node: Expression) {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//// [doWhileUnreachableCode.ts]
2+
function test() {
3+
let foo = 0;
4+
testLoop: do {
5+
foo++;
6+
continue testLoop;
7+
} while (function() {
8+
var x = 1;
9+
return false;
10+
}());
11+
12+
return foo;
13+
}
14+
15+
//// [doWhileUnreachableCode.js]
16+
function test() {
17+
var foo = 0;
18+
testLoop: do {
19+
foo++;
20+
continue testLoop;
21+
} while (function () {
22+
var x = 1;
23+
return false;
24+
}());
25+
return foo;
26+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
=== tests/cases/compiler/doWhileUnreachableCode.ts ===
2+
function test() {
3+
>test : Symbol(test, Decl(doWhileUnreachableCode.ts, 0, 0))
4+
5+
let foo = 0;
6+
>foo : Symbol(foo, Decl(doWhileUnreachableCode.ts, 1, 7))
7+
8+
testLoop: do {
9+
foo++;
10+
>foo : Symbol(foo, Decl(doWhileUnreachableCode.ts, 1, 7))
11+
12+
continue testLoop;
13+
} while (function() {
14+
var x = 1;
15+
>x : Symbol(x, Decl(doWhileUnreachableCode.ts, 6, 11))
16+
17+
return false;
18+
}());
19+
20+
return foo;
21+
>foo : Symbol(foo, Decl(doWhileUnreachableCode.ts, 1, 7))
22+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
=== tests/cases/compiler/doWhileUnreachableCode.ts ===
2+
function test() {
3+
>test : () => number
4+
5+
let foo = 0;
6+
>foo : number
7+
>0 : 0
8+
9+
testLoop: do {
10+
>testLoop : any
11+
12+
foo++;
13+
>foo++ : number
14+
>foo : number
15+
16+
continue testLoop;
17+
>testLoop : any
18+
19+
} while (function() {
20+
>function() { var x = 1; return false; }() : boolean
21+
>function() { var x = 1; return false; } : () => boolean
22+
23+
var x = 1;
24+
>x : number
25+
>1 : 1
26+
27+
return false;
28+
>false : false
29+
30+
}());
31+
32+
return foo;
33+
>foo : number
34+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function test() {
2+
let foo = 0;
3+
testLoop: do {
4+
foo++;
5+
continue testLoop;
6+
} while (function() {
7+
var x = 1;
8+
return false;
9+
}());
10+
11+
return foo;
12+
}

0 commit comments

Comments
 (0)