aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2012-07-25 21:58:25 +0000
committerTed Kremenek <kremenek@apple.com>2012-07-25 21:58:25 +0000
commit469841a8e0967f038aa0f78e1926ce82e06248c7 (patch)
tree30f4a062041338d399dd6b82fbe443f2ab2be7e2
parent2ca5af239af48ed5c6af62ae03cd39c246af06db (diff)
Update ExprEngine's handling of ternary operators to find the ternary expression
value by scanning the path, rather than assuming we have visited the '?:' operator as a terminator (which sets a value indicating which expression to grab the final ternary expression value from). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160760 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineC.cpp28
-rw-r--r--test/Analysis/misc-ps.c7
2 files changed, 26 insertions, 9 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 0254b756ee..4bcc0fbd10 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -590,17 +590,27 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
StmtNodeBuilder B(Pred, Dst, *currentBuilderContext);
-
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
- SVal X = state->getSVal(Ex, LCtx);
- assert (X.isUndef());
- const Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
- assert(SE);
- X = state->getSVal(SE, LCtx);
-
- // Make sure that we invalidate the previous binding.
- B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, X, true));
+
+ // Assume that the last CFGElement visited is the value of
+ // the guarded expression.
+ ExplodedNode *N = Pred;
+ SVal V;
+ while (N) {
+ ProgramPoint P = N->getLocation();
+ if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) {
+ const Expr *Ex = cast<Expr>(PS->getStmt());
+ V = state->getSVal(Ex, LCtx);
+ break;
+ }
+ assert(N->pred_size() == 1);
+ N = *N->pred_begin();
+ }
+ assert(N);
+
+ // Generate a new node with the binding from the appropriate path.
+ B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true));
}
void ExprEngine::
diff --git a/test/Analysis/misc-ps.c b/test/Analysis/misc-ps.c
index f81b0ddc68..8ff710b12f 100644
--- a/test/Analysis/misc-ps.c
+++ b/test/Analysis/misc-ps.c
@@ -126,3 +126,10 @@ void rdar10686586() {
}
}
+// This example tests CFG handling of '||' nested in a ternary expression,
+// and seeing that the analyzer doesn't crash.
+int isctype(char c, unsigned long f)
+{
+ return (c < 1 || c > 10) ? 0 : !!(c & f);
+}
+