[Coverage] Fix handling of abnormal exits through repeat blocks

We do not correctly update the counter expression for conditionals in
repeat-while blocks in the following two situations:

Situation 1:

repeat {     // Region 1
  if (C1) {  // Region 2
    break
  }
} while C2   // Should be "Region 1 - Region 2", not "Region 1"

Situation 2:

repeat {     // Region 1
  if (C1) {  // Region 2
    continue
  }
} while C2   // Should be "Region 1", not "Region 1 + Region 2"

Fix both of these problems and add thorough regression tests.

Closes Swift PR #1244, rdar://problem/24572268
This commit is contained in:
Vedant Kumar
2016-02-09 13:19:22 -08:00
parent 5dd6e6f5f4
commit 2a34b7c641
2 changed files with 56 additions and 2 deletions

View File

@@ -514,7 +514,8 @@ public:
} else if (auto *CS = dyn_cast<ContinueStmt>(S)) {
// Continues create extra backedges, add them to the appropriate counters.
addToCounter(CS->getTarget(), getCurrentCounter());
if (!isa<RepeatWhileStmt>(CS->getTarget()))
addToCounter(CS->getTarget(), getCurrentCounter());
if (auto *WS = dyn_cast<WhileStmt>(CS->getTarget())) {
if (auto *E = getConditionNode(WS->getCond()))
addToCounter(E, getCurrentCounter());
@@ -525,8 +526,12 @@ public:
} else if (auto *BS = dyn_cast<BreakStmt>(S)) {
// When we break from a loop, we need to adjust the exit count.
if (!isa<SwitchStmt>(BS->getTarget()))
if (auto *RWS = dyn_cast<RepeatWhileStmt>(BS->getTarget())) {
auto CondCount = CounterExpr::Sub(getCounter(RWS), getCurrentCounter());
addToCounter(RWS->getCond(), createCounter(std::move(CondCount)));
} else if (!isa<SwitchStmt>(BS->getTarget())) {
addToCounter(BS->getTarget(), getCurrentCounter());
}
terminateRegion(S);
} else if (auto *FS = dyn_cast<FallthroughStmt>(S)) {