aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/CFRefCount.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2011-08-12 23:04:46 +0000
committerTed Kremenek <kremenek@apple.com>2011-08-12 23:04:46 +0000
commitca804539d908d3a0e8c72a0df5f1f571d29490bb (patch)
tree1c94c42841ae275c45b74b27fb8831fab62b4e7f /lib/StaticAnalyzer/Core/CFRefCount.cpp
parent79c9c75737cb22fd74d186999eccc10672eef8c0 (diff)
[analyzer] change "tag" in ProgramPoint from "void*" to a ProgramPointTag*.
Having a notion of an actual ProgramPointTag will aid in introspection of the analyzer's behavior. For example, the GraphViz output of the analyzer will pretty-print the tags in a useful manner. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@137529 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/CFRefCount.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/CFRefCount.cpp42
1 files changed, 31 insertions, 11 deletions
diff --git a/lib/StaticAnalyzer/Core/CFRefCount.cpp b/lib/StaticAnalyzer/Core/CFRefCount.cpp
index ad809e7649..46aacd473f 100644
--- a/lib/StaticAnalyzer/Core/CFRefCount.cpp
+++ b/lib/StaticAnalyzer/Core/CFRefCount.cpp
@@ -88,11 +88,11 @@ namespace {
class GenericNodeBuilderRefCount {
StmtNodeBuilder *SNB;
const Stmt *S;
- const void *tag;
+ const ProgramPointTag *tag;
EndOfFunctionNodeBuilder *ENB;
public:
GenericNodeBuilderRefCount(StmtNodeBuilder &snb, const Stmt *s,
- const void *t)
+ const ProgramPointTag *t)
: SNB(&snb), S(s), tag(t), ENB(0) {}
GenericNodeBuilderRefCount(EndOfFunctionNodeBuilder &enb)
@@ -1671,9 +1671,11 @@ public:
BugType *overAutorelease;
BugType *returnNotOwnedForOwned;
BugReporter *BR;
+
+ llvm::DenseMap<SymbolRef, const SimpleProgramPointTag*> DeadSymbolTags;
- const GRState * Update(const GRState * state, SymbolRef sym, RefVal V, ArgEffect E,
- RefVal::Kind& hasErr);
+ const GRState * Update(const GRState * state, SymbolRef sym, RefVal V,
+ ArgEffect E, RefVal::Kind& hasErr);
void ProcessNonLeakError(ExplodedNodeSet& Dst,
StmtNodeBuilder& Builder,
@@ -1699,7 +1701,11 @@ public:
leakWithinFunction(0), leakAtReturn(0), overAutorelease(0),
returnNotOwnedForOwned(0), BR(0) {}
- virtual ~CFRefCount() {}
+ virtual ~CFRefCount() {
+ for (llvm::DenseMap<SymbolRef, const SimpleProgramPointTag *>::iterator
+ it = DeadSymbolTags.begin(), ei = DeadSymbolTags.end(); it != ei; ++it)
+ delete it->second;
+ }
void RegisterChecks(ExprEngine &Eng);
@@ -1757,6 +1763,8 @@ public:
const GRState* state,
SymbolReaper& SymReaper);
+ const ProgramPointTag *getDeadSymbolTag(SymbolRef sym);
+
std::pair<ExplodedNode*, const GRState *>
HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilderRefCount Bd,
ExplodedNode* Pred, ExprEngine &Eng,
@@ -2968,7 +2976,7 @@ void CFRefCount::evalReturn(ExplodedNodeSet& Dst,
return;
// Update the autorelease counts.
- static unsigned autoreleasetag = 0;
+ static SimpleProgramPointTag autoreleasetag("CFRefCount : Autorelease");
GenericNodeBuilderRefCount Bd(Builder, S, &autoreleasetag);
bool stop = false;
llvm::tie(Pred, state) = HandleAutoreleaseCounts(state , Bd, Pred, Eng, Sym,
@@ -3031,7 +3039,8 @@ void CFRefCount::evalReturnWithRetEffect(ExplodedNodeSet &Dst,
if (hasError) {
// Generate an error node.
- static int ReturnOwnLeakTag = 0;
+ static SimpleProgramPointTag
+ ReturnOwnLeakTag("CFRefCount : ReturnsOwnLeak");
state = state->set<RefBindings>(Sym, X);
ExplodedNode *N =
Builder.generateNode(PostStmt(S, Pred->getLocationContext(),
@@ -3051,8 +3060,8 @@ void CFRefCount::evalReturnWithRetEffect(ExplodedNodeSet &Dst,
if (RE.isOwned()) {
// Trying to return a not owned object to a caller expecting an
// owned object.
-
- static int ReturnNotOwnedForOwnedTag = 0;
+ static SimpleProgramPointTag
+ ReturnNotOwnedForOwnedTag("CFRefCount : ReturnNotOwnedForOwned");
state = state->set<RefBindings>(Sym, X ^ RefVal::ErrorReturnedNotOwned);
if (ExplodedNode *N =
Builder.generateNode(PostStmt(S, Pred->getLocationContext(),
@@ -3375,6 +3384,17 @@ void CFRefCount::evalEndPath(ExprEngine& Eng,
ProcessLeaks(state, Leaked, Bd, Eng, Pred);
}
+const ProgramPointTag *CFRefCount::getDeadSymbolTag(SymbolRef sym) {
+ const SimpleProgramPointTag *&tag = DeadSymbolTags[sym];
+ if (!tag) {
+ llvm::SmallString<128> buf;
+ llvm::raw_svector_ostream out(buf);
+ out << "CFRefCount : Dead Symbol : " << sym->getSymbolID();
+ tag = new SimpleProgramPointTag(out.str());
+ }
+ return tag;
+}
+
void CFRefCount::evalDeadSymbols(ExplodedNodeSet& Dst,
ExprEngine& Eng,
StmtNodeBuilder& Builder,
@@ -3391,7 +3411,7 @@ void CFRefCount::evalDeadSymbols(ExplodedNodeSet& Dst,
if (const RefVal* T = B.lookup(Sym)){
// Use the symbol as the tag.
// FIXME: This might not be as unique as we would like.
- GenericNodeBuilderRefCount Bd(Builder, S, Sym);
+ GenericNodeBuilderRefCount Bd(Builder, S, getDeadSymbolTag(Sym));
bool stop = false;
llvm::tie(Pred, state) = HandleAutoreleaseCounts(state, Bd, Pred, Eng,
Sym, *T, stop);
@@ -3409,7 +3429,7 @@ void CFRefCount::evalDeadSymbols(ExplodedNodeSet& Dst,
state = HandleSymbolDeath(state, *I, *T, Leaked);
}
- static unsigned LeakPPTag = 0;
+ static SimpleProgramPointTag LeakPPTag("CFRefCount : Leak");
{
GenericNodeBuilderRefCount Bd(Builder, S, &LeakPPTag);
Pred = ProcessLeaks(state, Leaked, Bd, Eng, Pred);