[cfe-commits] r73572 - in /cfe/trunk: include/clang/Analysis/PathSensitive/Store.h lib/Analysis/RegionStore.cpp
Ted Kremenek
kremenek at apple.com
Tue Jun 16 15:36:44 PDT 2009
Author: kremenek
Date: Tue Jun 16 17:36:44 2009
New Revision: 73572
URL: http://llvm.org/viewvc/llvm-project?rev=73572&view=rev
Log:
RegionStoreManager:
- Add "sections" to RegionStoreManager.cpp to delineate functionality.
- Add new function "CreateFieldsOnlyRegionStoreManager" that uses the new
RegionStoreFeatures class to use a reduced set of features from
RegionStoreManager (in this case, only field-sensitivity). This isn't
completely hooked up yet.
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/Store.h
cfe/trunk/lib/Analysis/RegionStore.cpp
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/Store.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/Store.h?rev=73572&r1=73571&r2=73572&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Store.h Tue Jun 16 17:36:44 2009
@@ -196,8 +196,9 @@
virtual bool iterSubRegions(const MemRegion* R, Visitor& V) const = 0;
};
-StoreManager* CreateBasicStoreManager(GRStateManager& StMgr);
-StoreManager* CreateRegionStoreManager(GRStateManager& StMgr);
+StoreManager *CreateBasicStoreManager(GRStateManager& StMgr);
+StoreManager *CreateRegionStoreManager(GRStateManager& StMgr);
+StoreManager *CreateFieldsOnlyRegionStoreManager(GRStateManager& StMgr);
} // end clang namespace
Modified: cfe/trunk/lib/Analysis/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RegionStore.cpp?rev=73572&r1=73571&r2=73572&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/RegionStore.cpp (original)
+++ cfe/trunk/lib/Analysis/RegionStore.cpp Tue Jun 16 17:36:44 2009
@@ -31,6 +31,32 @@
typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionBindingsTy;
//===----------------------------------------------------------------------===//
+// Fine-grained control of RegionStoreManager.
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct VISIBILITY_HIDDEN minimal_features_tag {};
+struct VISIBILITY_HIDDEN maximal_features_tag {};
+
+class VISIBILITY_HIDDEN RegionStoreFeatures {
+ bool SupportsFields;
+ bool SupportsRemaining;
+
+public:
+ RegionStoreFeatures(minimal_features_tag) :
+ SupportsFields(false), SupportsRemaining(false) {}
+
+ RegionStoreFeatures(maximal_features_tag) :
+ SupportsFields(true), SupportsRemaining(false) {}
+
+ void enableFields(bool t) { SupportsFields = t; }
+
+ bool supportsFields() const { return SupportsFields; }
+ bool supportsRemaining() const { return SupportsRemaining; }
+};
+}
+
+//===----------------------------------------------------------------------===//
// Region "Views"
//===----------------------------------------------------------------------===//
//
@@ -151,6 +177,7 @@
};
class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
+ const RegionStoreFeatures Features;
RegionBindingsTy::Factory RBFactory;
RegionViews::Factory RVFactory;
@@ -158,8 +185,9 @@
const ImplicitParamDecl *SelfDecl;
public:
- RegionStoreManager(GRStateManager& mgr)
+ RegionStoreManager(GRStateManager& mgr, const RegionStoreFeatures &f)
: StoreManager(mgr),
+ Features(f),
RBFactory(mgr.getAllocator()),
RVFactory(mgr.getAllocator()),
SelfRegion(0), SelfDecl(0) {
@@ -308,8 +336,19 @@
} // end anonymous namespace
-StoreManager* clang::CreateRegionStoreManager(GRStateManager& StMgr) {
- return new RegionStoreManager(StMgr);
+//===----------------------------------------------------------------------===//
+// RegionStore creation.
+//===----------------------------------------------------------------------===//
+
+StoreManager *clang::CreateRegionStoreManager(GRStateManager& StMgr) {
+ RegionStoreFeatures F = maximal_features_tag();
+ return new RegionStoreManager(StMgr, F);
+}
+
+StoreManager *clang::CreateFieldsOnlyRegionStoreManager(GRStateManager &StMgr) {
+ RegionStoreFeatures F = minimal_features_tag();
+ F.enableFields(true);
+ return new RegionStoreManager(StMgr, F);
}
SubRegionMap* RegionStoreManager::getSubRegionMap(const GRState *state) {
@@ -324,6 +363,10 @@
return M;
}
+//===----------------------------------------------------------------------===//
+// getLValueXXX methods.
+//===----------------------------------------------------------------------===//
+
/// getLValueString - Returns an SVal representing the lvalue of a
/// StringLiteral. Within RegionStore a StringLiteral has an
/// associated StringRegion, and the lvalue of a StringLiteral is the
@@ -477,6 +520,10 @@
getContext()));
}
+//===----------------------------------------------------------------------===//
+// Extents for regions.
+//===----------------------------------------------------------------------===//
+
SVal RegionStoreManager::getSizeInElements(const GRState* St,
const MemRegion* R) {
if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
@@ -539,6 +586,16 @@
return UnknownVal();
}
+const GRState* RegionStoreManager::setExtent(const GRState* St,
+ const MemRegion* R, SVal Extent) {
+ GRStateRef state(St, StateMgr);
+ return state.set<RegionExtents>(R, Extent);
+}
+
+//===----------------------------------------------------------------------===//
+// Location and region casting.
+//===----------------------------------------------------------------------===//
+
/// ArrayToPointer - Emulates the "decay" of an array to a pointer
/// type. 'Array' represents the lvalue of the array being decayed
/// to a pointer, and the returned SVal represents the decayed
@@ -637,6 +694,10 @@
return 0;
}
+//===----------------------------------------------------------------------===//
+// Pointer arithmetic.
+//===----------------------------------------------------------------------===//
+
SVal RegionStoreManager::EvalBinOp(const GRState *state,
BinaryOperator::Opcode Op, Loc L, NonLoc R) {
// Assume the base location is MemRegionVal.
@@ -696,6 +757,10 @@
return UnknownVal();
}
+//===----------------------------------------------------------------------===//
+// Loading values from regions.
+//===----------------------------------------------------------------------===//
+
SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
assert(!isa<UnknownVal>(L) && "location unknown");
assert(!isa<UndefinedVal>(L) && "location undefined");
@@ -883,45 +948,49 @@
return NonLoc::MakeCompoundVal(T, ArrayVal, getBasicVals());
}
+//===----------------------------------------------------------------------===//
+// Binding values to regions.
+//===----------------------------------------------------------------------===//
+
+Store RegionStoreManager::Remove(Store store, Loc L) {
+ const MemRegion* R = 0;
+
+ if (isa<loc::MemRegionVal>(L))
+ R = cast<loc::MemRegionVal>(L).getRegion();
+
+ if (R) {
+ RegionBindingsTy B = GetRegionBindings(store);
+ return RBFactory.Remove(B, R).getRoot();
+ }
+
+ return store;
+}
+
const GRState* RegionStoreManager::Bind(const GRState* St, Loc L, SVal V) {
// If we get here, the location should be a region.
const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion();
assert(R);
-
+
// Check if the region is a struct region.
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
if (TR->getValueType(getContext())->isStructureType())
return BindStruct(St, TR, V);
-
+
Store store = St->getStore();
RegionBindingsTy B = GetRegionBindings(store);
-
+
if (V.isUnknown()) {
// Remove the binding.
store = RBFactory.Remove(B, R).getRoot();
-
+
// Add the region to the killset.
GRStateRef state(St, StateMgr);
St = state.add<RegionKills>(R);
}
else
store = RBFactory.Add(B, R, V).getRoot();
-
- return StateMgr.MakeStateWithStore(St, store);
-}
-
-Store RegionStoreManager::Remove(Store store, Loc L) {
- const MemRegion* R = 0;
-
- if (isa<loc::MemRegionVal>(L))
- R = cast<loc::MemRegionVal>(L).getRegion();
- if (R) {
- RegionBindingsTy B = GetRegionBindings(store);
- return RBFactory.Remove(B, R).getRoot();
- }
-
- return store;
+ return StateMgr.MakeStateWithStore(St, store);
}
const GRState* RegionStoreManager::BindDecl(const GRState* St,
@@ -946,182 +1015,6 @@
return Bind(St, loc::MemRegionVal(R), V);
}
-const GRState* RegionStoreManager::setExtent(const GRState* St,
- const MemRegion* R, SVal Extent) {
- GRStateRef state(St, StateMgr);
- return state.set<RegionExtents>(R, Extent);
-}
-
-
-static void UpdateLiveSymbols(SVal X, SymbolReaper& SymReaper) {
- if (loc::MemRegionVal *XR = dyn_cast<loc::MemRegionVal>(&X)) {
- const MemRegion *R = XR->getRegion();
-
- while (R) {
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
- SymReaper.markLive(SR->getSymbol());
- return;
- }
-
- if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
- R = SR->getSuperRegion();
- continue;
- }
-
- break;
- }
-
- return;
- }
-
- 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,
- SymbolReaper& SymReaper,
- llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
-{
-
- Store store = state->getStore();
- RegionBindingsTy B = GetRegionBindings(store);
-
- // Lazily constructed backmap from MemRegions to SubRegions.
- typedef llvm::ImmutableSet<const MemRegion*> SubRegionsTy;
- typedef llvm::ImmutableMap<const MemRegion*, SubRegionsTy> SubRegionsMapTy;
-
- // FIXME: As a future optimization we can modifiy BumpPtrAllocator to have
- // the ability to reuse memory. This way we can keep TmpAlloc around as
- // an instance variable of RegionStoreManager (avoiding repeated malloc
- // overhead).
- llvm::BumpPtrAllocator TmpAlloc;
-
- // Factory objects.
- SubRegionsMapTy::Factory SubRegMapF(TmpAlloc);
- SubRegionsTy::Factory SubRegF(TmpAlloc);
-
- // The backmap from regions to subregions.
- SubRegionsMapTy SubRegMap = SubRegMapF.GetEmptyMap();
-
- // Do a pass over the regions in the store. For VarRegions we check if
- // the variable is still live and if so add it to the list of live roots.
- // For other regions we populate our region backmap.
-
- llvm::SmallVector<const MemRegion*, 10> IntermediateRoots;
-
- for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- IntermediateRoots.push_back(I.getKey());
- }
-
- while (!IntermediateRoots.empty()) {
- const MemRegion* R = IntermediateRoots.back();
- IntermediateRoots.pop_back();
-
- if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
- if (SymReaper.isLive(Loc, VR->getDecl()))
- RegionRoots.push_back(VR); // This is a live "root".
- }
- else if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) {
- if (SymReaper.isLive(SR->getSymbol()))
- RegionRoots.push_back(SR);
- }
- else {
- // Get the super region for R.
- const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion();
-
- // Get the current set of subregions for SuperR.
- const SubRegionsTy* SRptr = SubRegMap.lookup(SuperR);
- SubRegionsTy SRs = SRptr ? *SRptr : SubRegF.GetEmptySet();
-
- // Add R to the subregions of SuperR.
- SubRegMap = SubRegMapF.Add(SubRegMap, SuperR, SubRegF.Add(SRs, R));
-
- // Super region may be VarRegion or subregion of another VarRegion. Add it
- // to the work list.
- if (isa<SubRegion>(SuperR))
- IntermediateRoots.push_back(SuperR);
- }
- }
-
- // Process the worklist of RegionRoots. This performs a "mark-and-sweep"
- // of the store. We want to find all live symbols and dead regions.
- llvm::SmallPtrSet<const MemRegion*, 10> Marked;
-
- while (!RegionRoots.empty()) {
- // Dequeue the next region on the worklist.
- const MemRegion* R = RegionRoots.back();
- RegionRoots.pop_back();
-
- // Check if we have already processed this region.
- if (Marked.count(R)) continue;
-
- // Mark this region as processed. This is needed for termination in case
- // a region is referenced more than once.
- Marked.insert(R);
-
- // 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))
- 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, 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))
- RegionRoots.push_back(RegionX->getRegion());
- }
-
- // Get the subregions of R. These are RegionRoots as well since they
- // represent values that are also bound to R.
- const SubRegionsTy* SRptr = SubRegMap.lookup(R);
- if (!SRptr) continue;
- SubRegionsTy SR = *SRptr;
-
- for (SubRegionsTy::iterator I=SR.begin(), E=SR.end(); I!=E; ++I)
- RegionRoots.push_back(*I);
- }
-
- // We have now scanned the store, marking reachable regions and symbols
- // as live. We now remove all the regions that are dead from the store
- // as well as update DSymbols with the set symbols that are now dead.
- for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- const MemRegion* R = I.getKey();
-
- // If this region live? Is so, none of its symbols are dead.
- if (Marked.count(R))
- continue;
-
- // Remove this dead region from the store.
- 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))
- SymReaper.maybeDead(SymR->getSymbol());
-
- SVal X = I.getData();
- SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
- for (; SI != SE; ++SI) SymReaper.maybeDead(*SI);
- }
-
- return store;
-}
-
-void RegionStoreManager::print(Store store, std::ostream& Out,
- const char* nl, const char *sep) {
- llvm::raw_os_ostream OS(Out);
- RegionBindingsTy B = GetRegionBindings(store);
- OS << "Store:" << nl;
-
- for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- OS << ' '; I.getKey()->print(OS); OS << " : ";
- I.getData().print(OS); OS << nl;
- }
-}
-
const GRState* RegionStoreManager::BindArray(const GRState* St,
const TypedRegion* R, SVal Init) {
QualType T = R->getValueType(getContext());
@@ -1264,6 +1157,10 @@
return StateMgr.MakeStateWithStore(St, store);
}
+//===----------------------------------------------------------------------===//
+// Region views.
+//===----------------------------------------------------------------------===//
+
const GRState* RegionStoreManager::AddRegionView(const GRState* St,
const MemRegion* View,
const MemRegion* Base) {
@@ -1310,3 +1207,180 @@
GRStateRef state(St, StateMgr);
return state.set<RegionDefaultValue>(R, V);
}
+
+//===----------------------------------------------------------------------===//
+// State pruning.
+//===----------------------------------------------------------------------===//
+
+static void UpdateLiveSymbols(SVal X, SymbolReaper& SymReaper) {
+ if (loc::MemRegionVal *XR = dyn_cast<loc::MemRegionVal>(&X)) {
+ const MemRegion *R = XR->getRegion();
+
+ while (R) {
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
+ SymReaper.markLive(SR->getSymbol());
+ return;
+ }
+
+ if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
+ R = SR->getSuperRegion();
+ continue;
+ }
+
+ break;
+ }
+
+ return;
+ }
+
+ 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,
+ SymbolReaper& SymReaper,
+ llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
+{
+
+ Store store = state->getStore();
+ RegionBindingsTy B = GetRegionBindings(store);
+
+ // Lazily constructed backmap from MemRegions to SubRegions.
+ typedef llvm::ImmutableSet<const MemRegion*> SubRegionsTy;
+ typedef llvm::ImmutableMap<const MemRegion*, SubRegionsTy> SubRegionsMapTy;
+
+ // FIXME: As a future optimization we can modifiy BumpPtrAllocator to have
+ // the ability to reuse memory. This way we can keep TmpAlloc around as
+ // an instance variable of RegionStoreManager (avoiding repeated malloc
+ // overhead).
+ llvm::BumpPtrAllocator TmpAlloc;
+
+ // Factory objects.
+ SubRegionsMapTy::Factory SubRegMapF(TmpAlloc);
+ SubRegionsTy::Factory SubRegF(TmpAlloc);
+
+ // The backmap from regions to subregions.
+ SubRegionsMapTy SubRegMap = SubRegMapF.GetEmptyMap();
+
+ // Do a pass over the regions in the store. For VarRegions we check if
+ // the variable is still live and if so add it to the list of live roots.
+ // For other regions we populate our region backmap.
+
+ llvm::SmallVector<const MemRegion*, 10> IntermediateRoots;
+
+ for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+ IntermediateRoots.push_back(I.getKey());
+ }
+
+ while (!IntermediateRoots.empty()) {
+ const MemRegion* R = IntermediateRoots.back();
+ IntermediateRoots.pop_back();
+
+ if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
+ if (SymReaper.isLive(Loc, VR->getDecl()))
+ RegionRoots.push_back(VR); // This is a live "root".
+ }
+ else if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) {
+ if (SymReaper.isLive(SR->getSymbol()))
+ RegionRoots.push_back(SR);
+ }
+ else {
+ // Get the super region for R.
+ const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion();
+
+ // Get the current set of subregions for SuperR.
+ const SubRegionsTy* SRptr = SubRegMap.lookup(SuperR);
+ SubRegionsTy SRs = SRptr ? *SRptr : SubRegF.GetEmptySet();
+
+ // Add R to the subregions of SuperR.
+ SubRegMap = SubRegMapF.Add(SubRegMap, SuperR, SubRegF.Add(SRs, R));
+
+ // Super region may be VarRegion or subregion of another VarRegion. Add it
+ // to the work list.
+ if (isa<SubRegion>(SuperR))
+ IntermediateRoots.push_back(SuperR);
+ }
+ }
+
+ // Process the worklist of RegionRoots. This performs a "mark-and-sweep"
+ // of the store. We want to find all live symbols and dead regions.
+ llvm::SmallPtrSet<const MemRegion*, 10> Marked;
+
+ while (!RegionRoots.empty()) {
+ // Dequeue the next region on the worklist.
+ const MemRegion* R = RegionRoots.back();
+ RegionRoots.pop_back();
+
+ // Check if we have already processed this region.
+ if (Marked.count(R)) continue;
+
+ // Mark this region as processed. This is needed for termination in case
+ // a region is referenced more than once.
+ Marked.insert(R);
+
+ // 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))
+ 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, 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))
+ RegionRoots.push_back(RegionX->getRegion());
+ }
+
+ // Get the subregions of R. These are RegionRoots as well since they
+ // represent values that are also bound to R.
+ const SubRegionsTy* SRptr = SubRegMap.lookup(R);
+ if (!SRptr) continue;
+ SubRegionsTy SR = *SRptr;
+
+ for (SubRegionsTy::iterator I=SR.begin(), E=SR.end(); I!=E; ++I)
+ RegionRoots.push_back(*I);
+ }
+
+ // We have now scanned the store, marking reachable regions and symbols
+ // as live. We now remove all the regions that are dead from the store
+ // as well as update DSymbols with the set symbols that are now dead.
+ for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+ const MemRegion* R = I.getKey();
+
+ // If this region live? Is so, none of its symbols are dead.
+ if (Marked.count(R))
+ continue;
+
+ // Remove this dead region from the store.
+ 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))
+ SymReaper.maybeDead(SymR->getSymbol());
+
+ SVal X = I.getData();
+ SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
+ for (; SI != SE; ++SI) SymReaper.maybeDead(*SI);
+ }
+
+ return store;
+}
+
+//===----------------------------------------------------------------------===//
+// Utility methods.
+//===----------------------------------------------------------------------===//
+
+void RegionStoreManager::print(Store store, std::ostream& Out,
+ const char* nl, const char *sep) {
+ llvm::raw_os_ostream OS(Out);
+ RegionBindingsTy B = GetRegionBindings(store);
+ OS << "Store:" << nl;
+
+ for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+ OS << ' '; I.getKey()->print(OS); OS << " : ";
+ I.getData().print(OS); OS << nl;
+ }
+}
More information about the cfe-commits
mailing list