]> granicus.if.org Git - clang/commitdiff
Don't emit a dead store for '++' operations unless it occurs with a return statement...
authorTed Kremenek <kremenek@apple.com>
Sat, 12 Feb 2011 00:17:19 +0000 (00:17 +0000)
committerTed Kremenek <kremenek@apple.com>
Sat, 12 Feb 2011 00:17:19 +0000 (00:17 +0000)
Fixes <rdar://problem/6962292>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125419 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ParentMap.h
lib/AST/ParentMap.cpp
lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
test/Analysis/dead-stores.c
test/Analysis/dead-stores.cpp

index 600321268e53ac6b614bf0dfc4efd2aed9cd3d95..9ea5a0930d32857aabedab2bd5cf50c25a7d13af 100644 (file)
@@ -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;
   }
index 21847f28217bd0b14dd78c7ee58811251c39b404..87f8f36e6e220ebe5205fb3e3f1b8f55e49d5aff 100644 (file)
@@ -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;
index 442e1b3af78e0b18ad27c575e690a298f6124293..a6c0ea3154e8a64f1ae2555f41d0748c434b6b4c 100644 (file)
@@ -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();
index 9e3f736d77049b3ad6b66253dfd7efba8982e9b6..942b80e70e13c7eab7f354f9b47cc2b5e06a2000 100644 (file)
@@ -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;
index b5fc05028f7570e2ff4e69ab5697d238733beb47..9648baceb1b5b2f60a8eb74df227b968fb4aa54f 100644 (file)
@@ -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) {