Don't emit a dead store for '++' operations unless it occurs with a return statement. We've never seen any other cases that were real bugs.

Fixes <rdar://problem/6962292>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125419 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ted Kremenek 2011-02-12 00:17:19 +00:00
Родитель 0a86d44703
Коммит f4e532b5a1
5 изменённых файлов: 26 добавлений и 12 удалений

Просмотреть файл

@ -31,6 +31,7 @@ public:
Stmt *getParent(Stmt*) const; Stmt *getParent(Stmt*) const;
Stmt *getParentIgnoreParens(Stmt *) const; Stmt *getParentIgnoreParens(Stmt *) const;
Stmt *getParentIgnoreParenCasts(Stmt *) const;
const Stmt *getParent(const Stmt* S) const { const Stmt *getParent(const Stmt* S) const {
return getParent(const_cast<Stmt*>(S)); return getParent(const_cast<Stmt*>(S));
@ -40,6 +41,10 @@ public:
return getParentIgnoreParens(const_cast<Stmt*>(S)); return getParentIgnoreParens(const_cast<Stmt*>(S));
} }
const Stmt *getParentIgnoreParenCasts(const Stmt *S) const {
return getParentIgnoreParenCasts(const_cast<Stmt*>(S));
}
bool hasParent(Stmt* S) const { bool hasParent(Stmt* S) const {
return getParent(S) != 0; return getParent(S) != 0;
} }

Просмотреть файл

@ -57,6 +57,15 @@ Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
return S; return S;
} }
Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
do {
S = getParent(S);
}
while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S)));
return S;
}
bool ParentMap::isConsumedExpr(Expr* E) const { bool ParentMap::isConsumedExpr(Expr* E) const {
Stmt *P = getParent(E); Stmt *P = getParent(E);
Stmt *DirectChild = E; Stmt *DirectChild = E;

Просмотреть файл

@ -191,6 +191,8 @@ public:
if (S->getLocStart().isMacroID()) if (S->getLocStart().isMacroID())
return; return;
// Only cover dead stores from regular assignments. ++/-- dead stores
// have never flagged a real bug.
if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
if (!B->isAssignmentOp()) return; // Skip non-assignments. if (!B->isAssignmentOp()) return; // Skip non-assignments.
@ -221,14 +223,11 @@ public:
} }
} }
else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) { else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
if (!U->isIncrementOp()) if (!U->isIncrementOp() || U->isPrefix())
return; return;
// Handle: ++x within a subexpression. The solution is not warn Stmt *parent = Parents.getParentIgnoreParenCasts(U);
// about preincrements to dead variables when the preincrement occurs if (!parent || !isa<ReturnStmt>(parent))
// as a subexpression. This can lead to false negatives, e.g. "(++x);"
// A generalized dead code checker should find such issues.
if (U->isPrefix() && Parents.isConsumedExpr(U))
return; return;
Expr *Ex = U->getSubExpr()->IgnoreParenCasts(); Expr *Ex = U->getSubExpr()->IgnoreParenCasts();

Просмотреть файл

@ -44,10 +44,11 @@ void f5() {
} }
//
int f6() { int f6() {
int x = 4; int x = 4;
++x; // expected-warning{{never read}} ++x; // no-warning
return 1; return 1;
} }
@ -231,7 +232,7 @@ void halt() __attribute__((noreturn));
int f21() { int f21() {
int x = 4; int x = 4;
++x; // expected-warning{{never read}} x = x + 1; // expected-warning{{never read}}
if (1) { if (1) {
halt(); halt();
(void)x; (void)x;
@ -263,7 +264,7 @@ void f22() {
int y19 = 4; int y19 = 4;
int y20 = 4; int y20 = 4;
++x; // expected-warning{{never read}} x = x + 1; // expected-warning{{never read}}
++y1; ++y1;
++y2; ++y2;
++y3; ++y3;

Просмотреть файл

@ -12,7 +12,7 @@ int j;
void test1() { void test1() {
int x = 4; int x = 4;
++x; // expected-warning{{never read}} x = x + 1; // expected-warning{{never read}}
switch (j) { switch (j) {
case 1: case 1:
@ -69,11 +69,11 @@ void test2_b() {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
void test3_a(int x) { void test3_a(int x) {
++x; // expected-warning{{never read}} x = x + 1; // expected-warning{{never read}}
} }
void test3_b(int &x) { void test3_b(int &x) {
++x; // no-warninge x = x + 1; // no-warninge
} }
void test3_c(int x) { void test3_c(int x) {