]> granicus.if.org Git - clang/commitdiff
Add CFG support for the condition variable that can appear in IfStmts in C++ mode.
authorTed Kremenek <kremenek@apple.com>
Wed, 23 Dec 2009 04:49:01 +0000 (04:49 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 23 Dec 2009 04:49:01 +0000 (04:49 +0000)
Add transfer function support in GRExprEngine for IfStmts with initialized condition variables.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91987 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/PathSensitive/GRExprEngine.h
lib/Analysis/CFG.cpp
lib/Analysis/GRExprEngine.cpp
test/Analysis/misc-ps-region-store.cpp

index 647c1226f0d5133f6f2d32632bb2dec113ef80ae..6aa4be345688787baa468e017c1fe77e701bb963 100644 (file)
@@ -293,6 +293,11 @@ protected:
   void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred,
                         ExplodedNodeSet& Dst);
 
+  /// VisitIfStmtCondInit - Transfer function for handling the initialization
+  ///  of a condition variable in an IfStmt.
+  void VisitIfStmtCondInit(IfStmt *IS, ExplodedNode *Pred,
+                           ExplodedNodeSet& Dst);
+  
   void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
                          ExplodedNodeSet& Dst);
 
index 884188acd78a5a2b16d05cfa188b45bc0fd28434..8f2a5719f68ba1d3613f452dfc4191bd4fb4fe2a 100644 (file)
@@ -776,7 +776,19 @@ CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) {
   // Add the condition as the last statement in the new block.  This may create
   // new blocks as the condition may contain control-flow.  Any newly created
   // blocks will be pointed to be "Block".
-  return addStmt(I->getCond());
+  Block = addStmt(I->getCond());
+  
+  // Finally, if the IfStmt contains a condition variable, add both the IfStmt
+  // and the condition variable initialization to the CFG.
+  if (VarDecl *VD = I->getConditionVariable()) {
+    if (Expr *Init = VD->getInit()) {
+      autoCreateBlock();
+      AppendStmt(Block, I, AddStmtChoice::AlwaysAdd);
+      addStmt(Init);
+    }
+  }
+  
+  return Block;
 }
 
 
index 22becee2892ce7c3fb57636be7850fcadf65660c..ceefea81f5c10b923f509401538ce6e6c04ebaab 100644 (file)
@@ -661,6 +661,12 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
       VisitCast(C, C->getSubExpr(), Pred, Dst, false);
       break;
     }
+      
+    case Stmt::IfStmtClass:
+      // This case isn't for branch processing, but for handling the
+      // initialization of a condition variable.
+      VisitIfStmtCondInit(cast<IfStmt>(S), Pred, Dst);
+      break;
 
     case Stmt::InitListExprClass:
       VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
@@ -749,6 +755,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
                                 Ex->getLocStart(),
                                 "Error evaluating statement");
 
+
   Ex = Ex->IgnoreParens();
 
   if (Ex != CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(Ex)){
@@ -2223,6 +2230,36 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
   }
 }
 
+void GRExprEngine::VisitIfStmtCondInit(IfStmt *IS, ExplodedNode *Pred,
+                                       ExplodedNodeSet& Dst) {
+  
+  VarDecl* VD = IS->getConditionVariable();
+  Expr* InitEx = VD->getInit();
+  
+  ExplodedNodeSet Tmp;
+  Visit(InitEx, Pred, Tmp);
+
+  for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+    ExplodedNode *N = *I;
+    const GRState *state = GetState(N);
+    
+    const LocationContext *LC = N->getLocationContext();
+    SVal InitVal = state->getSVal(InitEx);
+    QualType T = VD->getType();
+      
+    // Recover some path-sensitivity if a scalar value evaluated to
+    // UnknownVal.
+    if (InitVal.isUnknown() ||
+        !getConstraintManager().canReasonAbout(InitVal)) {
+      InitVal = ValMgr.getConjuredSymbolVal(NULL, InitEx, 
+                                            Builder->getCurrentBlockCount());
+    }
+      
+    EvalBind(Dst, IS, IS, N, state,
+             loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
+  }
+}
+
 namespace {
   // This class is used by VisitInitListExpr as an item in a worklist
   // for processing the values contained in an InitListExpr.
index be150c92cc346f4688e60aecb3c0f6bef1f6a5ac..7b911a5c82dece76877f80d0b7bd73033f1f2740 100644 (file)
@@ -34,3 +34,10 @@ int test3(Test3_Derived x) {
   return test3_aux(x);
 }
 
+int test_init_in_condition_aux();
+int test_init_in_condition() {
+  if (int x = test_init_in_condition_aux()) { // no-warning
+    return 1;
+  }
+  return 0;
+}