From 7037ab8f15950e594642adf77a56d299667debe7 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Fri, 20 Mar 2009 17:34:15 +0000 Subject: [PATCH] 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 --- lib/Analysis/CFRefCount.cpp | 55 ++++++++++++++++++++++++++++++++----- 1 file 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 }; } // end clang namespace +static SymbolRef GetCurrentAutoreleasePool(const GRState* state) { + ARStack stack = state->get(); + 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(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(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 << ""; + Out << ":{"; + + // Get the contents of the pool. + if (const ARCounts *cnts = state->get(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(); @@ -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(); - 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. -- 2.40.0