[cfe-commits] r160819 - in /cfe/trunk: lib/StaticAnalyzer/Core/ExprEngineC.cpp test/Analysis/misc-ps.m

Ted Kremenek kremenek at apple.com
Thu Jul 26 15:23:41 PDT 2012


Author: kremenek
Date: Thu Jul 26 17:23:41 2012
New Revision: 160819

URL: http://llvm.org/viewvc/llvm-project?rev=160819&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
    cfe/trunk/test/Analysis/misc-ps.m

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=160819&r1=160818&r2=160819&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Thu Jul 26 17:23:41 2012
@@ -593,22 +593,36 @@
   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));

Modified: cfe/trunk/test/Analysis/misc-ps.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps.m?rev=160819&r1=160818&r2=160819&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/misc-ps.m (original)
+++ cfe/trunk/test/Analysis/misc-ps.m Thu Jul 26 17:23:41 2012
@@ -1356,3 +1356,21 @@
 }
 @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;
+}
+
+





More information about the cfe-commits mailing list