diff options
Diffstat (limited to 'lib/Analysis')
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 40 | ||||
-rw-r--r-- | lib/Analysis/Environment.cpp | 22 | ||||
-rw-r--r-- | lib/Analysis/GRState.cpp | 31 | ||||
-rw-r--r-- | lib/Analysis/SymbolManager.cpp | 3 |
4 files changed, 73 insertions, 23 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 875c4e39b8..81faf21653 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -21,6 +21,7 @@ #include "clang/Analysis/LocalCheckers.h" #include "clang/Analysis/PathDiagnostic.h" #include "clang/Analysis/PathSensitive/BugReporter.h" +#include "clang/Analysis/PathSensitive/SymbolManager.h" #include "clang/AST/DeclObjC.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -1736,13 +1737,25 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst, EvalSummary(Dst, Eng, Builder, ME, ME->getReceiver(), Summ, ME->arg_begin(), ME->arg_end(), Pred); } + +namespace { +class VISIBILITY_HIDDEN StopTrackingCallback : public SymbolVisitor { + GRStateRef state; +public: + StopTrackingCallback(GRStateRef st) : state(st) {} + GRStateRef getState() { return state; } + + bool VisitSymbol(SymbolRef sym) { + state = state.remove<RefBindings>(sym); + return true; + } -void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) { - // Check if we have a binding for "Val" and if we are storing it to something - // we don't understand or otherwise the value "escapes" the function. - if (!isa<loc::SymbolVal>(val)) - return; + const GRState* getState() const { return state.getState(); } +}; +} // end anonymous namespace + +void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) { // Are we storing to something that causes the value to "escape"? bool escapes = false; @@ -1752,7 +1765,6 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) { // (2) we are binding to a memregion that does not have stack storage // (3) we are binding to a memregion with stack storage that the store // does not understand. - SymbolRef Sym = cast<loc::SymbolVal>(val).getSymbol(); GRStateRef state = B.getState(); if (!isa<loc::MemRegionVal>(location)) @@ -1769,15 +1781,15 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) { } } - // Our store can represent the binding and we aren't storing to something - // that doesn't have local storage. Just return and have the simulation - // state continue as is. We should also just return if the tracked symbol - // is not associated with a reference count. - if (!escapes || !state.get<RefBindings>(Sym)) - return; + // If our store can represent the binding and we aren't storing to something + // that doesn't have local storage then just return and have the simulation + // state continue as is. + if (!escapes) + return; - // The tracked object excapes. Stop tracking the object. - B.MakeNode(state.remove<RefBindings>(Sym)); + // Otherwise, find all symbols referenced by 'val' that we are tracking + // and stop tracking them. + B.MakeNode(state.scanReachableSymbols<StopTrackingCallback>(val).getState()); } std::pair<GRStateRef,bool> diff --git a/lib/Analysis/Environment.cpp b/lib/Analysis/Environment.cpp index c4ed349906..e3ed678d5e 100644 --- a/lib/Analysis/Environment.cpp +++ b/lib/Analysis/Environment.cpp @@ -10,11 +10,11 @@ // This file defined the Environment and EnvironmentManager classes. // //===----------------------------------------------------------------------===// - -#include "clang/Analysis/PathSensitive/Environment.h" +#include "clang/Analysis/PathSensitive/GRState.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/Support/Streams.h" +#include "llvm/Support/Compiler.h" using namespace clang; @@ -106,9 +106,19 @@ Environment EnvironmentManager::BindExpr(const Environment& Env, Stmt* E,SVal V, return isBlkExpr ? AddBlkExpr(Env, E, V) : AddSubExpr(Env, E, V); } +namespace { +class VISIBILITY_HIDDEN MarkLiveCallback : public SymbolVisitor { + SymbolReaper &SymReaper; +public: + MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {} + bool VisitSymbol(SymbolRef sym) { SymReaper.markLive(sym); return true; } +}; +} // end anonymous namespace + Environment EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc, SymbolReaper& SymReaper, + GRStateManager& StateMgr, llvm::SmallVectorImpl<const MemRegion*>& DRoots) { // Drop bindings for subexpressions. @@ -126,11 +136,9 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc, 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) - SymReaper.markLive(*SI); - + // Mark all symbols in the block expr's value live. + MarkLiveCallback cb(SymReaper); + StateMgr.scanReachableSymbols(X, cb); } else { // The block expr is dead. SVal X = I.getData(); diff --git a/lib/Analysis/GRState.cpp b/lib/Analysis/GRState.cpp index ea6f7a03d6..0788b432ba 100644 --- a/lib/Analysis/GRState.cpp +++ b/lib/Analysis/GRState.cpp @@ -45,7 +45,7 @@ GRStateManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, llvm::SmallVector<const MemRegion*, 10> RegionRoots; GRState NewState = *state; - NewState.Env = EnvMgr.RemoveDeadBindings(NewState.Env, Loc, SymReaper, + NewState.Env = EnvMgr.RemoveDeadBindings(NewState.Env, Loc, SymReaper, *this, RegionRoots); // Clean up the store. @@ -205,6 +205,35 @@ const GRState* GRStateManager::addGDM(const GRState* St, void* Key, void* Data){ } //===----------------------------------------------------------------------===// +// Utility. +//===----------------------------------------------------------------------===// + +bool GRStateManager::scanReachableSymbols(nonloc::CompoundVal val, + SymbolVisitor& visitor) { + for (nonloc::CompoundVal::iterator I=val.begin(), E=val.end(); I!=E; ++I) + if (!scanReachableSymbols(*I, visitor)) return false; + + return true; +} + +bool GRStateManager::scanReachableSymbols(SVal val, SymbolVisitor& visitor) { + + // FIXME: Scan through through the reachable regions. + // if (isa<Loc>(val)) { ... } + + if (loc::SymbolVal *X = dyn_cast<loc::SymbolVal>(&val)) + return visitor.VisitSymbol(X->getSymbol()); + + if (nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(&val)) + return visitor.VisitSymbol(X->getSymbol()); + + if (nonloc::CompoundVal *X = dyn_cast<nonloc::CompoundVal>(&val)) + return scanReachableSymbols(*X, visitor); + + return true; +} + +//===----------------------------------------------------------------------===// // Queries. //===----------------------------------------------------------------------===// diff --git a/lib/Analysis/SymbolManager.cpp b/lib/Analysis/SymbolManager.cpp index 1672af8c61..f1c1cc0a46 100644 --- a/lib/Analysis/SymbolManager.cpp +++ b/lib/Analysis/SymbolManager.cpp @@ -99,4 +99,5 @@ bool SymbolReaper::isLive(SymbolRef sym) { // the analyzed function/method. return isa<SymbolRegionRValue>(SymMgr.getSymbolData(sym)); } - + +SymbolVisitor::~SymbolVisitor() {} |