]> granicus.if.org Git - clang/commitdiff
Improve the diagnostics for the UndefinedAssignmentChecker when an
authorTed Kremenek <kremenek@apple.com>
Mon, 22 Mar 2010 22:16:26 +0000 (22:16 +0000)
committerTed Kremenek <kremenek@apple.com>
Mon, 22 Mar 2010 22:16:26 +0000 (22:16 +0000)
uninitialized value is used in the LHS of a compound assignment.

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

lib/Checker/UndefinedAssignmentChecker.cpp
test/Analysis/uninit-vals-ps-region.m

index 7c33c1d3923571a483000cab970e77e84cbeb77d..9f17ef126da32dac10e4c8f83d16f65bb23e6d38 100644 (file)
@@ -53,27 +53,43 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
   if (!N)
     return;
 
+  const char *str = "Assigned value is garbage or undefined";
+
   if (!BT)
-    BT = new BuiltinBug("Assigned value is garbage or undefined");
+    BT = new BuiltinBug(str);
 
   // Generate a report for this bug.
-  EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName(), N);
+  const Expr *ex = 0;
 
-  if (AssignE) {
-    const Expr *ex = 0;
+  while (AssignE) {
+    if (const BinaryOperator *B = dyn_cast<BinaryOperator>(AssignE)) {
+      if (B->isCompoundAssignmentOp()) {
+        const GRState *state = C.getState();
+        if (state->getSVal(B->getLHS()).isUndef()) {
+          str = "The left expression of the compound assignment is an "
+                "uninitialized value. The computed value will also be garbage";
+          ex = B->getLHS();
+          break;
+        }
+      }
 
-    if (const BinaryOperator *B = dyn_cast<BinaryOperator>(AssignE))
       ex = B->getRHS();
-    else if (const DeclStmt *DS = dyn_cast<DeclStmt>(AssignE)) {
+      break;
+    }
+
+    if (const DeclStmt *DS = dyn_cast<DeclStmt>(AssignE)) {
       const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl());
       ex = VD->getInit();
     }
-    if (ex) {
-      R->addRange(ex->getSourceRange());
-      R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex);
-    }
+
+    break;
   }
 
+  EnhancedBugReport *R = new EnhancedBugReport(*BT, str, N);
+  if (ex) {
+    R->addRange(ex->getSourceRange());
+    R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex);
+  }
   C.EmitReport(R);
-}  
+}
 
index 7e2fff9db53010bc032e0a512d252f03a38f2382..69c1ecd1e3a65953950e0af910d8f73c64349570 100644 (file)
@@ -59,4 +59,11 @@ void testFoo(Foo *o) {
   [o passVal:x]; // expected-warning{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}
 }
 
+// Test case from <rdar://problem/7780304>.  That shows an uninitialized value
+// being used in the LHS of a compound assignment.
+void rdar_7780304() {
+  typedef struct s_r7780304 { int x; } s_r7780304;
+  s_r7780304 b;
+  b.x |= 1; // expected-warning{{The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage}}
+}