diff options
author | Anna Zaks <ganna@apple.com> | 2013-12-06 18:56:29 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2013-12-06 18:56:29 +0000 |
commit | cf8d2165ffebd254927463af7d86f61d8bbd3fd2 (patch) | |
tree | cd59cde242b50c800597e0d404729d22141ed601 /clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | |
parent | ba0aea16e1902cf39d32e2617b88582519e31a28 (diff) | |
download | bcm5719-llvm-cf8d2165ffebd254927463af7d86f61d8bbd3fd2.tar.gz bcm5719-llvm-cf8d2165ffebd254927463af7d86f61d8bbd3fd2.zip |
Revert "[analyzer] Refactor conditional expression evaluating code"
This reverts commit r189090.
The original patch introduced regressions (see the added live-variables.* tests). The patch depends on the correctness of live variable analyses, which are not computed correctly. I've opened PR18159 to track the proper resolution to this problem.
The patch was a stepping block to r189746. This is why part of the patch reverts temporary destructor tests that started crashing. The temporary destructors feature is disabled by default.
llvm-svn: 196593
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 98 |
1 files changed, 55 insertions, 43 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 297754d6086..983fda00a2f 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -505,33 +505,6 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, getCheckerManager().runCheckersForPostStmt(Dst, B.getResults(), DS, *this); } -static ProgramStateRef evaluateLogicalExpression(const Expr *E, - const LocationContext *LC, - ProgramStateRef State) { - SVal X = State->getSVal(E, LC); - if (! X.isUnknown()) - return State; - - const BinaryOperator *B = dyn_cast<BinaryOperator>(E->IgnoreParens()); - if (!B || (B->getOpcode() != BO_LAnd && B->getOpcode() != BO_LOr)) - return State; - - State = evaluateLogicalExpression(B->getLHS(), LC, State); - X = State->getSVal(B->getLHS(), LC); - QualType XType = B->getLHS()->getType(); - - assert(X.isConstant()); - if (!X.isZeroConstant() == (B->getOpcode() == BO_LAnd)) { - // LHS not sufficient, we need to check RHS as well - State = evaluateLogicalExpression(B->getRHS(), LC, State); - X = State->getSVal(B->getRHS(), LC); - XType = B->getRHS()->getType(); - } - - SValBuilder &SVB = State->getStateManager().getSValBuilder(); - return State->BindExpr(E, LC, SVB.evalCast(X, B->getType(), XType)); -} - void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, ExplodedNodeSet &Dst) { assert(B->getOpcode() == BO_LAnd || @@ -540,25 +513,64 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); ProgramStateRef state = Pred->getState(); - state = evaluateLogicalExpression(B, Pred->getLocationContext(), state); - SVal X = state->getSVal(B, Pred->getLocationContext()); - - if (!X.isUndef()) { - DefinedOrUnknownSVal DefinedRHS = X.castAs<DefinedOrUnknownSVal>(); - ProgramStateRef StTrue, StFalse; - llvm::tie(StTrue, StFalse) = state->assume(DefinedRHS); - if (StTrue) { - if (!StFalse) { - // The value is known to be true. - X = getSValBuilder().makeIntVal(1, B->getType()); - } // else The truth value of X is unknown, just leave it as it is. + ExplodedNode *N = Pred; + while (!N->getLocation().getAs<BlockEntrance>()) { + ProgramPoint P = N->getLocation(); + assert(P.getAs<PreStmt>()|| P.getAs<PreStmtPurgeDeadSymbols>()); + (void) P; + assert(N->pred_size() == 1); + N = *N->pred_begin(); + } + assert(N->pred_size() == 1); + N = *N->pred_begin(); + BlockEdge BE = N->getLocation().castAs<BlockEdge>(); + SVal X; + + // Determine the value of the expression by introspecting how we + // got this location in the CFG. This requires looking at the previous + // block we were in and what kind of control-flow transfer was involved. + const CFGBlock *SrcBlock = BE.getSrc(); + // The only terminator (if there is one) that makes sense is a logical op. + CFGTerminator T = SrcBlock->getTerminator(); + if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(T.getStmt())) { + (void) Term; + assert(Term->isLogicalOp()); + assert(SrcBlock->succ_size() == 2); + // Did we take the true or false branch? + unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 1 : 0; + X = svalBuilder.makeIntVal(constant, B->getType()); + } + else { + // If there is no terminator, by construction the last statement + // in SrcBlock is the value of the enclosing expression. + // However, we still need to constrain that value to be 0 or 1. + assert(!SrcBlock->empty()); + CFGStmt Elem = SrcBlock->rbegin()->castAs<CFGStmt>(); + const Expr *RHS = cast<Expr>(Elem.getStmt()); + SVal RHSVal = N->getState()->getSVal(RHS, Pred->getLocationContext()); + + if (RHSVal.isUndef()) { + X = RHSVal; } else { - // The value is known to be false. - assert(StFalse && "Infeasible path!"); - X = getSValBuilder().makeIntVal(0, B->getType()); + DefinedOrUnknownSVal DefinedRHS = RHSVal.castAs<DefinedOrUnknownSVal>(); + ProgramStateRef StTrue, StFalse; + llvm::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS); + if (StTrue) { + if (StFalse) { + // We can't constrain the value to 0 or 1. + // The best we can do is a cast. + X = getSValBuilder().evalCast(RHSVal, B->getType(), RHS->getType()); + } else { + // The value is known to be true. + X = getSValBuilder().makeIntVal(1, B->getType()); + } + } else { + // The value is known to be false. + assert(StFalse && "Infeasible path!"); + X = getSValBuilder().makeIntVal(0, B->getType()); + } } } - Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X)); } |