diff options
author | Ted Kremenek <kremenek@apple.com> | 2012-07-26 22:23:41 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2012-07-26 22:23:41 +0000 |
commit | 6da60499eae46caf9f92f7ba35c607043dc3f7fa (patch) | |
tree | c6b2c108dcae73481e723afd54651f968a13f2da | |
parent | 7c99aa385178c630e29f671299cdd9c104f1c885 (diff) |
Look at the preceding CFGBlock for the expression to load from in ExprEngine::VisitGuardedExpr
instead of walking to the preceding PostStmt node. There are cases where the last evaluated
expression does not appear in the ExplodedGraph.
Fixes PR 13466.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160819 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineC.cpp | 36 | ||||
-rw-r--r-- | test/Analysis/misc-ps.m | 18 |
2 files changed, 43 insertions, 11 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp index fd467c2b7a..7ec151ef6d 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -593,22 +593,36 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex, StmtNodeBuilder B(Pred, Dst, *currentBuilderContext); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); + const CFGBlock *SrcBlock = 0; - // Assume that the last CFGElement visited is the value of - // the guarded expression. - ExplodedNode *N = Pred; + for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()) { + ProgramPoint PP = N->getLocation(); + if (isa<PreStmtPurgeDeadSymbols>(PP) || isa<BlockEntrance>(PP)) { + assert(N->pred_size() == 1); + continue; + } + SrcBlock = cast<BlockEdge>(&PP)->getSrc(); + break; + } + + // Find the last expression in the predecessor block. That is the + // expression that is used for the value of the ternary expression. + bool hasValue = false; 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); + + for (CFGBlock::const_reverse_iterator I = SrcBlock->rbegin(), + E = SrcBlock->rend(); I != E; ++I) { + CFGElement CE = *I; + if (CFGStmt *CS = dyn_cast<CFGStmt>(&CE)) { + const Expr *ValEx = cast<Expr>(CS->getStmt()); + hasValue = true; + V = state->getSVal(ValEx, LCtx); break; } - assert(N->pred_size() == 1); - N = *N->pred_begin(); } - assert(N); + + assert(hasValue); + (void) hasValue; // Generate a new node with the binding from the appropriate path. B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true)); diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index c22837e4e6..edc1e1f94d 100644 --- a/test/Analysis/misc-ps.m +++ b/test/Analysis/misc-ps.m @@ -1356,3 +1356,21 @@ void radar9414427() { } @end +// Don't crash when a ?: is only preceded by a statement (not an expression) +// in the CFG. +void __assert_fail(); + +enum rdar1196620_e { E_A, E_B, E_C, E_D }; +struct rdar1196620_s { int ints[E_D+1]; }; + +static int rdar1196620_call_assert(struct rdar1196620_s* s) { + int i = 0; + s?(void)0:__assert_fail(); +} + +static void rdar1196620(struct rdar1196620_s* s) { + if (rdar1196620_call_assert(s)) + return; +} + + |