]> granicus.if.org Git - clang/commitdiff
Look through chains of 'x = y = z' when employing silencing heuristics in the DeadSto...
authorTed Kremenek <kremenek@apple.com>
Wed, 4 Apr 2012 19:58:03 +0000 (19:58 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 4 Apr 2012 19:58:03 +0000 (19:58 +0000)
Fixes <rdar://problem/11185138>.

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

lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
test/Analysis/dead-stores.c

index 7457e44e18b0151c848dfe912c57db1d3a1f6d36..510e8cd8104b222e9cb39b6079421b4fa3e4ed9a 100644 (file)
@@ -68,6 +68,21 @@ void ReachableCode::computeReachableBlocks() {
   }
 }
 
+static const Expr *LookThroughTransitiveAssignments(const Expr *Ex) {
+  while (Ex) {
+    const BinaryOperator *BO =
+      dyn_cast<BinaryOperator>(Ex->IgnoreParenCasts());
+    if (!BO)
+      break;
+    if (BO->getOpcode() == BO_Assign) {
+      Ex = BO->getRHS();
+      continue;
+    }
+    break;
+  }
+  return Ex;
+}
+
 namespace {
 class DeadStoreObs : public LiveVariables::Observer {
   const CFG &cfg;
@@ -200,17 +215,18 @@ public:
         if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
           // Special case: check for assigning null to a pointer.
           //  This is a common form of defensive programming.
+          const Expr *RHS = LookThroughTransitiveAssignments(B->getRHS());
+          
           QualType T = VD->getType();
           if (T->isPointerType() || T->isObjCObjectPointerType()) {
-            if (B->getRHS()->isNullPointerConstant(Ctx,
-                                              Expr::NPC_ValueDependentIsNull))
+            if (RHS->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNull))
               return;
           }
 
-          Expr *RHS = B->getRHS()->IgnoreParenCasts();
+          RHS = RHS->IgnoreParenCasts();
           // Special case: self-assignments.  These are often used to shut up
           //  "unused variable" compiler warnings.
-          if (DeclRefExpr *RhsDR = dyn_cast<DeclRefExpr>(RHS))
+          if (const DeclRefExpr *RhsDR = dyn_cast<DeclRefExpr>(RHS))
             if (VD == dyn_cast<VarDecl>(RhsDR->getDecl()))
               return;
 
@@ -252,10 +268,15 @@ public:
           if (V->getType()->getAs<ReferenceType>())
             return;
             
-          if (Expr *E = V->getInit()) {
-            while (ExprWithCleanups *exprClean = dyn_cast<ExprWithCleanups>(E))
+          if (const Expr *E = V->getInit()) {
+            while (const ExprWithCleanups *exprClean =
+                    dyn_cast<ExprWithCleanups>(E))
               E = exprClean->getSubExpr();
             
+            // Look through transitive assignments, e.g.:
+            // int x = y = 0;
+            E = LookThroughTransitiveAssignments(E);
+            
             // Don't warn on C++ objects (yet) until we can show that their
             // constructors/destructors don't have side effects.
             if (isa<CXXConstructExpr>(E))
@@ -275,8 +296,9 @@ public:
               if (E->isEvaluatable(Ctx))
                 return;
 
-              if (DeclRefExpr *DRE=dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
-                if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+              if (const DeclRefExpr *DRE =
+                  dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
+                if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
                   // Special case: check for initialization from constant
                   //  variables.
                   //
index 4c0c1bc130bf90bb340fd006e71d77e3df76a3db..b8d195d05a767fd447127f07e30615d442b91d5b 100644 (file)
@@ -526,3 +526,25 @@ void rdar8405222() {
     rdar8405222_aux(i);
 }
 
+// Look through chains of assignements, e.g.: int x = y = 0, when employing
+// silencing heuristics.
+int radar11185138_foo() {
+  int x, y;
+  x = y = 0; // expected-warning {{never read}}
+  return y;
+}
+
+int rdar11185138_bar() {
+  int y;
+  int x = y = 0; // no-warning
+  x = 2;
+  y = 2;
+  return x + y;
+}
+
+int *radar11185138_baz() {
+  int *x, *y;
+  x = y = 0; // no-warning
+  return y;
+}
+