diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-12-23 04:49:01 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-12-23 04:49:01 +0000 |
commit | 61dfbecd8e6181b2ba42ffb5feede27a2bab3b8a (patch) | |
tree | a83619142539ddc193d8c11d617283007b618abc | |
parent | 604d939ac15d1398761df313679673d30bb10f27 (diff) |
Add CFG support for the condition variable that can appear in IfStmts in C++ mode.
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
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRExprEngine.h | 5 | ||||
-rw-r--r-- | lib/Analysis/CFG.cpp | 14 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 37 | ||||
-rw-r--r-- | test/Analysis/misc-ps-region-store.cpp | 7 |
4 files changed, 62 insertions, 1 deletions
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 647c1226f0..6aa4be3456 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -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); diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 884188acd7..8f2a5719f6 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -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; } diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 22becee289..ceefea81f5 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -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. diff --git a/test/Analysis/misc-ps-region-store.cpp b/test/Analysis/misc-ps-region-store.cpp index be150c92cc..7b911a5c82 100644 --- a/test/Analysis/misc-ps-region-store.cpp +++ b/test/Analysis/misc-ps-region-store.cpp @@ -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; +} |