[analyzer] Add debug.DumpCalls, which prints out any CallEvents it sees.

This is probably not so useful yet because it is not path-sensitive, though
it does try to show inlining with indentation.

This also adds a dump() method to CallEvent, which should be useful for
debugging.

llvm-svn: 160030
This commit is contained in:
Jordan Rose 2012-07-10 23:56:23 +00:00
parent 6cd16c5152
commit 8889cf008d
4 changed files with 55 additions and 2 deletions

View File

@ -216,6 +216,10 @@ public:
return llvm::map_iterator(param_end(), get_type_fun(&ParmVarDecl::getType));
}
// For debugging purposes only
virtual void dump(raw_ostream &Out) const;
LLVM_ATTRIBUTE_USED void dump() const { dump(llvm::errs()); }
static bool classof(const CallEvent *) { return true; }
};

View File

@ -483,6 +483,10 @@ def TraversalDumper : Checker<"DumpTraversal">,
HelpText<"Print branch conditions as they are traversed by the engine">,
DescFile<"TraversalChecker.cpp">;
def CallDumper : Checker<"DumpCalls">,
HelpText<"Print calls as they are traversed by the engine">,
DescFile<"TraversalChecker.cpp">;
def AnalyzerStatsChecker : Checker<"Stats">,
HelpText<"Emit warnings with analyzer statistics">,
DescFile<"AnalyzerStatsChecker.cpp">;

View File

@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
//
// This checker prints branch statements to llvm::outs as they are encountered.
// This lets us see exactly how the ExprEngine is traversing the graph.
// These checkers print various aspects of the ExprEngine's traversal of the CFG
// as it builds the ExplodedGraph.
//
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
@ -16,6 +16,7 @@
#include "clang/AST/StmtObjC.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
using namespace clang;
@ -55,3 +56,29 @@ void TraversalDumper::checkEndPath(CheckerContext &C) const {
void ento::registerTraversalDumper(CheckerManager &mgr) {
mgr.registerChecker<TraversalDumper>();
}
//------------------------------------------------------------------------------
namespace {
class CallDumper : public Checker< check::PreCall > {
public:
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
};
}
void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
unsigned Indentation = 0;
for (const LocationContext *LC = C.getLocationContext()->getParent();
LC != 0; LC = LC->getParent())
++Indentation;
// It is mildly evil to print directly to llvm::outs() rather than emitting
// warnings, but this ensures things do not get filtered out by the rest of
// the static analyzer machinery.
llvm::outs().indent(Indentation);
Call.dump(llvm::outs());
}
void ento::registerCallDumper(CheckerManager &mgr) {
mgr.registerChecker<CallDumper>();
}

View File

@ -310,6 +310,24 @@ const FunctionDecl *SimpleCall::getDecl() const {
return getSVal(CE->getCallee()).getAsFunctionDecl();
}
void CallEvent::dump(raw_ostream &Out) const {
ASTContext &Ctx = State->getStateManager().getContext();
if (const Expr *E = getOriginExpr()) {
E->printPretty(Out, Ctx, 0, Ctx.getLangOpts());
Out << "\n";
return;
}
if (const Decl *D = getDecl()) {
Out << "Call to ";
D->print(Out, Ctx.getLangOpts());
return;
}
// FIXME: a string representation of the kind would be nice.
Out << "Unknown call (type " << getKind() << ")";
}
SVal CXXMemberCall::getCXXThisVal() const {
const Expr *Base = getOriginExpr()->getImplicitObjectArgument();