diff options
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 27 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ProgramState.cpp | 6 | ||||
-rw-r--r-- | test/Analysis/inlining/false-positive-suppression.c | 5 |
3 files changed, 26 insertions, 12 deletions
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 5f364304e8..7f71b8e81e 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -800,14 +800,22 @@ static const Expr *peelOffOuterExpr(const Stmt *S, // Peel off the ternary operator. if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) { - ProgramStateRef State = N->getState(); - SVal CondVal = State->getSVal(CO->getCond(), N->getLocationContext()); - if (State->isNull(CondVal).isConstrainedTrue()) { - return CO->getTrueExpr(); - } else { - assert(State->isNull(CondVal).isConstrainedFalse()); - return CO->getFalseExpr(); - } + const Expr *CondEx = CO->getCond(); + + // Find a node where the value of the condition is known. + do { + ProgramStateRef State = N->getState(); + SVal CondVal = State->getSVal(CondEx, N->getLocationContext()); + ConditionTruthVal CondEvaluated = State->isNull(CondVal); + if (CondEvaluated.isConstrained()) { + if (CondEvaluated.isConstrainedTrue()) + return CO->getFalseExpr(); + else + return CO->getTrueExpr(); + } + N = N->getFirstPred(); + } while (N); + } } return 0; @@ -820,9 +828,8 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, if (!S || !N) return false; - if (const Expr *Ex = peelOffOuterExpr(S, N)) { + if (const Expr *Ex = peelOffOuterExpr(S, N)) S = Ex; - } const Expr *Inner = 0; if (const Expr *Ex = dyn_cast<Expr>(S)) { diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp index f3e80f19c9..bff2242925 100644 --- a/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -380,9 +380,13 @@ ConditionTruthVal ProgramState::isNull(SVal V) const { if (V.isZeroConstant()) return true; + if (V.isConstant()) + return false; + SymbolRef Sym = V.getAsSymbol(); if (!Sym) - return false; + return ConditionTruthVal(); + return getStateManager().ConstraintMgr->isNull(this, Sym); } diff --git a/test/Analysis/inlining/false-positive-suppression.c b/test/Analysis/inlining/false-positive-suppression.c index 31ad891762..e12612d8c4 100644 --- a/test/Analysis/inlining/false-positive-suppression.c +++ b/test/Analysis/inlining/false-positive-suppression.c @@ -9,6 +9,8 @@ int *getNull() { return 0; } +int* getPtr(); + int *dynCastToInt(void *ptr) { if (opaquePropertyCheck(ptr)) return (int *)ptr; @@ -219,9 +221,10 @@ int derefAssignment(int *p) { // expected-warning@-2 {{Dereference of null pointer}} #endif } + void ternaryAssignment(char cond) { static int x; - int *p = cond ? &x : getNull(); + int *p = cond ? getNull() : getPtr(); derefAssignment(p); } |