diff options
| author | Ted Kremenek <kremenek@apple.com> | 2010-03-22 22:16:26 +0000 | 
|---|---|---|
| committer | Ted Kremenek <kremenek@apple.com> | 2010-03-22 22:16:26 +0000 | 
| commit | 28ec56d7ddf1ed2caa56bc7e8650f0defccb684a (patch) | |
| tree | b46b3952a96add917259529e49c77428c60dbb44 | |
| parent | fdc7ccc4e482b99064034345b299fd322f9961fd (diff) | |
| download | bcm5719-llvm-28ec56d7ddf1ed2caa56bc7e8650f0defccb684a.tar.gz bcm5719-llvm-28ec56d7ddf1ed2caa56bc7e8650f0defccb684a.zip  | |
Improve the diagnostics for the UndefinedAssignmentChecker when an
uninitialized value is used in the LHS of a compound assignment.
llvm-svn: 99221
| -rw-r--r-- | clang/lib/Checker/UndefinedAssignmentChecker.cpp | 38 | ||||
| -rw-r--r-- | clang/test/Analysis/uninit-vals-ps-region.m | 7 | 
2 files changed, 34 insertions, 11 deletions
diff --git a/clang/lib/Checker/UndefinedAssignmentChecker.cpp b/clang/lib/Checker/UndefinedAssignmentChecker.cpp index 7c33c1d3923..9f17ef126da 100644 --- a/clang/lib/Checker/UndefinedAssignmentChecker.cpp +++ b/clang/lib/Checker/UndefinedAssignmentChecker.cpp @@ -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); -}   +} diff --git a/clang/test/Analysis/uninit-vals-ps-region.m b/clang/test/Analysis/uninit-vals-ps-region.m index 7e2fff9db53..69c1ecd1e3a 100644 --- a/clang/test/Analysis/uninit-vals-ps-region.m +++ b/clang/test/Analysis/uninit-vals-ps-region.m @@ -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}} +}  | 

