diff options
-rw-r--r-- | clang/include/clang/Analysis/PathSensitive/ConstraintManager.h | 3 | ||||
-rw-r--r-- | clang/include/clang/Analysis/PathSensitive/Environment.h | 8 | ||||
-rw-r--r-- | clang/include/clang/Analysis/PathSensitive/GRExprEngine.h | 6 | ||||
-rw-r--r-- | clang/include/clang/Analysis/PathSensitive/GRState.h | 5 | ||||
-rw-r--r-- | clang/include/clang/Analysis/PathSensitive/GRTransferFuncs.h | 5 | ||||
-rw-r--r-- | clang/include/clang/Analysis/PathSensitive/Store.h | 17 | ||||
-rw-r--r-- | clang/include/clang/Analysis/PathSensitive/SymbolManager.h | 43 | ||||
-rw-r--r-- | clang/lib/Analysis/BasicConstraintManager.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Analysis/BasicStore.cpp | 26 | ||||
-rw-r--r-- | clang/lib/Analysis/CFRefCount.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Analysis/Environment.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Analysis/GRExprEngine.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Analysis/GRState.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Analysis/RegionStore.cpp | 35 | ||||
-rw-r--r-- | clang/lib/Analysis/SymbolManager.cpp | 18 |
15 files changed, 136 insertions, 118 deletions
diff --git a/clang/include/clang/Analysis/PathSensitive/ConstraintManager.h b/clang/include/clang/Analysis/PathSensitive/ConstraintManager.h index cec7f69df3b..4cded5ce691 100644 --- a/clang/include/clang/Analysis/PathSensitive/ConstraintManager.h +++ b/clang/include/clang/Analysis/PathSensitive/ConstraintManager.h @@ -46,8 +46,7 @@ public: const llvm::APSInt& V) const = 0; virtual const GRState* RemoveDeadBindings(const GRState* St, - StoreManager::LiveSymbolsTy& LSymbols, - StoreManager::DeadSymbolsTy& DSymbols) = 0; + SymbolReaper& SymReaper) = 0; virtual void print(const GRState* St, std::ostream& Out, const char* nl, const char *sep) = 0; diff --git a/clang/include/clang/Analysis/PathSensitive/Environment.h b/clang/include/clang/Analysis/PathSensitive/Environment.h index 7a0c88279cf..7613c9ea5f6 100644 --- a/clang/include/clang/Analysis/PathSensitive/Environment.h +++ b/clang/include/clang/Analysis/PathSensitive/Environment.h @@ -139,10 +139,10 @@ public: Environment BindExpr(const Environment& Env, Stmt* E, SVal V, bool isBlkExpr, bool Invalidate); - Environment RemoveDeadBindings(Environment Env, Stmt* Loc, - const LiveVariables& Liveness, - llvm::SmallVectorImpl<const MemRegion*>& DRoots, - StoreManager::LiveSymbolsTy& LSymbols); + Environment + RemoveDeadBindings(Environment Env, Stmt* Loc, SymbolReaper& SymReaper, + llvm::SmallVectorImpl<const MemRegion*>& DRoots); + }; } // end clang namespace diff --git a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h index e62a75b8737..05bb333cdc5 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -55,11 +55,7 @@ protected: /// Liveness - live-variables information the ValueDecl* and block-level /// Expr* in the CFG. Used to prune out dead state. LiveVariables& Liveness; - - /// DeadSymbols - A scratch set used to record the set of symbols that - /// were just marked dead by a call to GRStateManager::RemoveDeadBindings. - GRStateManager::DeadSymbolsTy DeadSymbols; - + /// Builder - The current GRStmtNodeBuilder which is used when building the /// nodes for a given statement. StmtNodeBuilder* Builder; diff --git a/clang/include/clang/Analysis/PathSensitive/GRState.h b/clang/include/clang/Analysis/PathSensitive/GRState.h index 59de60084d6..7cf3a43bfa8 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRState.h +++ b/clang/include/clang/Analysis/PathSensitive/GRState.h @@ -334,8 +334,6 @@ public: MemRegionManager& getRegionManager() { return StoreMgr->getRegionManager(); } StoreManager& getStoreManager() { return *StoreMgr; } - typedef StoreManager::DeadSymbolsTy DeadSymbolsTy; - const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal IVal) { // Store manager should return a persistent state. return StoreMgr->BindDecl(St, VD, IVal); @@ -356,8 +354,7 @@ public: } const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc, - const LiveVariables& Liveness, - DeadSymbolsTy& DeadSyms); + SymbolReaper& SymReaper); const GRState* RemoveSubExprBindings(const GRState* St) { GRState NewSt = *St; diff --git a/clang/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/clang/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index 8f6a75a8ab6..6f4266b9df6 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/clang/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -108,9 +108,8 @@ public: GRExprEngine& Engine, GRStmtNodeBuilder<GRState>& Builder, ExplodedNode<GRState>* Pred, - Stmt* S, - const GRState* St, - const GRStateManager::DeadSymbolsTy& Dead) {} + Stmt* S, const GRState* state, + SymbolReaper& SymReaper) {} // Return statements. virtual void EvalReturn(ExplodedNodeSet<GRState>& Dst, diff --git a/clang/include/clang/Analysis/PathSensitive/Store.h b/clang/include/clang/Analysis/PathSensitive/Store.h index b43699e72bf..b8d6364388f 100644 --- a/clang/include/clang/Analysis/PathSensitive/Store.h +++ b/clang/include/clang/Analysis/PathSensitive/Store.h @@ -28,16 +28,11 @@ typedef const void* Store; class GRState; class GRStateManager; -class LiveVariables; class Stmt; class Expr; class ObjCIvarDecl; class StoreManager { -public: - typedef llvm::SmallSet<SymbolRef, 20> LiveSymbolsTy; - typedef llvm::DenseSet<SymbolRef> DeadSymbolsTy; - protected: /// MRMgr - Manages region objects associated with this StoreManager. MemRegionManager MRMgr; @@ -55,12 +50,7 @@ public: /// lazily computed. /// \return The value bound to the location \c loc. virtual SVal Retrieve(const GRState* state, Loc loc, - QualType T = QualType()) = 0; - -// /// Retrieves the value bound to the specified region. -// SVal GetRegionSVal(const GRState* state, const MemRegion* R) { -// return Retrieve(state, loc::MemRegionVal(R)); -// } + QualType T = QualType()) = 0; /// Return a state with the specified value bound to the given location. /// \param[in] state The analysis state. @@ -129,9 +119,8 @@ public: virtual const MemRegion* getSelfRegion(Store store) = 0; virtual Store - RemoveDeadBindings(const GRState* state, Stmt* Loc, const LiveVariables& Live, - llvm::SmallVectorImpl<const MemRegion*>& RegionRoots, - LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) = 0; + RemoveDeadBindings(const GRState* state, Stmt* Loc, SymbolReaper& SymReaper, + llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0; virtual const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal InitVal) = 0; diff --git a/clang/include/clang/Analysis/PathSensitive/SymbolManager.h b/clang/include/clang/Analysis/PathSensitive/SymbolManager.h index 87852934945..e326166dfc9 100644 --- a/clang/include/clang/Analysis/PathSensitive/SymbolManager.h +++ b/clang/include/clang/Analysis/PathSensitive/SymbolManager.h @@ -17,10 +17,12 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/DenseMap.h" +#include "clang/Analysis/Analyses/LiveVariables.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/Allocator.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ImmutableSet.h" namespace llvm { class raw_ostream; @@ -292,7 +294,44 @@ public: return getSymbolData(ID).getType(*this); } }; + +class SymbolReaper { + typedef llvm::ImmutableSet<SymbolRef> SetTy; + typedef SetTy::Factory FactoryTy; + + FactoryTy F; + SetTy TheLiving; + SetTy TheDead; + LiveVariables& Liveness; + SymbolManager& SymMgr; + +public: + SymbolReaper(LiveVariables& liveness, SymbolManager& symmgr) + : TheLiving(F.GetEmptySet()), TheDead(F.GetEmptySet()), + Liveness(liveness), SymMgr(symmgr) {} + + bool isLive(SymbolRef sym); + bool isLive(const Stmt* Loc, const Stmt* ExprVal) const { + return Liveness.isLive(Loc, ExprVal); + } + + bool isLive(const Stmt* Loc, const VarDecl* VD) const { + return Liveness.isLive(Loc, VD); + } + + void markLive(SymbolRef sym); + bool maybeDead(SymbolRef sym); + + typedef SetTy::iterator dead_iterator; + dead_iterator dead_begin() const { return TheDead.begin(); } + dead_iterator dead_end() const { return TheDead.end(); } + + bool hasDeadSymbols() const { + return !TheDead.isEmpty(); + } +}; + } // end clang namespace #endif diff --git a/clang/lib/Analysis/BasicConstraintManager.cpp b/clang/lib/Analysis/BasicConstraintManager.cpp index d9d97c601a7..450c38f20b9 100644 --- a/clang/lib/Analysis/BasicConstraintManager.cpp +++ b/clang/lib/Analysis/BasicConstraintManager.cpp @@ -82,9 +82,8 @@ public: bool isNotEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const; bool isEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const; - const GRState* RemoveDeadBindings(const GRState* St, - StoreManager::LiveSymbolsTy& LSymbols, - StoreManager::DeadSymbolsTy& DSymbols); + const GRState* RemoveDeadBindings(const GRState* St, SymbolReaper& SymReaper); + void print(const GRState* St, std::ostream& Out, const char* nl, const char *sep); @@ -504,19 +503,17 @@ bool BasicConstraintManager::isEqual(const GRState* St, SymbolRef sym, /// Scan all symbols referenced by the constraints. If the symbol is not alive /// as marked in LSymbols, mark it as dead in DSymbols. -const GRState* BasicConstraintManager::RemoveDeadBindings(const GRState* St, - StoreManager::LiveSymbolsTy& LSymbols, - StoreManager::DeadSymbolsTy& DSymbols) { +const GRState* +BasicConstraintManager::RemoveDeadBindings(const GRState* St, + SymbolReaper& SymReaper) { + GRStateRef state(St, StateMgr); ConstEqTy CE = state.get<ConstEqTy>(); ConstEqTy::Factory& CEFactory = state.get_context<ConstEqTy>(); for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) { - SymbolRef sym = I.getKey(); - if (!LSymbols.count(sym)) { - DSymbols.insert(sym); - CE = CEFactory.Remove(CE, sym); - } + SymbolRef sym = I.getKey(); + if (SymReaper.maybeDead(sym)) CE = CEFactory.Remove(CE, sym); } state = state.set<ConstEqTy>(CE); @@ -525,10 +522,7 @@ const GRState* BasicConstraintManager::RemoveDeadBindings(const GRState* St, for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) { SymbolRef sym = I.getKey(); - if (!LSymbols.count(sym)) { - DSymbols.insert(sym); - CNE = CNEFactory.Remove(CNE, sym); - } + if (SymReaper.maybeDead(sym)) CNE = CNEFactory.Remove(CNE, sym); } return state.set<ConstNotEqTy>(CNE); diff --git a/clang/lib/Analysis/BasicStore.cpp b/clang/lib/Analysis/BasicStore.cpp index b223114a51d..7315ec71ace 100644 --- a/clang/lib/Analysis/BasicStore.cpp +++ b/clang/lib/Analysis/BasicStore.cpp @@ -88,10 +88,10 @@ public: /// RemoveDeadBindings - Scans a BasicStore of 'state' for dead values. /// It returns a new Store with these values removed, and populates LSymbols /// and DSymbols with the known set of live and dead symbols respectively. - Store RemoveDeadBindings(const GRState* state, Stmt* Loc, - const LiveVariables& Live, - llvm::SmallVectorImpl<const MemRegion*>& RegionRoots, - LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols); + Store + RemoveDeadBindings(const GRState* state, Stmt* Loc, + SymbolReaper& SymReaper, + llvm::SmallVectorImpl<const MemRegion*>& RegionRoots); void iterBindings(Store store, BindingsHandler& f); @@ -344,9 +344,9 @@ Store BasicStoreManager::Remove(Store store, Loc loc) { Store BasicStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, - const LiveVariables& Liveness, - llvm::SmallVectorImpl<const MemRegion*>& RegionRoots, - LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) { + SymbolReaper& SymReaper, + llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) +{ Store store = state->getStore(); VarBindingsTy B = GetVarBindings(store); @@ -354,12 +354,12 @@ BasicStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, // Iterate over the variable bindings. for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) - if (Liveness.isLive(Loc, I.getKey())) { + if (SymReaper.isLive(Loc, I.getKey())) { RegionRoots.push_back(MRMgr.getVarRegion(I.getKey())); SVal X = I.getData(); for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI) - LSymbols.insert(*SI); + SymReaper.markLive(*SI); } // Scan for live variables and live symbols. @@ -371,7 +371,7 @@ BasicStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, while (MR) { if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(MR)) { - LSymbols.insert(SymR->getSymbol()); + SymReaper.markLive(SymR->getSymbol()); break; } else if (const VarRegion* R = dyn_cast<VarRegion>(MR)) { @@ -382,8 +382,8 @@ BasicStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, SVal X = Retrieve(state, loc::MemRegionVal(R)); // FIXME: We need to handle symbols nested in region definitions. - for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI) - LSymbols.insert(*SI); + for (symbol_iterator SI=X.symbol_begin(),SE=X.symbol_end();SI!=SE;++SI) + SymReaper.markLive(*SI); if (!isa<loc::MemRegionVal>(X)) break; @@ -408,7 +408,7 @@ BasicStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, SVal X = I.getData(); for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI) - if (!LSymbols.count(*SI)) DSymbols.insert(*SI); + SymReaper.maybeDead(*SI); } } diff --git a/clang/lib/Analysis/CFRefCount.cpp b/clang/lib/Analysis/CFRefCount.cpp index c72d2a3070b..4731921731f 100644 --- a/clang/lib/Analysis/CFRefCount.cpp +++ b/clang/lib/Analysis/CFRefCount.cpp @@ -1367,9 +1367,9 @@ public: GRExprEngine& Engine, GRStmtNodeBuilder<GRState>& Builder, ExplodedNode<GRState>* Pred, - Stmt* S, - const GRState* St, - const GRStateManager::DeadSymbolsTy& Dead); + Stmt* S, const GRState* state, + SymbolReaper& SymReaper); + // Return statements. virtual void EvalReturn(ExplodedNodeSet<GRState>& Dst, @@ -1915,20 +1915,18 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst, ExplodedNode<GRState>* Pred, Stmt* S, const GRState* St, - const GRStateManager::DeadSymbolsTy& Dead) { + SymbolReaper& SymReaper) { // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor. RefBindings B = St->get<RefBindings>(); llvm::SmallVector<std::pair<SymbolRef,bool>, 10> Leaked; - for (GRStateManager::DeadSymbolsTy::const_iterator - I=Dead.begin(), E=Dead.end(); I!=E; ++I) { + for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(), + E = SymReaper.dead_end(); I != E; ++I) { const RefVal* T = B.lookup(*I); - - if (!T) - continue; + if (!T) continue; bool hasLeak = false; diff --git a/clang/lib/Analysis/Environment.cpp b/clang/lib/Analysis/Environment.cpp index 5f9e97eb0a3..c4ed349906d 100644 --- a/clang/lib/Analysis/Environment.cpp +++ b/clang/lib/Analysis/Environment.cpp @@ -108,9 +108,8 @@ Environment EnvironmentManager::BindExpr(const Environment& Env, Stmt* E,SVal V, Environment EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc, - const LiveVariables& Liveness, - llvm::SmallVectorImpl<const MemRegion*>& DRoots, - StoreManager::LiveSymbolsTy& LSymbols) { + SymbolReaper& SymReaper, + llvm::SmallVectorImpl<const MemRegion*>& DRoots) { // Drop bindings for subexpressions. Env = RemoveSubExprBindings(Env); @@ -120,19 +119,18 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc, I != E; ++I) { Stmt* BlkExpr = I.getKey(); - if (Liveness.isLive(Loc, BlkExpr)) { + if (SymReaper.isLive(Loc, BlkExpr)) { SVal X = I.getData(); // If the block expr's value is a memory region, then mark that region. if (isa<loc::MemRegionVal>(X)) DRoots.push_back(cast<loc::MemRegionVal>(X).getRegion()); - // Mark all symbols in the block expr's value. for (SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); - SI != SE; ++SI) { - LSymbols.insert(*SI); - } + SI != SE; ++SI) + SymReaper.markLive(*SI); + } else { // The block expr is dead. SVal X = I.getData(); diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index 80215f34e88..6a7f86b14bf 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -211,18 +211,17 @@ void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) { if (BatchAuditor) Builder->setAuditor(BatchAuditor.get()); + // Create the cleaned state. - if (PurgeDead) - CleanedState = StateMgr.RemoveDeadBindings(EntryNode->getState(), - CurrentStmt, - Liveness, DeadSymbols); - else - CleanedState = EntryNode->getState(); - + SymbolReaper SymReaper(Liveness, SymMgr); + CleanedState = PurgeDead ? StateMgr.RemoveDeadBindings(EntryNode->getState(), + CurrentStmt, SymReaper) + : EntryNode->getState(); + // Process any special transfer function for dead symbols. NodeSet Tmp; - if (DeadSymbols.empty()) + if (!SymReaper.hasDeadSymbols()) Tmp.Add(EntryNode); else { SaveAndRestore<bool> OldSink(Builder->BuildSinks); @@ -232,7 +231,7 @@ void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) { Builder->PurgingDeadSymbols = true; getTF().EvalDeadSymbols(Tmp, *this, *Builder, EntryNode, S, - CleanedState, DeadSymbols); + CleanedState, SymReaper); if (!Builder->BuildSinks && !Builder->HasGeneratedNode) Tmp.Add(EntryNode); diff --git a/clang/lib/Analysis/GRState.cpp b/clang/lib/Analysis/GRState.cpp index 8e49ebb63db..ea6f7a03d69 100644 --- a/clang/lib/Analysis/GRState.cpp +++ b/clang/lib/Analysis/GRState.cpp @@ -34,9 +34,8 @@ GRStateManager::~GRStateManager() { const GRState* GRStateManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, - const LiveVariables& Liveness, - DeadSymbolsTy& DSymbols) { - + SymbolReaper& SymReaper) { + // This code essentially performs a "mark-and-sweep" of the VariableBindings. // The roots are any Block-level exprs and Decls that our liveness algorithm // tells us are live. We then see what Decls they may reference, and keep @@ -44,19 +43,17 @@ GRStateManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, // frequency of which this method is called should be experimented with // for optimum performance. llvm::SmallVector<const MemRegion*, 10> RegionRoots; - StoreManager::LiveSymbolsTy LSymbols; GRState NewState = *state; - NewState.Env = EnvMgr.RemoveDeadBindings(NewState.Env, Loc, Liveness, - RegionRoots, LSymbols); + NewState.Env = EnvMgr.RemoveDeadBindings(NewState.Env, Loc, SymReaper, + RegionRoots); // Clean up the store. - DSymbols.clear(); - NewState.St = StoreMgr->RemoveDeadBindings(&NewState, Loc, Liveness, - RegionRoots, LSymbols, DSymbols); + NewState.St = StoreMgr->RemoveDeadBindings(&NewState, Loc, SymReaper, + RegionRoots); return ConstraintMgr->RemoveDeadBindings(getPersistentState(NewState), - LSymbols, DSymbols); + SymReaper); } const GRState* GRStateManager::Unbind(const GRState* St, Loc LV) { diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp index 0c6fb8098b7..7c42fec6ffb 100644 --- a/clang/lib/Analysis/RegionStore.cpp +++ b/clang/lib/Analysis/RegionStore.cpp @@ -195,11 +195,8 @@ public: /// It returns a new Store with these values removed, and populates LSymbols // and DSymbols with the known set of live and dead symbols respectively. Store RemoveDeadBindings(const GRState* state, Stmt* Loc, - const LiveVariables& Live, - llvm::SmallVectorImpl<const MemRegion*>& RegionRoots, - LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols); - - void UpdateLiveSymbols(SVal X, LiveSymbolsTy& LSymbols); + SymbolReaper& SymReaper, + llvm::SmallVectorImpl<const MemRegion*>& RegionRoots); const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal InitVal); @@ -696,15 +693,15 @@ const GRState* RegionStoreManager::setExtent(const GRState* St, } -void RegionStoreManager::UpdateLiveSymbols(SVal X, LiveSymbolsTy& LSymbols) { - for (SVal::symbol_iterator SI=X.symbol_begin(),SE=X.symbol_end();SI!=SE;++SI) - LSymbols.insert(*SI); +static void UpdateLiveSymbols(SVal X, SymbolReaper& SymReaper) { + for (SVal::symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end();SI!=SE;++SI) + SymReaper.markLive(*SI); } Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, - const LiveVariables& Live, - llvm::SmallVectorImpl<const MemRegion*>& RegionRoots, - LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) { + SymbolReaper& SymReaper, + llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) +{ Store store = state->getStore(); RegionBindingsTy B = GetRegionBindings(store); @@ -732,7 +729,7 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { const MemRegion* R = I.getKey(); if (const VarRegion* VR = dyn_cast<VarRegion>(R)) { - if (Live.isLive(Loc, VR->getDecl())) + if (SymReaper.isLive(Loc, VR->getDecl())) RegionRoots.push_back(VR); // This is a live "root". } else { @@ -748,7 +745,7 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, // to also mark SuperR as a root (as it may not have a value directly // bound to it in the store). if (const VarRegion* VR = dyn_cast<VarRegion>(SuperR)) { - if (Live.isLive(Loc, VR->getDecl())) + if (SymReaper.isLive(Loc, VR->getDecl())) RegionRoots.push_back(VR); // This is a live "root". } } @@ -773,13 +770,13 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, // Mark the symbol for any live SymbolicRegion as "live". This means we // should continue to track that symbol. if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R)) - LSymbols.insert(SymR->getSymbol()); + SymReaper.markLive(SymR->getSymbol()); // Get the data binding for R (if any). RegionBindingsTy::data_type* Xptr = B.lookup(R); if (Xptr) { SVal X = *Xptr; - UpdateLiveSymbols(X, LSymbols); // Update the set of live symbols. + UpdateLiveSymbols(X, SymReaper); // Update the set of live symbols. // If X is a region, then add it the RegionRoots. if (loc::MemRegionVal* RegionX = dyn_cast<loc::MemRegionVal>(&X)) @@ -811,14 +808,12 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, store = Remove(store, Loc::MakeVal(R)); // Mark all non-live symbols that this region references as dead. - if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R)) { - SymbolRef Sym = SymR->getSymbol(); - if (!LSymbols.count(Sym)) DSymbols.insert(Sym); - } + if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R)) + SymReaper.maybeDead(SymR->getSymbol()); SVal X = I.getData(); SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); - for (; SI != SE; ++SI) { if (!LSymbols.count(*SI)) DSymbols.insert(*SI); } + for (; SI != SE; ++SI) SymReaper.maybeDead(*SI); } return store; diff --git a/clang/lib/Analysis/SymbolManager.cpp b/clang/lib/Analysis/SymbolManager.cpp index f8f85559492..d0099e15fa8 100644 --- a/clang/lib/Analysis/SymbolManager.cpp +++ b/clang/lib/Analysis/SymbolManager.cpp @@ -158,3 +158,21 @@ QualType SymbolData::getType(const SymbolManager& SymMgr) const { } SymbolManager::~SymbolManager() {} + +void SymbolReaper::markLive(SymbolRef sym) { + TheLiving = F.Add(TheLiving, sym); + TheDead = F.Remove(TheDead, sym); +} + +bool SymbolReaper::maybeDead(SymbolRef sym) { + if (isLive(sym)) + return false; + + TheDead = F.Add(TheDead, sym); + return true; +} + +bool SymbolReaper::isLive(SymbolRef sym) { + return TheLiving.contains(sym); +} + |