]> granicus.if.org Git - clang/commitdiff
[analyzer] Teach DeadStoreChecker to look though BO_Comma and disregard the LHS.
authorAnna Zaks <ganna@apple.com>
Thu, 25 Apr 2013 21:52:35 +0000 (21:52 +0000)
committerAnna Zaks <ganna@apple.com>
Thu, 25 Apr 2013 21:52:35 +0000 (21:52 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180579 91177308-0d34-0410-b5e6-96231b3b80d8

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

index f2e3e6d7815e113a24f0667fd7af8c73f8c58541..f336a6e680519a41816da8e5d5eca930e85dcbc4 100644 (file)
@@ -101,7 +101,8 @@ void ReachableCode::computeReachableBlocks() {
   }
 }
 
-static const Expr *LookThroughTransitiveAssignments(const Expr *Ex) {
+static const Expr *
+LookThroughTransitiveAssignmentsAndCommaOperators(const Expr *Ex) {
   while (Ex) {
     const BinaryOperator *BO =
       dyn_cast<BinaryOperator>(Ex->IgnoreParenCasts());
@@ -111,6 +112,10 @@ static const Expr *LookThroughTransitiveAssignments(const Expr *Ex) {
       Ex = BO->getRHS();
       continue;
     }
+    if (BO->getOpcode() == BO_Comma) {
+      Ex = BO->getRHS();
+      continue;
+    }
     break;
   }
   return Ex;
@@ -266,7 +271,9 @@ 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());
+          const Expr *RHS =
+            LookThroughTransitiveAssignmentsAndCommaOperators(B->getRHS());
+          RHS = RHS->IgnoreParenCasts();
           
           QualType T = VD->getType();
           if (T->isPointerType() || T->isObjCObjectPointerType()) {
@@ -274,7 +281,6 @@ public:
               return;
           }
 
-          RHS = RHS->IgnoreParenCasts();
           // Special case: self-assignments.  These are often used to shut up
           //  "unused variable" compiler warnings.
           if (const DeclRefExpr *RhsDR = dyn_cast<DeclRefExpr>(RHS))
@@ -326,7 +332,7 @@ public:
             
             // Look through transitive assignments, e.g.:
             // int x = y = 0;
-            E = LookThroughTransitiveAssignments(E);
+            E = LookThroughTransitiveAssignmentsAndCommaOperators(E);
             
             // Don't warn on C++ objects (yet) until we can show that their
             // constructors/destructors don't have side effects.
index 165a12b59b1fa4cece04d412adfcf7a6fe31dcd1..067a0504f13d8ae199caa32710cc61ab4b447742 100644 (file)
@@ -547,3 +547,25 @@ int *radar11185138_baz() {
   return y;
 }
 
+int getInt();
+int *getPtr();
+void testBOComma() {
+  int x0 = (getInt(), 0); // expected-warning{{unused variable 'x0'}}
+  int x1 = (getInt(), getInt()); // expected-warning {{Value stored to 'x1' during its initialization is never read}} // expected-warning{{unused variable 'x1'}}
+  int x2 = (getInt(), getInt(), getInt()); //expected-warning{{Value stored to 'x2' during its initialization is never read}} // expected-warning{{unused variable 'x2'}}
+  int x3;
+  x3 = (getInt(), getInt(), 0); // expected-warning{{Value stored to 'x3' is never read}}
+  int x4 = (getInt(), (getInt(), 0)); // expected-warning{{unused variable 'x4'}}
+  int y;
+  int x5 = (getInt(), (y = 0)); // expected-warning{{unused variable 'x5'}}
+  int x6 = (getInt(), (y = getInt())); //expected-warning {{Value stored to 'x6' during its initialization is never read}} // expected-warning{{unused variable 'x6'}}
+  int x7 = 0, x8 = getInt(); //expected-warning {{Value stored to 'x8' during its initialization is never read}} // expected-warning{{unused variable 'x8'}} // expected-warning{{unused variable 'x7'}}
+  int x9 = getInt(), x10 = 0; //expected-warning {{Value stored to 'x9' during its initialization is never read}} // expected-warning{{unused variable 'x9'}}  // expected-warning{{unused variable 'x10'}}
+  int m = getInt(), mm, mmm; //expected-warning {{Value stored to 'm' during its initialization is never read}} // expected-warning{{unused variable 'm'}} // expected-warning{{unused variable 'mm'}} // expected-warning{{unused variable 'mmm'}}
+  int n, nn = getInt(); //expected-warning {{Value stored to 'nn' during its initialization is never read}} // expected-warning{{unused variable 'n'}} // expected-warning{{unused variable 'nn'}}
+
+  int *p;
+  p = (getPtr(), (int *)0); // no warning
+
+}
+