aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2011-02-12 00:17:19 +0000
committerTed Kremenek <kremenek@apple.com>2011-02-12 00:17:19 +0000
commitf4e532b5a1683a9f6c842f361c7415bf3474315f (patch)
tree64a235fb732ad821ee73e7a4dfbd3c75cc0710da
parent0a86d44703fc5cd3cd38ea1708176f5b44321ed8 (diff)
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
-rw-r--r--include/clang/AST/ParentMap.h5
-rw-r--r--lib/AST/ParentMap.cpp9
-rw-r--r--lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp11
-rw-r--r--test/Analysis/dead-stores.c7
-rw-r--r--test/Analysis/dead-stores.cpp6
5 files changed, 26 insertions, 12 deletions
diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h
index 600321268e..9ea5a0930d 100644
--- a/include/clang/AST/ParentMap.h
+++ b/include/clang/AST/ParentMap.h
@@ -31,6 +31,7 @@ public:
Stmt *getParent(Stmt*) const;
Stmt *getParentIgnoreParens(Stmt *) const;
+ Stmt *getParentIgnoreParenCasts(Stmt *) const;
const Stmt *getParent(const Stmt* S) const {
return getParent(const_cast<Stmt*>(S));
@@ -40,6 +41,10 @@ public:
return getParentIgnoreParens(const_cast<Stmt*>(S));
}
+ const Stmt *getParentIgnoreParenCasts(const Stmt *S) const {
+ return getParentIgnoreParenCasts(const_cast<Stmt*>(S));
+ }
+
bool hasParent(Stmt* S) const {
return getParent(S) != 0;
}
diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp
index 21847f2821..87f8f36e6e 100644
--- a/lib/AST/ParentMap.cpp
+++ b/lib/AST/ParentMap.cpp
@@ -57,6 +57,15 @@ Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
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 {
Stmt *P = getParent(E);
Stmt *DirectChild = E;
diff --git a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
index 442e1b3af7..a6c0ea3154 100644
--- a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -191,6 +191,8 @@ public:
if (S->getLocStart().isMacroID())
return;
+ // Only cover dead stores from regular assignments. ++/-- dead stores
+ // have never flagged a real bug.
if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
if (!B->isAssignmentOp()) return; // Skip non-assignments.
@@ -221,14 +223,11 @@ public:
}
}
else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
- if (!U->isIncrementOp())
+ if (!U->isIncrementOp() || U->isPrefix())
return;
- // Handle: ++x within a subexpression. The solution is not warn
- // about preincrements to dead variables when the preincrement occurs
- // 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))
+ Stmt *parent = Parents.getParentIgnoreParenCasts(U);
+ if (!parent || !isa<ReturnStmt>(parent))
return;
Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
diff --git a/test/Analysis/dead-stores.c b/test/Analysis/dead-stores.c
index 9e3f736d77..942b80e70e 100644
--- a/test/Analysis/dead-stores.c
+++ b/test/Analysis/dead-stores.c
@@ -44,10 +44,11 @@ void f5() {
}
+//
int f6() {
int x = 4;
- ++x; // expected-warning{{never read}}
+ ++x; // no-warning
return 1;
}
@@ -231,7 +232,7 @@ void halt() __attribute__((noreturn));
int f21() {
int x = 4;
- ++x; // expected-warning{{never read}}
+ x = x + 1; // expected-warning{{never read}}
if (1) {
halt();
(void)x;
@@ -263,7 +264,7 @@ void f22() {
int y19 = 4;
int y20 = 4;
- ++x; // expected-warning{{never read}}
+ x = x + 1; // expected-warning{{never read}}
++y1;
++y2;
++y3;
diff --git a/test/Analysis/dead-stores.cpp b/test/Analysis/dead-stores.cpp
index b5fc05028f..9648baceb1 100644
--- a/test/Analysis/dead-stores.cpp
+++ b/test/Analysis/dead-stores.cpp
@@ -12,7 +12,7 @@ int j;
void test1() {
int x = 4;
- ++x; // expected-warning{{never read}}
+ x = x + 1; // expected-warning{{never read}}
switch (j) {
case 1:
@@ -69,11 +69,11 @@ void test2_b() {
//===----------------------------------------------------------------------===//
void test3_a(int x) {
- ++x; // expected-warning{{never read}}
+ x = x + 1; // expected-warning{{never read}}
}
void test3_b(int &x) {
- ++x; // no-warninge
+ x = x + 1; // no-warninge
}
void test3_c(int x) {