From f4e532b5a1683a9f6c842f361c7415bf3474315f Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Sat, 12 Feb 2011 00:17:19 +0000 Subject: [PATCH] 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 . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125419 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ParentMap.h | 5 +++++ lib/AST/ParentMap.cpp | 9 +++++++++ lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp | 11 +++++------ test/Analysis/dead-stores.c | 7 ++++--- test/Analysis/dead-stores.cpp | 6 +++--- 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(S)); @@ -40,6 +41,10 @@ public: return getParentIgnoreParens(const_cast(S)); } + const Stmt *getParentIgnoreParenCasts(const Stmt *S) const { + return getParentIgnoreParenCasts(const_cast(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(S) || isa(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(S)) { if (!B->isAssignmentOp()) return; // Skip non-assignments. @@ -221,14 +223,11 @@ public: } } else if (UnaryOperator* U = dyn_cast(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(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) {