diff options
author | Jordy Rose <jediknil@belkadan.com> | 2011-08-28 19:11:56 +0000 |
---|---|---|
committer | Jordy Rose <jediknil@belkadan.com> | 2011-08-28 19:11:56 +0000 |
commit | dbd658e139b3e0bf084f75feaea8d844af9e319f (patch) | |
tree | b16a9239734bb69c9cbdb8010d4dc42032d2f08f /lib/StaticAnalyzer/Core/CFRefCount.cpp | |
parent | e2c8663ad2b110712401145b866072bb94108058 (diff) |
[analyzer] Introduce a new callback for checkers, printState, to be used for debug-printing the contents of a ProgramState.
Unlike the other callbacks, this one is a simple virtual method, since it is only to be used for debugging.
This new callback replaces the old ProgramState::Printer interface, and allows us to move the printing of refcount bindings from CFRefCount to RetainReleaseChecker.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138728 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/CFRefCount.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/CFRefCount.cpp | 117 |
1 files changed, 60 insertions, 57 deletions
diff --git a/lib/StaticAnalyzer/Core/CFRefCount.cpp b/lib/StaticAnalyzer/Core/CFRefCount.cpp index 7991071a54..a38c450148 100644 --- a/lib/StaticAnalyzer/Core/CFRefCount.cpp +++ b/lib/StaticAnalyzer/Core/CFRefCount.cpp @@ -255,7 +255,7 @@ public: void RefVal::print(raw_ostream &Out) const { if (!T.isNull()) - Out << "Tracked Type:" << T.getAsString() << '\n'; + Out << "Tracked " << T.getAsString() << '/'; switch (getKind()) { default: assert(false); @@ -1585,14 +1585,6 @@ namespace { class CFRefCount : public TransferFuncs { public: - class BindingsPrinter : public ProgramState::Printer { - public: - virtual void Print(raw_ostream &Out, - const ProgramState *state, - const char* nl, - const char* sep); - }; - const LangOptions& LOpts; const bool GCEnabled; @@ -1601,60 +1593,12 @@ public: : LOpts(lopts), GCEnabled(gcenabled) {} void RegisterChecks(ExprEngine &Eng); - - virtual void RegisterPrinters(std::vector<ProgramState::Printer*>& Printers) { - Printers.push_back(new BindingsPrinter()); - } const LangOptions& getLangOptions() const { return LOpts; } }; } // end anonymous namespace -static void PrintPool(raw_ostream &Out, - SymbolRef Sym, - const ProgramState *state) { - Out << ' '; - if (Sym) - Out << Sym->getSymbolID(); - 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(raw_ostream &Out, - const ProgramState *state, - const char* nl, const char* sep) { - - RefBindings B = state->get<RefBindings>(); - - if (!B.isEmpty()) - Out << sep << nl; - - for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) { - Out << (*I).first << " : "; - (*I).second.print(Out); - Out << nl; - } - - // Print the autorelease stack. - Out << sep << nl << "AR pool stack:"; - ARStack stack = state->get<AutoreleaseStack>(); - - 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; -} - //===----------------------------------------------------------------------===// // Error reporting. //===----------------------------------------------------------------------===// @@ -2543,6 +2487,9 @@ public: } } + void printState(raw_ostream &Out, const ProgramState *State, + const char *NL, const char *Sep) const; + void checkBind(SVal loc, SVal val, CheckerContext &C) const; void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const; void checkPostStmt(const CastExpr *CE, CheckerContext &C) const; @@ -3623,6 +3570,62 @@ void RetainReleaseChecker::checkDeadSymbols(SymbolReaper &SymReaper, } //===----------------------------------------------------------------------===// +// Debug printing of refcount bindings and autorelease pools. +//===----------------------------------------------------------------------===// + +static void PrintPool(raw_ostream &Out, SymbolRef Sym, + const ProgramState *State) { + Out << ' '; + if (Sym) + Out << Sym->getSymbolID(); + else + Out << "<pool>"; + Out << ":{"; + + // Get the contents of the pool. + if (const ARCounts *Cnts = State->get<AutoreleasePoolContents>(Sym)) + for (ARCounts::iterator I = Cnts->begin(), E = Cnts->end(); I != E; ++I) + Out << '(' << I.getKey() << ',' << I.getData() << ')'; + + Out << '}'; +} + +bool UsesAutorelease(const ProgramState *state) { + // A state uses autorelease if it allocated an autorelease pool or if it has + // objects in the caller's autorelease pool. + return !state->get<AutoreleaseStack>().isEmpty() || + state->get<AutoreleasePoolContents>(SymbolRef()); +} + +void RetainReleaseChecker::printState(raw_ostream &Out, + const ProgramState *State, + const char *NL, const char *Sep) const { + + RefBindings B = State->get<RefBindings>(); + + if (!B.isEmpty()) + Out << Sep << NL; + + for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) { + Out << I->first << " : "; + I->second.print(Out); + Out << NL; + } + + // Print the autorelease stack. + if (UsesAutorelease(State)) { + Out << Sep << NL << "AR pool stack:"; + ARStack Stack = State->get<AutoreleaseStack>(); + + 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; + } +} + +//===----------------------------------------------------------------------===// // Transfer function creation for external clients. //===----------------------------------------------------------------------===// |