diff options
author | Zhongxing Xu <xuzhongxing@gmail.com> | 2008-08-21 22:34:01 +0000 |
---|---|---|
committer | Zhongxing Xu <xuzhongxing@gmail.com> | 2008-08-21 22:34:01 +0000 |
commit | bbe8ff48be1728ef145c874d6d99879fac78892f (patch) | |
tree | 6956c27d2bc46d02f54b1362a0bccfb3d3c4d3c6 | |
parent | dbc933701d20918add13b6a3c9d47ff8c75419cf (diff) |
Move the handling of DeclStmt from GRExprEngine to BasicStoreManager.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55144 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRState.h | 5 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/Store.h | 6 | ||||
-rw-r--r-- | lib/Analysis/BasicStore.cpp | 69 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 71 | ||||
-rw-r--r-- | lib/Analysis/GRState.cpp | 18 |
5 files changed, 97 insertions, 72 deletions
diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index 584bf6edf9..d5eb55ab6d 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -310,7 +310,10 @@ public: LiveVariables& getLiveVariables() { return Liveness; } typedef StoreManager::DeadSymbolsTy DeadSymbolsTy; - + + const GRState* AddDecl(const GRState* St, const VarDecl* VD, Expr* Ex, + unsigned Count); + const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc, const LiveVariables& Liveness, DeadSymbolsTy& DeadSyms); diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index aa8dc234d4..a0a441c4ff 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -44,7 +44,11 @@ public: const LiveVariables& Live, DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) = 0; - + + virtual Store AddDecl(Store store, BasicValueFactory& BasicVals, + SymbolManager& SymMgr, const VarDecl* VD, Expr* Ex, + RVal InitVal = UndefinedVal(), unsigned Count = 0) = 0; + virtual void print(Store store, std::ostream& Out, const char* nl, const char *sep) = 0; }; diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp index 24ec7f0e38..ad0e12aa4c 100644 --- a/lib/Analysis/BasicStore.cpp +++ b/lib/Analysis/BasicStore.cpp @@ -40,7 +40,11 @@ public: const LiveVariables& Live, DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols); - + + virtual Store AddDecl(Store store, BasicValueFactory& BasicVals, + SymbolManager& SymMgr, const VarDecl* VD, Expr* Ex, + RVal InitVal = UndefinedVal(), unsigned Count = 0); + static inline VarBindingsTy GetVarBindings(Store store) { return VarBindingsTy(static_cast<const VarBindingsTy::TreeTy*>(store)); } @@ -239,6 +243,69 @@ Store BasicStoreManager::getInitialStore(GRStateManager& StateMgr) { return St; } +Store BasicStoreManager::AddDecl(Store store, BasicValueFactory& BasicVals, + SymbolManager& SymMgr, const VarDecl* VD, + Expr* Ex, RVal InitVal, unsigned Count) { + // BasicStore does not model arrays and structs. + if (VD->getType()->isArrayType() || VD->getType()->isStructureType()) + return store; + + if (VD->hasGlobalStorage()) { + // Handle variables with global storage: extern, static, PrivateExtern. + + // FIXME:: static variables may have an initializer, but the second time a + // function is called those values may not be current. Currently, a function + // will not be called more than once. + + // Static global variables should not be visited here. + assert(!(VD->getStorageClass() == VarDecl::Static && + VD->isFileVarDecl())); + + // Process static variables. + if (VD->getStorageClass() == VarDecl::Static) { + // C99: 6.7.8 Initialization + // If an object that has static storage duration is not initialized + // explicitly, then: + // —if it has pointer type, it is initialized to a null pointer; + // —if it has arithmetic type, it is initialized to (positive or + // unsigned) zero; + if (!Ex) { + QualType T = VD->getType(); + if (LVal::IsLValType(T)) + store = SetRVal(store, lval::DeclVal(VD), + lval::ConcreteInt(BasicVals.getValue(0, T))); + else if (T->isIntegerType()) + store = SetRVal(store, lval::DeclVal(VD), + nonlval::ConcreteInt(BasicVals.getValue(0, T))); + else { + // assert(0 && "ignore other types of variables"); + } + } else { + store = SetRVal(store, lval::DeclVal(VD), InitVal); + } + } + } else { + // Process local scalar variables. + QualType T = VD->getType(); + if (LVal::IsLValType(T) || T->isIntegerType()) { + RVal V = Ex ? InitVal : UndefinedVal(); + + if (Ex && InitVal.isUnknown()) { + // EXPERIMENTAL: "Conjured" symbols. + SymbolID Sym = SymMgr.getConjuredSymbol(Ex, Count); + + V = LVal::IsLValType(Ex->getType()) + ? cast<RVal>(lval::SymbolVal(Sym)) + : cast<RVal>(nonlval::SymbolVal(Sym)); + } + + store = SetRVal(store, lval::DeclVal(VD), V); + } + } + + return store; +} + void BasicStoreManager::print(Store store, std::ostream& Out, const char* nl, const char *sep) { diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 7433509c85..93ea5251e8 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1484,76 +1484,9 @@ void GRExprEngine::VisitDeclStmtAux(DeclStmt* DS, ScopedDecl* D, if (Tmp.empty()) Tmp.Add(Pred); for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { - const GRState* St = GetState(*I); - - if (!Ex && VD->hasGlobalStorage()) { - - // Handle variables with global storage and no initializers. - - // FIXME: static variables may have an initializer, but the second - // time a function is called those values may not be current. - - - // In this context, Static => Local variable. - - assert (!VD->getStorageClass() == VarDecl::Static || - !VD->isFileVarDecl()); - - // If there is no initializer, set the value of the - // variable to "Undefined". - - if (VD->getStorageClass() == VarDecl::Static) { - - // C99: 6.7.8 Initialization - // If an object that has static storage duration is not initialized - // explicitly, then: - // —if it has pointer type, it is initialized to a null pointer; - // —if it has arithmetic type, it is initialized to (positive or - // unsigned) zero; - - // FIXME: Handle structs. Now we treat their values as unknown. - - QualType T = VD->getType(); - - if (LVal::IsLValType(T)) - St = SetRVal(St, lval::DeclVal(VD), - lval::ConcreteInt(getBasicVals().getValue(0, T))); - else if (T->isIntegerType()) - St = SetRVal(St, lval::DeclVal(VD), - nonlval::ConcreteInt(getBasicVals().getValue(0, T))); - - // FIXME: Handle structs. Now we treat them as unknown. What - // we need to do is treat their members as unknown. - } - } - else { - - // FIXME: Handle structs. Now we treat them as unknown. What - // we need to do is treat their members as unknown. - - QualType T = VD->getType(); - - if (LVal::IsLValType(T) || T->isIntegerType()) { - - RVal V = Ex ? GetRVal(St, Ex) : UndefinedVal(); - - if (Ex && V.isUnknown()) { - - // EXPERIMENTAL: "Conjured" symbols. - - unsigned Count = Builder->getCurrentBlockCount(); - SymbolID Sym = SymMgr.getConjuredSymbol(Ex, Count); - - V = LVal::IsLValType(Ex->getType()) - ? cast<RVal>(lval::SymbolVal(Sym)) - : cast<RVal>(nonlval::SymbolVal(Sym)); - } - - St = SetRVal(St, lval::DeclVal(VD), V); - } - } - + St = StateMgr.AddDecl(St, VD, Ex, Builder->getCurrentBlockCount()); + // Create a new node. We don't really need to create a new NodeSet // here, but it simplifies things and doesn't cost much. NodeSet Tmp2; diff --git a/lib/Analysis/GRState.cpp b/lib/Analysis/GRState.cpp index 1cee484357..f9257274a6 100644 --- a/lib/Analysis/GRState.cpp +++ b/lib/Analysis/GRState.cpp @@ -142,6 +142,24 @@ const GRState* GRStateManager::SetRVal(const GRState* St, LVal LV, return getPersistentState(NewSt); } +const GRState* GRStateManager::AddDecl(const GRState* St, const VarDecl* VD, + Expr* Ex, unsigned Count) { + Store OldStore = St->getStore(); + Store NewStore; + + if (Ex) + NewStore = StMgr->AddDecl(OldStore, BasicVals, SymMgr, VD, Ex, + GetRVal(St, Ex), Count); + else + NewStore = StMgr->AddDecl(OldStore, BasicVals, SymMgr, VD, Ex); + + if (NewStore == OldStore) + return St; + GRState NewSt = *St; + NewSt.St = NewStore; + return getPersistentState(NewSt); +} + const GRState* GRStateManager::Unbind(const GRState* St, LVal LV) { Store OldStore = St->getStore(); Store NewStore = StMgr->Remove(OldStore, LV); |