aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/CFRefCount.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-03-20 17:34:15 +0000
committerTed Kremenek <kremenek@apple.com>2009-03-20 17:34:15 +0000
commit7037ab8f15950e594642adf77a56d299667debe7 (patch)
treed4c75d18a20e9181ef87344e4c1559607a05172c /lib/Analysis/CFRefCount.cpp
parentdef1a888f999725dba7184e4fae7b94f8978032f (diff)
retain/release checker: Tracking autorelease counts for objects. We're still not
completely there with accurately modeling autorelease pools. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67384 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/CFRefCount.cpp')
-rw-r--r--lib/Analysis/CFRefCount.cpp55
1 files changed, 48 insertions, 7 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 8b3ad8ddab..be1d794252 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -1440,6 +1440,28 @@ template<> struct GRStateTrait<AutoreleasePoolContents>
};
} // end clang namespace
+static SymbolRef GetCurrentAutoreleasePool(const GRState* state) {
+ ARStack stack = state->get<AutoreleaseStack>();
+ return stack.isEmpty() ? SymbolRef() : stack.getHead();
+}
+
+static GRStateRef SendAutorelease(GRStateRef state, ARCounts::Factory &F,
+ SymbolRef sym) {
+
+ SymbolRef pool = GetCurrentAutoreleasePool(state);
+ const ARCounts *cnts = state.get<AutoreleasePoolContents>(pool);
+ ARCounts newCnts(0);
+
+ if (cnts) {
+ const unsigned *cnt = (*cnts).lookup(sym);
+ newCnts = F.Add(*cnts, sym, cnt ? *cnt + 1 : 1);
+ }
+ else
+ newCnts = F.Add(F.GetEmptyMap(), sym, 1);
+
+ return state.set<AutoreleasePoolContents>(pool, newCnts);
+}
+
//===----------------------------------------------------------------------===//
// Transfer functions.
//===----------------------------------------------------------------------===//
@@ -1567,9 +1589,26 @@ public:
} // end anonymous namespace
+static void PrintPool(std::ostream &Out, SymbolRef Sym, const GRState *state) {
+ Out << ' ';
+ if (Sym.isValid())
+ Out << Sym;
+ else
+ Out << "<pool>";
+ Out << ":{";
+
+ // Get the contents of the pool.
+ if (const ARCounts *cnts = state->get<AutoreleasePoolContents>(Sym))
+ for (ARCounts::iterator J=cnts->begin(), EJ=cnts->end(); J != EJ; ++J)
+ Out << '(' << J.getKey() << ',' << J.getData() << ')';
+
+ Out << '}';
+}
void CFRefCount::BindingsPrinter::Print(std::ostream& Out, const GRState* state,
const char* nl, const char* sep) {
+
+
RefBindings B = state->get<RefBindings>();
@@ -1583,15 +1622,14 @@ void CFRefCount::BindingsPrinter::Print(std::ostream& Out, const GRState* state,
}
// Print the autorelease stack.
+ Out << sep << nl << "AR pool stack:";
ARStack stack = state->get<AutoreleaseStack>();
- if (!stack.isEmpty()) {
- Out << sep << nl << "AR pool stack:";
- for (ARStack::iterator I=stack.begin(), E=stack.end(); I!=E; ++I)
- Out << ' ' << (*I);
-
- Out << nl;
- }
+ PrintPool(Out, SymbolRef(), state); // Print the caller's pool.
+ for (ARStack::iterator I=stack.begin(), E=stack.end(); I!=E; ++I)
+ PrintPool(Out, *I, state);
+
+ Out << nl;
}
static inline ArgEffect GetArgE(RetainSummary* Summ, unsigned idx) {
@@ -2230,6 +2268,9 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
case Autorelease:
if (isGCEnabled())
return state;
+
+ // Update the autorelease counts.
+ state = SendAutorelease(state, ARCountFactory, sym);
// Fall-through.