Store: (static analyzer)
- Change definition of store::Region and store::Binding (once again) to make
them real classes that just wrap pointers. This makes them more strictly
typed, and allows specific implementations of Regions/Bindings to just
subclass them.
- minor renamings to RegionExtent and its subclasses
- added a bunch of doxygen comments
StoreManager: (static analyzer)
- added 'iterBindings', an iteration method for iterating over the bindings of a
store. It that takes a callback object (acting like a poor man's closure).
- added 'getRVal' version for store::Binding. Will potentially phase the other
versions of GetRVal in StoreManager out.
- reimplemented 'getBindings' to be non-virtual and to use 'iterBindings'
BasicStoreManager: (static analyzer)
- implemented 'iterBindings' for BasicStoreManager
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55688 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index 867028d..9756679 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -21,10 +21,11 @@
using store::Region;
using store::RegionExtent;
+typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;
+
namespace {
class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
- typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;
VarBindingsTy::Factory VBFactory;
GRStateManager& StMgr;
@@ -44,6 +45,8 @@
DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols,
DeadSymbolsTy& DSymbols);
+ virtual void iterBindings(Store store, BindingsHandler& f);
+
virtual Store AddDecl(Store store, GRStateManager& StateMgr,
const VarDecl* VD, Expr* Ex,
RVal InitVal = UndefinedVal(), unsigned Count = 0);
@@ -57,14 +60,38 @@
virtual RegionExtent getExtent(Region R);
- /// getBindings - Returns all bindings in the specified store that bind
- /// to the specified symbolic value.
- virtual void getBindings(llvm::SmallVectorImpl<store::Binding>& bindings,
- Store store, SymbolID Sym);
-
/// BindingAsString - Returns a string representing the given binding.
virtual std::string BindingAsString(store::Binding binding);
-};
+
+ /// getRVal - Returns the bound RVal for a given binding.
+ virtual RVal getRVal(Store store, store::Binding binding);
+};
+
+class VISIBILITY_HIDDEN VarRegion : public store::Region {
+public:
+ VarRegion(VarDecl* VD) : Region(VD) {}
+ VarDecl* getDecl() const { return (VarDecl*) Data; }
+ static bool classof(const store::Region*) { return true; }
+};
+
+class VISIBILITY_HIDDEN VarBinding : public store::Binding {
+public:
+ VarBinding(VarBindingsTy::value_type* T) : store::Binding(T) {}
+
+ const VarBindingsTy::value_type_ref getValue() const {
+ return *static_cast<const VarBindingsTy::value_type*>(first);
+ }
+
+ std::string getName() const {
+ return getValue().first->getName();
+ }
+
+ RVal getRVal() const {
+ return getValue().second;
+ }
+
+ static inline bool classof(const store::Binding*) { return true; }
+};
} // end anonymous namespace
@@ -74,8 +101,7 @@
}
RegionExtent BasicStoreManager::getExtent(Region R) {
- VarDecl* VD = (VarDecl*) R;
- QualType T = VD->getType();
+ QualType T = cast<VarRegion>(&R)->getDecl()->getType();
// FIXME: Add support for VLAs. This may require passing in additional
// information, or tracking a different region type.
@@ -85,8 +111,8 @@
ASTContext& C = StMgr.getContext();
assert (!T->isObjCInterfaceType()); // @interface not a possible VarDecl type.
assert (T != C.VoidTy); // void not a possible VarDecl type.
- return store::IntExtent(StMgr.getBasicVals().getValue(C.getTypeSize(T),
- C.VoidPtrTy));
+ return store::FixedExtent(StMgr.getBasicVals().getValue(C.getTypeSize(T),
+ C.VoidPtrTy));
}
@@ -335,28 +361,62 @@
}
}
-void
-BasicStoreManager::getBindings(llvm::SmallVectorImpl<store::Binding>& bindings,
- Store store, SymbolID Sym) {
+
+void BasicStoreManager::iterBindings(Store store, BindingsHandler& f) {
+ VarBindingsTy B = GetVarBindings(store);
- VarBindingsTy VB((VarBindingsTy::TreeTy*) store);
-
- for (VarBindingsTy::iterator I=VB.begin(), E=VB.end(); I!=E; ++I) {
- if (const lval::SymbolVal* SV=dyn_cast<lval::SymbolVal>(&I->second)) {
- if (SV->getSymbol() == Sym)
- bindings.push_back(I->first);
-
- continue;
- }
-
- if (const nonlval::SymbolVal* SV=dyn_cast<nonlval::SymbolVal>(&I->second)){
- if (SV->getSymbol() == Sym)
- bindings.push_back(I->first);
- }
+ for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I != E; ++I) {
+ VarBinding binding(&(*I));
+ f.HandleBinding(*this, store, binding);
}
}
+
std::string BasicStoreManager::BindingAsString(store::Binding binding) {
- // A binding is just an VarDecl*.
- return ((VarDecl*) binding)->getName();
+ return cast<VarBinding>(binding).getName();
}
+
+RVal BasicStoreManager::getRVal(Store store, store::Binding binding) {
+ return cast<VarBinding>(binding).getRVal();
+}
+
+//==------------------------------------------------------------------------==//
+// Generic store operations.
+//==------------------------------------------------------------------------==//
+
+namespace {
+class VISIBILITY_HIDDEN GetBindingsIterator : public StoreManager::BindingsHandler {
+ SymbolID Sym;
+ llvm::SmallVectorImpl<store::Binding>& bindings;
+public:
+ GetBindingsIterator(SymbolID s, llvm::SmallVectorImpl<store::Binding>& b)
+ : Sym(s), bindings(b) {}
+
+ virtual bool HandleBinding(StoreManager& SMgr, Store store,
+ store::Binding binding) {
+
+ RVal V = SMgr.getRVal(store, binding);
+
+ if (const lval::SymbolVal* SV=dyn_cast<lval::SymbolVal>(&V)) {
+ if (SV->getSymbol() == Sym)
+ bindings.push_back(binding);
+ }
+ else if (const nonlval::SymbolVal* SV=dyn_cast<nonlval::SymbolVal>(&V)){
+ if (SV->getSymbol() == Sym)
+ bindings.push_back(binding);
+ }
+
+ return true;
+ }
+};
+} // end anonymous namespace
+
+void StoreManager::getBindings(llvm::SmallVectorImpl<store::Binding>& bindings,
+ Store store, SymbolID Sym) {
+
+ GetBindingsIterator BI(Sym, bindings);
+ iterBindings(store, BI);
+}
+
+StoreManager::BindingsHandler::~BindingsHandler() {}
+
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 8ea8301..25841cd 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -2308,7 +2308,7 @@
// Find both first node that referred to the tracked symbol and the
// memory location that value was store to.
ExplodedNode<GRState>* Last = N;
- store::Binding FirstBinding = 0;
+ store::Binding FirstBinding;
while (N) {
const GRState* St = N->getState();
@@ -2351,7 +2351,7 @@
// symbol appeared, and also get the first VarDecl that tracked object
// is stored to.
ExplodedNode<GRState>* AllocNode = 0;
- store::Binding FirstBinding = 0;
+ store::Binding FirstBinding;
llvm::tie(AllocNode, FirstBinding) =
GetAllocationSite(&BR.getStateManager(), EndN, Sym);