aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/ExprEngineC.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2013-04-15 22:38:07 +0000
committerAnna Zaks <ganna@apple.com>2013-04-15 22:38:07 +0000
commitd8eeac5bd5e3cca0b3ff3993ee479ec9e66f386e (patch)
tree218843daada9e61fa6d7b0d897919a715dbadbcc /lib/StaticAnalyzer/Core/ExprEngineC.cpp
parent07d8470effc0b0364801adddb6ff92bd22334402 (diff)
[analyzer] Do not crash when processing binary "?:" in C++
When computing the value of ?: expression, we rely on the last expression in the previous basic block to be the resulting value of the expression. This is not the case for binary "?:" operator (GNU extension) in C++. As the last basic block has the expression for the condition subexpression, which is an R-value, whereas the true subexpression is the L-value. Note the operator evaluation just happens to work in C since the true subexpression is an R-value (like the condition subexpression). CFG is the same in C and C++ case, but the AST nodes are different, which the LValue to Rvalue conversion happening after the BinaryConditionalOperator evaluation. Changed the logic to only use the last expression from the predecessor only if it matches either true or false subexpression. Note, the logic needed fortification anyway: L and R were passed but not even used by the function. Also, change the conjureSymbolVal to correctly compute the type, when the expression is an LG-value. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179574 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngineC.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineC.cpp24
1 files changed, 20 insertions, 4 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 7a53fccf2e..2d52c01e1d 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -617,11 +617,15 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
const Expr *R,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
+ assert(L && R);
+
StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
const CFGBlock *SrcBlock = 0;
+ // Find the predecessor block.
+ ProgramStateRef SrcState = state;
for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()) {
ProgramPoint PP = N->getLocation();
if (PP.getAs<PreStmtPurgeDeadSymbols>() || PP.getAs<BlockEntrance>()) {
@@ -629,6 +633,7 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
continue;
}
SrcBlock = PP.castAs<BlockEdge>().getSrc();
+ SrcState = N->getState();
break;
}
@@ -644,14 +649,25 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
CFGElement CE = *I;
if (Optional<CFGStmt> CS = CE.getAs<CFGStmt>()) {
const Expr *ValEx = cast<Expr>(CS->getStmt());
- hasValue = true;
- V = state->getSVal(ValEx, LCtx);
+ ValEx = ValEx->IgnoreParens();
+
+ // For GNU extension '?:' operator, the left hand side will be an
+ // OpaqueValueExpr, so get the underlying expression.
+ if (const OpaqueValueExpr *OpaqueEx = dyn_cast<OpaqueValueExpr>(L))
+ L = OpaqueEx->getSourceExpr();
+
+ // If the last expression in the predecessor block matches true or false
+ // subexpression, get its the value.
+ if (ValEx == L->IgnoreParens() || ValEx == R->IgnoreParens()) {
+ hasValue = true;
+ V = SrcState->getSVal(ValEx, LCtx);
+ }
break;
}
}
- assert(hasValue);
- (void) hasValue;
+ if (!hasValue)
+ V = svalBuilder.conjureSymbolVal(0, Ex, LCtx, currBldrCtx->blockCount());
// Generate a new node with the binding from the appropriate path.
B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true));