forked from OSchip/llvm-project
[analyzer] Check all conditions in a chained if against each other.
Like the binary operator check of r201702, this actually checks the condition of every if in a chain against every other condition, an O(N^2) operation. In most cases N should be small enough to make this practical, and checking all cases like this makes it much more likely to catch a copy-paste error within the same series of branches. Part of IdenticalExprChecker; patch by Daniel Fahlgren! llvm-svn: 203585
This commit is contained in:
parent
b708306128
commit
a6839aaa9b
|
@ -108,6 +108,30 @@ bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) {
|
|||
const Stmt *Stmt1 = I->getThen();
|
||||
const Stmt *Stmt2 = I->getElse();
|
||||
|
||||
// Check for identical conditions:
|
||||
//
|
||||
// if (b) {
|
||||
// foo1();
|
||||
// } else if (b) {
|
||||
// foo2();
|
||||
// }
|
||||
if (Stmt1 && Stmt2) {
|
||||
const Expr *Cond1 = I->getCond();
|
||||
const Stmt *Else = Stmt2;
|
||||
while (const IfStmt *I2 = dyn_cast_or_null<IfStmt>(Else)) {
|
||||
const Expr *Cond2 = I2->getCond();
|
||||
if (isIdenticalStmt(AC->getASTContext(), Cond1, Cond2, false)) {
|
||||
SourceRange Sr = Cond1->getSourceRange();
|
||||
PathDiagnosticLocation ELoc(Cond2, BR.getSourceManager(), AC);
|
||||
BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions",
|
||||
categories::LogicError,
|
||||
"expression is identical to previous condition",
|
||||
ELoc, Sr);
|
||||
}
|
||||
Else = I2->getElse();
|
||||
}
|
||||
}
|
||||
|
||||
if (!Stmt1 || !Stmt2)
|
||||
return true;
|
||||
|
||||
|
|
|
@ -1406,3 +1406,108 @@ void test_identical_logical9(int x, int y) {
|
|||
;
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
void test_warn_chained_if_stmts_1(int x) {
|
||||
if (x == 1)
|
||||
;
|
||||
else if (x == 1) // expected-warning {{expression is identical to previous condition}}
|
||||
;
|
||||
}
|
||||
|
||||
void test_warn_chained_if_stmts_2(int x) {
|
||||
if (x == 1)
|
||||
;
|
||||
else if (x == 1) // expected-warning {{expression is identical to previous condition}}
|
||||
;
|
||||
else if (x == 1) // expected-warning {{expression is identical to previous condition}}
|
||||
;
|
||||
}
|
||||
|
||||
void test_warn_chained_if_stmts_3(int x) {
|
||||
if (x == 1)
|
||||
;
|
||||
else if (x == 2)
|
||||
;
|
||||
else if (x == 1) // expected-warning {{expression is identical to previous condition}}
|
||||
;
|
||||
}
|
||||
|
||||
void test_warn_chained_if_stmts_4(int x) {
|
||||
if (x == 1)
|
||||
;
|
||||
else if (func())
|
||||
;
|
||||
else if (x == 1) // expected-warning {{expression is identical to previous condition}}
|
||||
;
|
||||
}
|
||||
|
||||
void test_warn_chained_if_stmts_5(int x) {
|
||||
if (x & 1)
|
||||
;
|
||||
else if (x & 1) // expected-warning {{expression is identical to previous condition}}
|
||||
;
|
||||
}
|
||||
|
||||
void test_warn_chained_if_stmts_6(int x) {
|
||||
if (x == 1)
|
||||
;
|
||||
else if (x == 2)
|
||||
;
|
||||
else if (x == 2) // expected-warning {{expression is identical to previous condition}}
|
||||
;
|
||||
else if (x == 3)
|
||||
;
|
||||
}
|
||||
|
||||
void test_warn_chained_if_stmts_7(int x) {
|
||||
if (x == 1)
|
||||
;
|
||||
else if (x == 2)
|
||||
;
|
||||
else if (x == 3)
|
||||
;
|
||||
else if (x == 2) // expected-warning {{expression is identical to previous condition}}
|
||||
;
|
||||
else if (x == 5)
|
||||
;
|
||||
}
|
||||
|
||||
void test_warn_chained_if_stmts_8(int x) {
|
||||
if (x == 1)
|
||||
;
|
||||
else if (x == 2)
|
||||
;
|
||||
else if (x == 3)
|
||||
;
|
||||
else if (x == 2) // expected-warning {{expression is identical to previous condition}}
|
||||
;
|
||||
else if (x == 5)
|
||||
;
|
||||
else if (x == 3) // expected-warning {{expression is identical to previous condition}}
|
||||
;
|
||||
else if (x == 7)
|
||||
;
|
||||
}
|
||||
|
||||
void test_nowarn_chained_if_stmts_1(int x) {
|
||||
if (func())
|
||||
;
|
||||
else if (func()) // no-warning
|
||||
;
|
||||
}
|
||||
|
||||
void test_nowarn_chained_if_stmts_2(int x) {
|
||||
if (func())
|
||||
;
|
||||
else if (x == 1)
|
||||
;
|
||||
else if (func()) // no-warning
|
||||
;
|
||||
}
|
||||
|
||||
void test_nowarn_chained_if_stmts_3(int x) {
|
||||
if (x++)
|
||||
;
|
||||
else if (x++) // no-warning
|
||||
;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue