summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2013-12-06 18:56:29 +0000
committerAnna Zaks <ganna@apple.com>2013-12-06 18:56:29 +0000
commitcf8d2165ffebd254927463af7d86f61d8bbd3fd2 (patch)
treecd59cde242b50c800597e0d404729d22141ed601 /clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
parentba0aea16e1902cf39d32e2617b88582519e31a28 (diff)
downloadbcm5719-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.cpp98
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));
}
OpenPOWER on IntegriCloud