aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/CFRefCount.cpp
diff options
context:
space:
mode:
authorJordy Rose <jediknil@belkadan.com>2011-08-28 19:11:56 +0000
committerJordy Rose <jediknil@belkadan.com>2011-08-28 19:11:56 +0000
commitdbd658e139b3e0bf084f75feaea8d844af9e319f (patch)
treeb16a9239734bb69c9cbdb8010d4dc42032d2f08f /lib/StaticAnalyzer/Core/CFRefCount.cpp
parente2c8663ad2b110712401145b866072bb94108058 (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.cpp117
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.
//===----------------------------------------------------------------------===//