diff --git a/clang/include/clang/Analysis/PathSensitive/Environment.h b/clang/include/clang/Analysis/PathSensitive/Environment.h index 5c702d659c36..fde8b167f3c7 100644 --- a/clang/include/clang/Analysis/PathSensitive/Environment.h +++ b/clang/include/clang/Analysis/PathSensitive/Environment.h @@ -141,7 +141,7 @@ public: Environment RemoveDeadBindings(Environment Env, Stmt* Loc, SymbolReaper& SymReaper, - GRStateManager& StateMgr, + GRStateManager& StateMgr, const GRState *state, llvm::SmallVectorImpl& DRoots); }; diff --git a/clang/include/clang/Analysis/PathSensitive/GRState.h b/clang/include/clang/Analysis/PathSensitive/GRState.h index 18cba5dc0d8c..ac474edfdf53 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRState.h +++ b/clang/include/clang/Analysis/PathSensitive/GRState.h @@ -611,8 +611,8 @@ public: ConstraintMgr->EndPath(St); } - bool scanReachableSymbols(nonloc::CompoundVal val, SymbolVisitor& vistor); - bool scanReachableSymbols(SVal val, SymbolVisitor& visitor); + bool scanReachableSymbols(SVal val, const GRState* state, + SymbolVisitor& visitor); }; //===----------------------------------------------------------------------===// @@ -738,7 +738,7 @@ public: template CB scanReachableSymbols(SVal val) { CB cb(*this); - Mgr->scanReachableSymbols(val, cb); + Mgr->scanReachableSymbols(val, St, cb); return cb; } diff --git a/clang/include/clang/Analysis/PathSensitive/Store.h b/clang/include/clang/Analysis/PathSensitive/Store.h index 2f7920ac6b5c..ac0625dd0199 100644 --- a/clang/include/clang/Analysis/PathSensitive/Store.h +++ b/clang/include/clang/Analysis/PathSensitive/Store.h @@ -170,11 +170,11 @@ public: class Visitor { public: - virtual ~Visitor() {} - virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion); + virtual ~Visitor() {}; + virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0; }; - virtual void iterSubRegions(const MemRegion* R, Visitor& V) const = 0; + virtual bool iterSubRegions(const MemRegion* R, Visitor& V) const = 0; }; StoreManager* CreateBasicStoreManager(GRStateManager& StMgr); diff --git a/clang/lib/Analysis/BasicStore.cpp b/clang/lib/Analysis/BasicStore.cpp index 31408c02445f..35c6652fe58b 100644 --- a/clang/lib/Analysis/BasicStore.cpp +++ b/clang/lib/Analysis/BasicStore.cpp @@ -27,8 +27,9 @@ class VISIBILITY_HIDDEN BasicStoreSubRegionMap : public SubRegionMap { public: BasicStoreSubRegionMap() {} - void iterSubRegions(const MemRegion* R, Visitor& V) const { + bool iterSubRegions(const MemRegion* R, Visitor& V) const { // Do nothing. No subregions. + return true; } }; diff --git a/clang/lib/Analysis/Environment.cpp b/clang/lib/Analysis/Environment.cpp index e3ed678d5e95..41adddc360b2 100644 --- a/clang/lib/Analysis/Environment.cpp +++ b/clang/lib/Analysis/Environment.cpp @@ -119,6 +119,7 @@ Environment EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc, SymbolReaper& SymReaper, GRStateManager& StateMgr, + const GRState *state, llvm::SmallVectorImpl& DRoots) { // Drop bindings for subexpressions. @@ -138,7 +139,7 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc, // Mark all symbols in the block expr's value live. MarkLiveCallback cb(SymReaper); - StateMgr.scanReachableSymbols(X, cb); + StateMgr.scanReachableSymbols(X, state, cb); } else { // The block expr is dead. SVal X = I.getData(); diff --git a/clang/lib/Analysis/GRState.cpp b/clang/lib/Analysis/GRState.cpp index 0788b432ba5e..794871cb1a73 100644 --- a/clang/lib/Analysis/GRState.cpp +++ b/clang/lib/Analysis/GRState.cpp @@ -46,7 +46,7 @@ GRStateManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, GRState NewState = *state; NewState.Env = EnvMgr.RemoveDeadBindings(NewState.Env, Loc, SymReaper, *this, - RegionRoots); + state, RegionRoots); // Clean up the store. NewState.St = StoreMgr->RemoveDeadBindings(&NewState, Loc, SymReaper, @@ -208,19 +208,42 @@ const GRState* GRStateManager::addGDM(const GRState* St, void* Key, void* Data){ // Utility. //===----------------------------------------------------------------------===// -bool GRStateManager::scanReachableSymbols(nonloc::CompoundVal val, - SymbolVisitor& visitor) { +namespace { + class VISIBILITY_HIDDEN ScanReachableSymbols : public SubRegionMap::Visitor { + typedef llvm::DenseSet VisitedRegionsTy; + + VisitedRegionsTy visited; + GRStateRef state; + SymbolVisitor &visitor; + llvm::OwningPtr SRM; +public: + + ScanReachableSymbols(GRStateManager* sm, const GRState *st, SymbolVisitor& v) + : state(st, *sm), visitor(v) {} + + bool scan(nonloc::CompoundVal val); + bool scan(SVal val); + bool scan(const MemRegion *R); + + // From SubRegionMap::Visitor. + bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) { + return scan(SubRegion); + } +}; +} + +bool ScanReachableSymbols::scan(nonloc::CompoundVal val) { for (nonloc::CompoundVal::iterator I=val.begin(), E=val.end(); I!=E; ++I) - if (!scanReachableSymbols(*I, visitor)) return false; + if (!scan(*I)) + return false; return true; } - -bool GRStateManager::scanReachableSymbols(SVal val, SymbolVisitor& visitor) { - - // FIXME: Scan through through the reachable regions. - // if (isa(val)) { ... } - + +bool ScanReachableSymbols::scan(SVal val) { + if (loc::MemRegionVal *X = dyn_cast(&val)) + return scan(X->getRegion()); + if (loc::SymbolVal *X = dyn_cast(&val)) return visitor.VisitSymbol(X->getSymbol()); @@ -228,10 +251,43 @@ bool GRStateManager::scanReachableSymbols(SVal val, SymbolVisitor& visitor) { return visitor.VisitSymbol(X->getSymbol()); if (nonloc::CompoundVal *X = dyn_cast(&val)) - return scanReachableSymbols(*X, visitor); + return scan(*X); return true; } + +bool ScanReachableSymbols::scan(const MemRegion *R) { + if (visited.count(R)) + return true; + + visited.insert(R); + + // If this is a symbolic region, visit the symbol for the region. + if (const SymbolicRegion *SR = dyn_cast(R)) + if (!visitor.VisitSymbol(SR->getSymbol())) + return false; + + // If this is a subregion, also visit the parent regions. + if (const SubRegion *SR = dyn_cast(R)) + if (!scan(SR->getSuperRegion())); + return false; + + // Now look at the binding to this region (if any). + if (!scan(state.GetSVal(R))) + return false; + + // Now look at the subregions. + if (!SRM.get()) + SRM.reset(state.getManager().getStoreManager().getSubRegionMap(state).get()); + + return SRM->iterSubRegions(R, *this); +} + +bool GRStateManager::scanReachableSymbols(SVal val, const GRState* state, + SymbolVisitor& visitor) { + ScanReachableSymbols S(this, state, visitor); + return S.scan(val); +} //===----------------------------------------------------------------------===// // Queries. diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp index 0671a806d220..6238ff20ed7a 100644 --- a/clang/lib/Analysis/RegionStore.cpp +++ b/clang/lib/Analysis/RegionStore.cpp @@ -121,18 +121,20 @@ public: ~RegionStoreSubRegionMap() {} - void iterSubRegions(const MemRegion* Parent, Visitor& V) const { + bool iterSubRegions(const MemRegion* Parent, Visitor& V) const { Map::iterator I = M.find(Parent); if (I == M.end()) - return; + return true; llvm::ImmutableSet S = I->second; for (llvm::ImmutableSet::iterator SI=S.begin(),SE=S.end(); SI != SE; ++SI) { if (!V.Visit(Parent, *SI)) - return; + return false; } + + return true; } }; @@ -600,10 +602,8 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R, SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R) { // Assume the base location is MemRegionVal(ElementRegion). - - if (!isa(L)) { + if (!isa(L)) return UnknownVal(); - } const MemRegion* MR = cast(L).getRegion(); @@ -621,8 +621,9 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R) { ER->getArrayRegion()); return Loc::MakeVal(NewER); - } else - return UnknownVal(); + } + + return UnknownVal(); } SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {