forked from OSchip/llvm-project
[-Wunreachable-code] Handle idiomatic do...while() with an uninteresting condition.
Sometimes do..while() is used to create a scope that can be left early. In such cases, the unreachable 'while()' test is not usually interesting unless it actually does something that is observable. llvm-svn: 203036
This commit is contained in:
parent
4b047f2378
commit
1de2e14f2f
|
@ -296,10 +296,7 @@ static bool isTrivialExpression(const Expr *Ex) {
|
|||
isEnumConstant(Ex);
|
||||
}
|
||||
|
||||
static bool isTrivialReturn(const CFGBlock *B, const Stmt *S) {
|
||||
if (B->pred_empty())
|
||||
return false;
|
||||
|
||||
static bool isTrivialReturnOrDoWhile(const CFGBlock *B, const Stmt *S) {
|
||||
const Expr *Ex = dyn_cast<Expr>(S);
|
||||
if (!Ex)
|
||||
return false;
|
||||
|
@ -307,6 +304,16 @@ static bool isTrivialReturn(const CFGBlock *B, const Stmt *S) {
|
|||
if (!isTrivialExpression(Ex))
|
||||
return false;
|
||||
|
||||
// Check if the block ends with a do...while() and see if 'S' is the
|
||||
// condition.
|
||||
if (const Stmt *Term = B->getTerminator()) {
|
||||
if (const DoStmt *DS = dyn_cast<DoStmt>(Term))
|
||||
if (DS->getCond() == S)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Look to see if the block ends with a 'return', and see if 'S'
|
||||
// is a substatement. The 'return' may not be the last element in
|
||||
// the block because of destructors.
|
||||
|
@ -317,12 +324,15 @@ static bool isTrivialReturn(const CFGBlock *B, const Stmt *S) {
|
|||
if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
|
||||
const Expr *RE = RS->getRetValue();
|
||||
if (RE && RE->IgnoreParenCasts() == Ex)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (B->pred_size() == 1)
|
||||
return bodyEndsWithNoReturn(*B->pred_begin());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -336,7 +346,7 @@ void DeadCodeScan::reportDeadCode(const CFGBlock *B,
|
|||
return;
|
||||
|
||||
// Suppress trivial 'return' statements that are dead.
|
||||
if (isTrivialReturn(B, S))
|
||||
if (isTrivialReturnOrDoWhile(B, S))
|
||||
return;
|
||||
|
||||
SourceRange R1, R2;
|
||||
|
|
|
@ -268,9 +268,31 @@ int test_MyEnum() {
|
|||
return 2; // no-warning
|
||||
if (ME_B)
|
||||
return 3;
|
||||
// FIXME: we should only need one diagnostic here.
|
||||
if (!ME_B) // expected-warning {{will never be executed}}
|
||||
return 4;// expected-warning {{will never be executed}}
|
||||
return 4; // expected-warning {{will never be executed}}
|
||||
return 5;
|
||||
}
|
||||
|
||||
// Test for idiomatic do..while.
|
||||
int test_do_while(int x) {
|
||||
do {
|
||||
if (x == calledFun())
|
||||
break;
|
||||
++x;
|
||||
break;
|
||||
}
|
||||
while (0); // no-warning
|
||||
return x;
|
||||
}
|
||||
|
||||
int test_do_while_nontrivial_cond(int x) {
|
||||
do {
|
||||
if (x == calledFun())
|
||||
break;
|
||||
++x;
|
||||
break;
|
||||
}
|
||||
while (calledFun()); // expected-warning {{will never be executed}}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue