[analyzer] Improve debug output for PathDiagnosticPieces.

You can now dump a single PathDiagnosticPiece or PathDiagnosticLocation.

llvm-svn: 183367
This commit is contained in:
Jordan Rose 2013-06-06 01:57:19 +00:00
parent 5238eba7f5
commit d2f8a6a993
2 changed files with 90 additions and 57 deletions

View File

@ -285,6 +285,8 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const;
void dump() const;
/// \brief Given an exploded node, retrieve the statement that should be used
/// for the diagnostic location.
static const Stmt *getStmt(const ExplodedNode *N);
@ -401,6 +403,8 @@ public:
bool isLastInMainSourceFile() const {
return LastInMainSourceFile;
}
virtual void dump() const = 0;
};
@ -435,7 +439,7 @@ public:
PathDiagnosticLocation getLocation() const { return Pos; }
virtual void flattenLocations() { Pos.flatten(); }
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
static bool classof(const PathDiagnosticPiece *P) {
@ -529,6 +533,8 @@ public:
return "";
}
virtual void dump() const;
static inline bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Event;
}
@ -596,6 +602,8 @@ public:
static PathDiagnosticCallPiece *construct(PathPieces &pieces,
const Decl *caller);
virtual void dump() const;
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
static inline bool classof(const PathDiagnosticPiece *P) {
@ -663,7 +671,9 @@ public:
static inline bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == ControlFlow;
}
virtual void dump() const;
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
};
@ -687,7 +697,9 @@ public:
static inline bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Macro;
}
virtual void dump() const;
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
};

View File

@ -1886,60 +1886,6 @@ static bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL) {
typedef llvm::DenseSet<const PathDiagnosticCallPiece *>
OptimizedCallsSet;
void PathPieces::dump() const {
unsigned index = 0;
for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I ) {
llvm::errs() << "[" << index++ << "]";
switch ((*I)->getKind()) {
case PathDiagnosticPiece::Call:
llvm::errs() << " CALL\n--------------\n";
if (const Stmt *SLoc = getLocStmt((*I)->getLocation())) {
SLoc->dump();
} else {
const PathDiagnosticCallPiece *Call = cast<PathDiagnosticCallPiece>(*I);
if (const NamedDecl *ND = dyn_cast<NamedDecl>(Call->getCallee()))
llvm::errs() << *ND << "\n";
}
break;
case PathDiagnosticPiece::Event:
llvm::errs() << " EVENT\n--------------\n";
llvm::errs() << (*I)->getString() << "\n";
if (const Stmt *SLoc = getLocStmt((*I)->getLocation())) {
llvm::errs() << " ---- at ----\n";
SLoc->dump();
}
break;
case PathDiagnosticPiece::Macro:
llvm::errs() << " MACRO\n--------------\n";
// FIXME: print which macro is being invoked.
break;
case PathDiagnosticPiece::ControlFlow: {
const PathDiagnosticControlFlowPiece *CP =
cast<PathDiagnosticControlFlowPiece>(*I);
llvm::errs() << " CONTROL\n--------------\n";
if (const Stmt *s1Start = getLocStmt(CP->getStartLocation()))
s1Start->dump();
else
llvm::errs() << "NULL\n";
llvm::errs() << " ---- to ----\n";
if (const Stmt *s1End = getLocStmt(CP->getEndLocation()))
s1End->dump();
else
llvm::errs() << "NULL\n";
break;
}
}
llvm::errs() << "\n";
}
}
/// Adds synthetic edges from top-level statements to their subexpressions.
///
/// This avoids a "swoosh" effect, where an edge from a top-level statement A
@ -3448,3 +3394,78 @@ BugType *BugReporter::getBugTypeForName(StringRef name,
}
return BT;
}
void PathPieces::dump() const {
unsigned index = 0;
for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
llvm::errs() << "[" << index++ << "] ";
(*I)->dump();
llvm::errs() << "\n";
}
}
void PathDiagnosticCallPiece::dump() const {
llvm::errs() << "CALL\n--------------\n";
if (const Stmt *SLoc = getLocStmt(getLocation()))
SLoc->dump();
else if (const NamedDecl *ND = dyn_cast<NamedDecl>(getCallee()))
llvm::errs() << *ND << "\n";
else
getLocation().dump();
}
void PathDiagnosticEventPiece::dump() const {
llvm::errs() << "EVENT\n--------------\n";
llvm::errs() << getString() << "\n";
llvm::errs() << " ---- at ----\n";
getLocation().dump();
}
void PathDiagnosticControlFlowPiece::dump() const {
llvm::errs() << "CONTROL\n--------------\n";
getStartLocation().dump();
llvm::errs() << " ---- to ----\n";
getEndLocation().dump();
}
void PathDiagnosticMacroPiece::dump() const {
llvm::errs() << "MACRO\n--------------\n";
// FIXME: Print which macro is being invoked.
}
void PathDiagnosticLocation::dump() const {
if (!isValid()) {
llvm::errs() << "<INVALID>\n";
return;
}
switch (K) {
case RangeK:
// FIXME: actually print the range.
llvm::errs() << "<range>\n";
break;
case SingleLocK:
asLocation().dump();
llvm::errs() << "\n";
break;
case StmtK:
if (S)
S->dump();
else
llvm::errs() << "<NULL STMT>\n";
break;
case DeclK:
if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
llvm::errs() << *ND << "\n";
else if (isa<BlockDecl>(D))
// FIXME: Make this nicer.
llvm::errs() << "<block>\n";
else if (D)
llvm::errs() << "<unknown decl>\n";
else
llvm::errs() << "<NULL DECL>\n";
break;
}
}