From: Ted Kremenek Date: Wed, 4 Nov 2009 00:09:15 +0000 (+0000) Subject: Refactor StoreManager::BindDecl() to take a VarRegion* instead of a VarDecl*, and... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f6f56d4fc8ebce17e7b83eb2c35f57a055c22283;p=clang Refactor StoreManager::BindDecl() to take a VarRegion* instead of a VarDecl*, and modify GRExprEngine::EvalBind() to handle decl initialization as well. This paves the way for adding "checker" visitation in EvalBind(). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85983 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index cfb9ce95ea..1d2b08711c 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -562,8 +562,9 @@ protected: /// EvalBind - Handle the semantics of binding a value to a specific location. /// This method is used by EvalStore, VisitDeclStmt, and others. - void EvalBind(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, - const GRState* St, SVal location, SVal Val); + void EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred, + const GRState* St, SVal location, SVal Val, + bool atDeclInit = false); public: void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index 3f6fb8e242..8678ca9b5b 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -219,11 +219,9 @@ public: const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const; - const GRState *bindDecl(const VarDecl *VD, const LocationContext *LC, - SVal V) const; + const GRState *bindDecl(const VarRegion *VR, SVal V) const; - const GRState *bindDeclWithNoInit(const VarDecl *VD, - const LocationContext *LC) const; + const GRState *bindDeclWithNoInit(const VarRegion *VR) const; const GRState *bindLoc(Loc location, SVal V) const; @@ -602,15 +600,12 @@ inline const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, V); } -inline const GRState *GRState::bindDecl(const VarDecl* VD, - const LocationContext *LC, - SVal IVal) const { - return getStateManager().StoreMgr->BindDecl(this, VD, LC, IVal); +inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const { + return getStateManager().StoreMgr->BindDecl(this, VR, IVal); } -inline const GRState *GRState::bindDeclWithNoInit(const VarDecl* VD, - const LocationContext *LC) const { - return getStateManager().StoreMgr->BindDeclWithNoInit(this, VD, LC); +inline const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const { + return getStateManager().StoreMgr->BindDeclWithNoInit(this, VR); } inline const GRState *GRState::bindLoc(Loc LV, SVal V) const { diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index 7a462c579f..6ca2e9e9aa 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -134,12 +134,11 @@ public: SymbolReaper& SymReaper, llvm::SmallVectorImpl& RegionRoots) = 0; - virtual const GRState *BindDecl(const GRState *ST, const VarDecl *VD, - const LocationContext *LC, SVal initVal) = 0; + virtual const GRState *BindDecl(const GRState *ST, const VarRegion *VR, + SVal initVal) = 0; virtual const GRState *BindDeclWithNoInit(const GRState *ST, - const VarDecl *VD, - const LocationContext *LC) = 0; + const VarRegion *VR) = 0; typedef llvm::DenseSet InvalidatedSymbols; diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp index d81d83c7bf..888af9bd57 100644 --- a/lib/Analysis/BasicStore.cpp +++ b/lib/Analysis/BasicStore.cpp @@ -92,19 +92,17 @@ public: void iterBindings(Store store, BindingsHandler& f); - const GRState *BindDecl(const GRState *state, const VarDecl *VD, - const LocationContext *LC, SVal InitVal) { - return state->makeWithStore(BindDeclInternal(state->getStore(),VD, LC, + const GRState *BindDecl(const GRState *state, const VarRegion *VR, + SVal InitVal) { + return state->makeWithStore(BindDeclInternal(state->getStore(), VR, &InitVal)); } - const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl *VD, - const LocationContext *LC) { - return state->makeWithStore(BindDeclInternal(state->getStore(), VD, LC, 0)); + const GRState *BindDeclWithNoInit(const GRState *state, const VarRegion *VR) { + return state->makeWithStore(BindDeclInternal(state->getStore(), VR, 0)); } - Store BindDeclInternal(Store store, const VarDecl *VD, - const LocationContext *LC, SVal *InitVal); + Store BindDeclInternal(Store store, const VarRegion *VR, SVal *InitVal); static inline BindingsTy GetBindings(Store store) { return BindingsTy(static_cast(store)); @@ -532,11 +530,11 @@ Store BasicStoreManager::getInitialStore(const LocationContext *InitLoc) { return St; } -Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD, - const LocationContext *LC, +Store BasicStoreManager::BindDeclInternal(Store store, const VarRegion* VR, SVal* InitVal) { BasicValueFactory& BasicVals = StateMgr.getBasicVals(); + const VarDecl *VD = VR->getDecl(); // BasicStore does not model arrays and structs. if (VD->getType()->isArrayType() || VD->getType()->isStructureType()) @@ -564,16 +562,16 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD, if (!InitVal) { QualType T = VD->getType(); if (Loc::IsLocType(T)) - store = BindInternal(store, getLoc(VD, LC), + store = BindInternal(store, loc::MemRegionVal(VR), loc::ConcreteInt(BasicVals.getValue(0, T))); else if (T->isIntegerType()) - store = BindInternal(store, getLoc(VD, LC), + store = BindInternal(store, loc::MemRegionVal(VR), nonloc::ConcreteInt(BasicVals.getValue(0, T))); else { // assert(0 && "ignore other types of variables"); } } else { - store = BindInternal(store, getLoc(VD, LC), *InitVal); + store = BindInternal(store, loc::MemRegionVal(VR), *InitVal); } } } else { @@ -581,7 +579,7 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD, QualType T = VD->getType(); if (ValMgr.getSymbolManager().canSymbolicate(T)) { SVal V = InitVal ? *InitVal : UndefinedVal(); - store = BindInternal(store, getLoc(VD, LC), V); + store = BindInternal(store, loc::MemRegionVal(VR), V); } } diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 4c538c8dc8..bf1f6ab1e3 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1090,21 +1090,30 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, /// EvalBind - Handle the semantics of binding a value to a specific location. /// This method is used by EvalStore and (soon) VisitDeclStmt, and others. -void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, - const GRState* state, SVal location, SVal Val) { +void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred, + const GRState* state, SVal location, SVal Val, + bool atDeclInit) { const GRState* newState = 0; - if (location.isUnknown()) { - // We know that the new state will be the same as the old state since - // the location of the binding is "unknown". Consequently, there - // is no reason to just create a new node. - newState = state; + if (atDeclInit) { + const VarRegion *VR = + cast(cast(location).getRegion()); + + newState = state->bindDecl(VR, Val); } else { - // We are binding to a value other than 'unknown'. Perform the binding - // using the StoreManager. - newState = state->bindLoc(cast(location), Val); + if (location.isUnknown()) { + // We know that the new state will be the same as the old state since + // the location of the binding is "unknown". Consequently, there + // is no reason to just create a new node. + newState = state; + } + else { + // We are binding to a value other than 'unknown'. Perform the binding + // using the StoreManager. + newState = state->bindLoc(cast(location), Val); + } } // The next thing to do is check if the GRTransferFuncs object wants to @@ -2089,18 +2098,12 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred, InitVal = ValMgr.getConjuredSymbolVal(NULL, InitEx, Builder->getCurrentBlockCount()); } - - state = state->bindDecl(VD, LC, InitVal); - - // The next thing to do is check if the GRTransferFuncs object wants to - // update the state based on the new binding. If the GRTransferFunc - // object doesn't do anything, just auto-propagate the current state. - GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, state, DS,true); - getTF().EvalBind(BuilderRef, loc::MemRegionVal(state->getRegion(VD, LC)), - InitVal); + + EvalBind(Dst, DS, *I, state, loc::MemRegionVal(state->getRegion(VD, LC)), + InitVal, true); } else { - state = state->bindDeclWithNoInit(VD, LC); + state = state->bindDeclWithNoInit(state->getRegion(VD, LC)); MakeNode(Dst, DS, *I, state); } } diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp index 5cfe4c0410..dbf8c42d27 100644 --- a/lib/Analysis/RegionStore.cpp +++ b/lib/Analysis/RegionStore.cpp @@ -275,11 +275,11 @@ public: const GRState *BindCompoundLiteral(const GRState *state, const CompoundLiteralExpr* CL, SVal V); - const GRState *BindDecl(const GRState *ST, const VarDecl *VD, - const LocationContext *LC, SVal InitVal); + const GRState *BindDecl(const GRState *ST, const VarRegion *VR, + SVal InitVal); - const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl*, - const LocationContext *) { + const GRState *BindDeclWithNoInit(const GRState *state, + const VarRegion *) { return state; } @@ -1409,12 +1409,10 @@ const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) { } const GRState *RegionStoreManager::BindDecl(const GRState *ST, - const VarDecl *VD, - const LocationContext *LC, + const VarRegion *VR, SVal InitVal) { - QualType T = VD->getType(); - VarRegion* VR = MRMgr.getVarRegion(VD, LC); + QualType T = VR->getDecl()->getType(); if (T->isArrayType()) return BindArray(ST, VR, InitVal);