aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-08-29 00:47:32 +0000
committerTed Kremenek <kremenek@apple.com>2008-08-29 00:47:32 +0000
commit2bc39c61077e6a49728f309bb80a949fb0b2aaff (patch)
tree5d34c9916057c108fac37e6a6ac817e1f31f0677
parent561ca4be84d6456dde1d2bcecf9969d3e99e5368 (diff)
Added "getBindings" and "BindingAsString" to GRStateManager and StoreManager.
Migrated CFRefCount.cpp to use getBindings and BindingsAsString instead of making assumptions about the Store (removed dependence on GRState::vb_iterator). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55522 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Analysis/PathSensitive/GRState.h13
-rw-r--r--include/clang/Analysis/PathSensitive/Store.h9
-rw-r--r--lib/Analysis/BasicStore.cpp34
-rw-r--r--lib/Analysis/CFRefCount.cpp57
4 files changed, 81 insertions, 32 deletions
diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h
index 0ecfb27c16..8570a9d0c2 100644
--- a/include/clang/Analysis/PathSensitive/GRState.h
+++ b/include/clang/Analysis/PathSensitive/GRState.h
@@ -381,6 +381,19 @@ public:
const GRState* addGDM(const GRState* St, void* Key, void* Data);
// Methods that query & manipulate the Store.
+
+ /// getBindings - Returns all store bindings in the specified state that bind
+ /// to the specified symbolic value.
+ void getBindings(llvm::SmallVectorImpl<store::Binding>& bindings,
+ const GRState* St, SymbolID Sym) {
+ StMgr->getBindings(bindings, St->getStore(), Sym);
+ }
+
+ /// BindingAsString - Returns a string representing the given store binding.
+ std::string BindingAsString(store::Binding binding) {
+ return StMgr->BindingAsString(binding);
+ }
+
RVal GetRVal(const GRState* St, LVal LV, QualType T = QualType()) {
return StMgr->GetRVal(St->getStore(), LV, T);
}
diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h
index 4f16901972..d91dac1fe4 100644
--- a/include/clang/Analysis/PathSensitive/Store.h
+++ b/include/clang/Analysis/PathSensitive/Store.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVector.h"
#include <vector>
#include <iosfwd>
@@ -124,6 +125,14 @@ public:
virtual void print(Store store, std::ostream& Out,
const char* nl, const char *sep) = 0;
+ /// 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) = 0;
+
+ /// BindingAsString - Returns a string representing the given binding.
+ virtual std::string BindingAsString(store::Binding binding) = 0;
+
/// getExtent - Returns the size of the region in bits.
virtual store::RegionExtent getExtent(store::Region R) =0;
};
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index ace8f3fbb5..867028dc19 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -56,6 +56,14 @@ public:
const char* nl, const char *sep);
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);
};
} // end anonymous namespace
@@ -326,3 +334,29 @@ void BasicStoreManager::print(Store store, std::ostream& Out,
I.getData().print(Out);
}
}
+
+void
+BasicStoreManager::getBindings(llvm::SmallVectorImpl<store::Binding>& bindings,
+ Store store, SymbolID Sym) {
+
+ 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);
+ }
+ }
+}
+
+std::string BasicStoreManager::BindingAsString(store::Binding binding) {
+ // A binding is just an VarDecl*.
+ return ((VarDecl*) binding)->getName();
+}
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 16ce58f4ca..3ed4894fa1 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -2301,15 +2301,14 @@ PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<GRState>* N,
return P;
}
-static std::pair<ExplodedNode<GRState>*,VarDecl*>
-GetAllocationSite(ExplodedNode<GRState>* N, SymbolID Sym) {
+static std::pair<ExplodedNode<GRState>*,store::Binding>
+GetAllocationSite(GRStateManager* StateMgr, ExplodedNode<GRState>* N,
+ SymbolID Sym) {
+ // Find both first node that referred to the tracked symbol and the
+ // memory location that value was store to.
ExplodedNode<GRState>* Last = N;
-
- // Find the first node that referred to the tracked symbol. We also
- // try and find the first VarDecl the value was stored to.
-
- VarDecl* FirstDecl = 0;
+ store::Binding FirstBinding = 0;
while (N) {
const GRState* St = N->getState();
@@ -2317,35 +2316,27 @@ GetAllocationSite(ExplodedNode<GRState>* N, SymbolID Sym) {
if (!B.lookup(Sym))
break;
-
- VarDecl* VD = 0;
-
- // Determine if there is an LVal binding to the symbol.
- for (GRState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I) {
- if (!isa<lval::SymbolVal>(I->second) // Is the value a symbol?
- || cast<lval::SymbolVal>(I->second).getSymbol() != Sym)
- continue;
-
- if (VD) { // Multiple decls map to this symbol.
- VD = 0;
- break;
- }
-
- VD = I->first;
+
+ if (StateMgr) {
+ llvm::SmallVector<store::Binding, 5> Bindings;
+ StateMgr->getBindings(Bindings, St, Sym);
+
+ if (Bindings.size() == 1)
+ FirstBinding = Bindings[0];
}
- if (VD) FirstDecl = VD;
-
Last = N;
N = N->pred_empty() ? NULL : *(N->pred_begin());
}
- return std::make_pair(Last, FirstDecl);
+ return std::make_pair(Last, FirstBinding);
}
-PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
+PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& br,
ExplodedNode<GRState>* EndN) {
+ GRBugReporter& BR = cast<GRBugReporter>(br);
+
// Tell the BugReporter to report cases when the tracked symbol is
// assigned to different variables, etc.
cast<GRBugReporter>(BR).addNotableSymbol(Sym);
@@ -2360,8 +2351,10 @@ PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
// symbol appeared, and also get the first VarDecl that tracked object
// is stored to.
ExplodedNode<GRState>* AllocNode = 0;
- VarDecl* FirstDecl = 0;
- llvm::tie(AllocNode, FirstDecl) = GetAllocationSite(EndN, Sym);
+ store::Binding FirstBinding = 0;
+
+ llvm::tie(AllocNode, FirstBinding) =
+ GetAllocationSite(&BR.getStateManager(), EndN, Sym);
// Get the allocate site.
assert (AllocNode);
@@ -2413,9 +2406,9 @@ PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
os << "Object allocated on line " << AllocLine;
- if (FirstDecl)
- os << " and stored into '" << FirstDecl->getName() << '\'';
-
+ if (FirstBinding)
+ os << " and stored into '"
+ << BR.getStateManager().BindingAsString(FirstBinding) << '\'';
os << " is no longer referenced after this point and has a retain count of +"
<< RetCount << " (object leaked).";
@@ -2474,7 +2467,7 @@ bool Leak::isCached(BugReport& R) {
SymbolID Sym = static_cast<CFRefReport&>(R).getSymbol();
ExplodedNode<GRState>* AllocNode =
- GetAllocationSite(R.getEndNode(), Sym).first;
+ GetAllocationSite(0, R.getEndNode(), Sym).first;
if (!AllocNode)
return false;