forked from OSchip/llvm-project
Colorize and condense CFG pretty-printing.
llvm-svn: 147203
This commit is contained in:
parent
3cef10814a
commit
72be32af88
|
@ -146,7 +146,7 @@ public:
|
|||
/// Return a version of the CFG without any edges pruned.
|
||||
CFG *getUnoptimizedCFG();
|
||||
|
||||
void dumpCFG();
|
||||
void dumpCFG(bool ShowColors);
|
||||
|
||||
/// \brief Returns true if we have built a CFG for this analysis context.
|
||||
/// Note that this doesn't correspond to whether or not a valid CFG exists, it
|
||||
|
|
|
@ -495,8 +495,9 @@ public:
|
|||
|
||||
CFG *getParent() const { return Parent; }
|
||||
|
||||
void dump(const CFG *cfg, const LangOptions &LO) const;
|
||||
void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO) const;
|
||||
void dump(const CFG *cfg, const LangOptions &LO, bool ShowColors = false) const;
|
||||
void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO,
|
||||
bool ShowColors) const;
|
||||
void printTerminator(raw_ostream &OS, const LangOptions &LO) const;
|
||||
|
||||
void addSuccessor(CFGBlock *Block, BumpVectorContext &C) {
|
||||
|
@ -755,8 +756,8 @@ public:
|
|||
//===--------------------------------------------------------------------===//
|
||||
|
||||
void viewCFG(const LangOptions &LO) const;
|
||||
void print(raw_ostream &OS, const LangOptions &LO) const;
|
||||
void dump(const LangOptions &LO) const;
|
||||
void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const;
|
||||
void dump(const LangOptions &LO, bool ShowColors) const;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Internal: constructors and data.
|
||||
|
|
|
@ -179,8 +179,8 @@ CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnaly
|
|||
return 0;
|
||||
}
|
||||
|
||||
void AnalysisDeclContext::dumpCFG() {
|
||||
getCFG()->dump(getASTContext().getLangOptions());
|
||||
void AnalysisDeclContext::dumpCFG(bool ShowColors) {
|
||||
getCFG()->dump(getASTContext().getLangOptions(), ShowColors);
|
||||
}
|
||||
|
||||
ParentMap &AnalysisDeclContext::getParentMap() {
|
||||
|
|
|
@ -3554,27 +3554,35 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper* Helper,
|
|||
|
||||
static void print_block(raw_ostream &OS, const CFG* cfg,
|
||||
const CFGBlock &B,
|
||||
StmtPrinterHelper* Helper, bool print_edges) {
|
||||
StmtPrinterHelper* Helper, bool print_edges,
|
||||
bool ShowColors) {
|
||||
|
||||
if (Helper) Helper->setBlockID(B.getBlockID());
|
||||
if (Helper)
|
||||
Helper->setBlockID(B.getBlockID());
|
||||
|
||||
// Print the header.
|
||||
OS << "\n [ B" << B.getBlockID();
|
||||
if (ShowColors)
|
||||
OS.changeColor(raw_ostream::YELLOW, true);
|
||||
|
||||
OS << "\n [B" << B.getBlockID();
|
||||
|
||||
if (&B == &cfg->getEntry())
|
||||
OS << " (ENTRY) ]\n";
|
||||
OS << " (ENTRY)]\n";
|
||||
else if (&B == &cfg->getExit())
|
||||
OS << " (EXIT) ]\n";
|
||||
OS << " (EXIT)]\n";
|
||||
else if (&B == cfg->getIndirectGotoBlock())
|
||||
OS << " (INDIRECT GOTO DISPATCH) ]\n";
|
||||
OS << " (INDIRECT GOTO DISPATCH)]\n";
|
||||
else
|
||||
OS << " ]\n";
|
||||
OS << "]\n";
|
||||
|
||||
if (ShowColors)
|
||||
OS.resetColor();
|
||||
|
||||
// Print the label of this block.
|
||||
if (Stmt *Label = const_cast<Stmt*>(B.getLabel())) {
|
||||
|
||||
if (print_edges)
|
||||
OS << " ";
|
||||
OS << " ";
|
||||
|
||||
if (LabelStmt *L = dyn_cast<LabelStmt>(Label))
|
||||
OS << L->getName();
|
||||
|
@ -3612,22 +3620,22 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
|
|||
|
||||
// Print the statement # in the basic block and the statement itself.
|
||||
if (print_edges)
|
||||
OS << " ";
|
||||
OS << " ";
|
||||
|
||||
OS << llvm::format("%3d", j) << ": ";
|
||||
|
||||
if (Helper)
|
||||
Helper->setStmtID(j);
|
||||
|
||||
print_elem(OS,Helper,*I);
|
||||
print_elem(OS, Helper, *I);
|
||||
}
|
||||
|
||||
// Print the terminator of this block.
|
||||
if (B.getTerminator()) {
|
||||
if (print_edges)
|
||||
OS << " ";
|
||||
if (ShowColors)
|
||||
OS.changeColor(raw_ostream::GREEN);
|
||||
|
||||
OS << " T: ";
|
||||
OS << " T: ";
|
||||
|
||||
if (Helper) Helper->setBlockID(-1);
|
||||
|
||||
|
@ -3635,54 +3643,86 @@ static void print_block(raw_ostream &OS, const CFG* cfg,
|
|||
PrintingPolicy(Helper->getLangOpts()));
|
||||
TPrinter.Visit(const_cast<Stmt*>(B.getTerminator().getStmt()));
|
||||
OS << '\n';
|
||||
|
||||
if (ShowColors)
|
||||
OS.resetColor();
|
||||
}
|
||||
|
||||
if (print_edges) {
|
||||
// Print the predecessors of this block.
|
||||
OS << " Predecessors (" << B.pred_size() << "):";
|
||||
unsigned i = 0;
|
||||
if (!B.pred_empty()) {
|
||||
const raw_ostream::Colors Color = raw_ostream::BLUE;
|
||||
if (ShowColors)
|
||||
OS.changeColor(Color);
|
||||
OS << " Preds " ;
|
||||
if (ShowColors)
|
||||
OS.resetColor();
|
||||
OS << '(' << B.pred_size() << "):";
|
||||
unsigned i = 0;
|
||||
|
||||
for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end();
|
||||
I != E; ++I, ++i) {
|
||||
if (ShowColors)
|
||||
OS.changeColor(Color);
|
||||
|
||||
for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end();
|
||||
I != E; ++I, ++i) {
|
||||
|
||||
if (i == 8 || (i-8) == 0)
|
||||
OS << "\n ";
|
||||
if (i == 8 || (i-8) == 0)
|
||||
OS << "\n ";
|
||||
|
||||
OS << " B" << (*I)->getBlockID();
|
||||
OS << " B" << (*I)->getBlockID();
|
||||
}
|
||||
|
||||
if (ShowColors)
|
||||
OS.resetColor();
|
||||
|
||||
OS << '\n';
|
||||
}
|
||||
|
||||
OS << '\n';
|
||||
|
||||
// Print the successors of this block.
|
||||
OS << " Successors (" << B.succ_size() << "):";
|
||||
i = 0;
|
||||
if (!B.succ_empty()) {
|
||||
const raw_ostream::Colors Color = raw_ostream::MAGENTA;
|
||||
if (ShowColors)
|
||||
OS.changeColor(Color);
|
||||
OS << " Succs ";
|
||||
if (ShowColors)
|
||||
OS.resetColor();
|
||||
OS << '(' << B.succ_size() << "):";
|
||||
unsigned i = 0;
|
||||
|
||||
for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end();
|
||||
I != E; ++I, ++i) {
|
||||
if (ShowColors)
|
||||
OS.changeColor(Color);
|
||||
|
||||
if (i == 8 || (i-8) % 10 == 0)
|
||||
OS << "\n ";
|
||||
for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end();
|
||||
I != E; ++I, ++i) {
|
||||
|
||||
if (*I)
|
||||
OS << " B" << (*I)->getBlockID();
|
||||
else
|
||||
OS << " NULL";
|
||||
if (i == 8 || (i-8) % 10 == 0)
|
||||
OS << "\n ";
|
||||
|
||||
if (*I)
|
||||
OS << " B" << (*I)->getBlockID();
|
||||
else
|
||||
OS << " NULL";
|
||||
}
|
||||
|
||||
if (ShowColors)
|
||||
OS.resetColor();
|
||||
OS << '\n';
|
||||
}
|
||||
|
||||
OS << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// dump - A simple pretty printer of a CFG that outputs to stderr.
|
||||
void CFG::dump(const LangOptions &LO) const { print(llvm::errs(), LO); }
|
||||
void CFG::dump(const LangOptions &LO, bool ShowColors) const {
|
||||
print(llvm::errs(), LO, ShowColors);
|
||||
}
|
||||
|
||||
/// print - A simple pretty printer of a CFG that outputs to an ostream.
|
||||
void CFG::print(raw_ostream &OS, const LangOptions &LO) const {
|
||||
void CFG::print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const {
|
||||
StmtPrinterHelper Helper(this, LO);
|
||||
|
||||
// Print the entry block.
|
||||
print_block(OS, this, getEntry(), &Helper, true);
|
||||
print_block(OS, this, getEntry(), &Helper, true, ShowColors);
|
||||
|
||||
// Iterate through the CFGBlocks and print them one by one.
|
||||
for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
|
||||
|
@ -3690,25 +3730,28 @@ void CFG::print(raw_ostream &OS, const LangOptions &LO) const {
|
|||
if (&(**I) == &getEntry() || &(**I) == &getExit())
|
||||
continue;
|
||||
|
||||
print_block(OS, this, **I, &Helper, true);
|
||||
print_block(OS, this, **I, &Helper, true, ShowColors);
|
||||
}
|
||||
|
||||
// Print the exit block.
|
||||
print_block(OS, this, getExit(), &Helper, true);
|
||||
print_block(OS, this, getExit(), &Helper, true, ShowColors);
|
||||
OS << '\n';
|
||||
OS.flush();
|
||||
}
|
||||
|
||||
/// dump - A simply pretty printer of a CFGBlock that outputs to stderr.
|
||||
void CFGBlock::dump(const CFG* cfg, const LangOptions &LO) const {
|
||||
print(llvm::errs(), cfg, LO);
|
||||
void CFGBlock::dump(const CFG* cfg, const LangOptions &LO,
|
||||
bool ShowColors) const {
|
||||
print(llvm::errs(), cfg, LO, ShowColors);
|
||||
}
|
||||
|
||||
/// print - A simple pretty printer of a CFGBlock that outputs to an ostream.
|
||||
/// Generally this will only be called from CFG::print.
|
||||
void CFGBlock::print(raw_ostream &OS, const CFG* cfg,
|
||||
const LangOptions &LO) const {
|
||||
const LangOptions &LO, bool ShowColors) const {
|
||||
StmtPrinterHelper Helper(cfg, LO);
|
||||
print_block(OS, cfg, *this, &Helper, true);
|
||||
print_block(OS, cfg, *this, &Helper, true, ShowColors);
|
||||
OS << '\n';
|
||||
}
|
||||
|
||||
/// printTerminator - A simple pretty printer of the terminator of a CFGBlock.
|
||||
|
@ -3805,7 +3848,7 @@ struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits {
|
|||
#ifndef NDEBUG
|
||||
std::string OutSStr;
|
||||
llvm::raw_string_ostream Out(OutSStr);
|
||||
print_block(Out,Graph, *Node, GraphHelper, false);
|
||||
print_block(Out,Graph, *Node, GraphHelper, false, false);
|
||||
std::string& OutStr = Out.str();
|
||||
|
||||
if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
|
||||
#include "clang/Analysis/Analyses/LiveVariables.h"
|
||||
#include "clang/Analysis/Analyses/Dominators.h"
|
||||
#include "llvm/Support/Process.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace ento;
|
||||
|
@ -92,7 +93,8 @@ public:
|
|||
void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
|
||||
BugReporter &BR) const {
|
||||
if (CFG *cfg = mgr.getCFG(D)) {
|
||||
cfg->dump(mgr.getLangOptions());
|
||||
cfg->dump(mgr.getLangOptions(),
|
||||
llvm::sys::Process::StandardErrHasColors());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -35,26 +35,22 @@ public:
|
|||
|
||||
TestArray::~TestArray() {}
|
||||
|
||||
// CHECK: [ B2 (ENTRY) ]
|
||||
// CHECK: Predecessors (0):
|
||||
// CHECK: Successors (1): B1
|
||||
// CHECK: [ B1 ]
|
||||
// CHECK: 1: this->a.~A() (Member object destructor)
|
||||
// CHECK: 2: ~B() (Base object destructor)
|
||||
// CHECK: 3: ~C() (Base object destructor)
|
||||
// CHECK: 4: ~A() (Base object destructor)
|
||||
// CHECK: Predecessors (1): B2
|
||||
// CHECK: Successors (1): B0
|
||||
// CHECK: [ B0 (EXIT) ]
|
||||
// CHECK: Predecessors (1): B1
|
||||
// CHECK: Successors (0):
|
||||
// CHECK: [ B2 (ENTRY) ]
|
||||
// CHECK: Predecessors (0):
|
||||
// CHECK: Successors (1): B1
|
||||
// CHECK: [ B1 ]
|
||||
// CHECK: 1: this->a.~A() (Member object destructor)
|
||||
// CHECK: Predecessors (1): B2
|
||||
// CHECK: Successors (1): B0
|
||||
// CHECK: [ B0 (EXIT) ]
|
||||
// CHECK: Predecessors (1): B1
|
||||
// CHECK: Successors (0):
|
||||
// CHECK: [B2 (ENTRY)]
|
||||
// CHECK: Succs (1): B1
|
||||
// CHECK: [B1]
|
||||
// CHECK: 1: this->a.~A() (Member object destructor)
|
||||
// CHECK: 2: ~B() (Base object destructor)
|
||||
// CHECK: 3: ~C() (Base object destructor)
|
||||
// CHECK: 4: ~A() (Base object destructor)
|
||||
// CHECK: Preds (1): B2
|
||||
// CHECK: Succs (1): B0
|
||||
// CHECK: [B0 (EXIT)]
|
||||
// CHECK: Preds (1): B1
|
||||
// CHECK: [B2 (ENTRY)]
|
||||
// CHECK: Succs (1): B1
|
||||
// CHECK: [B1]
|
||||
// CHECK: 1: this->a.~A() (Member object destructor)
|
||||
// CHECK: Preds (1): B2
|
||||
// CHECK: Succs (1): B0
|
||||
// CHECK: [B0 (EXIT)]
|
||||
// CHECK: Preds (1): B1
|
||||
|
|
|
@ -44,60 +44,55 @@ TestControlFlow::TestControlFlow(bool b)
|
|||
int v;
|
||||
}
|
||||
|
||||
// CHECK: [ B2 (ENTRY) ]
|
||||
// CHECK: Predecessors (0):
|
||||
// CHECK: Successors (1): B1
|
||||
// CHECK: [ B1 ]
|
||||
// CHECK: 1:
|
||||
// CHECK: 2: A([B1.1]) (Base initializer)
|
||||
// CHECK: 3:
|
||||
// CHECK: 4: C([B1.3]) (Base initializer)
|
||||
// CHECK: 5:
|
||||
// CHECK: 6: B([B1.5]) (Base initializer)
|
||||
// CHECK: 7:
|
||||
// CHECK: 8: A([B1.7]) (Base initializer)
|
||||
// CHECK: 9: /*implicit*/int()
|
||||
// CHECK: 10: i([B1.9]) (Member initializer)
|
||||
// CHECK: 11: this
|
||||
// CHECK: 12: [B1.11]->i
|
||||
// CHECK: 13: r([B1.12]) (Member initializer)
|
||||
// CHECK: 14:
|
||||
// CHECK: 15: A a;
|
||||
// CHECK: Predecessors (1): B2
|
||||
// CHECK: Successors (1): B0
|
||||
// CHECK: [ B0 (EXIT) ]
|
||||
// CHECK: Predecessors (1): B1
|
||||
// CHECK: Successors (0):
|
||||
// CHECK: [ B5 (ENTRY) ]
|
||||
// CHECK: Predecessors (0):
|
||||
// CHECK: Successors (1): B4
|
||||
// CHECK: [ B1 ]
|
||||
// CHECK: 1: [B4.4] ? [B2.1] : [B3.1]
|
||||
// CHECK: 2: y([B1.1]) (Member initializer)
|
||||
// CHECK: 3: this
|
||||
// CHECK: 4: [B1.3]->y
|
||||
// CHECK: 5: [B1.4]
|
||||
// CHECK: 6: z([B1.5]) (Member initializer)
|
||||
// CHECK: 7: int v;
|
||||
// CHECK: Predecessors (2): B2 B3
|
||||
// CHECK: Successors (1): B0
|
||||
// CHECK: [ B2 ]
|
||||
// CHECK: 1: 0
|
||||
// CHECK: Predecessors (1): B4
|
||||
// CHECK: Successors (1): B1
|
||||
// CHECK: [ B3 ]
|
||||
// CHECK: 1: 1
|
||||
// CHECK: Predecessors (1): B4
|
||||
// CHECK: Successors (1): B1
|
||||
// CHECK: [ B4 ]
|
||||
// CHECK: 1: 0
|
||||
// CHECK: 2: x([B4.1]) (Member initializer)
|
||||
// CHECK: 3: b
|
||||
// CHECK: 4: [B4.3]
|
||||
// CHECK: T: [B4.4] ? ... : ...
|
||||
// CHECK: Predecessors (1): B5
|
||||
// CHECK: Successors (2): B2 B3
|
||||
// CHECK: [ B0 (EXIT) ]
|
||||
// CHECK: Predecessors (1): B1
|
||||
// CHECK: Successors (0):
|
||||
|
||||
// CHECK: [B2 (ENTRY)]
|
||||
// CHECK: Succs (1): B1
|
||||
// CHECK: [B1]
|
||||
// CHECK: 1: (CXXConstructExpr, class A)
|
||||
// CHECK: 2: A([B1.1]) (Base initializer)
|
||||
// CHECK: 3: (CXXConstructExpr, class C)
|
||||
// CHECK: 4: C([B1.3]) (Base initializer)
|
||||
// CHECK: 5: (CXXConstructExpr, class B)
|
||||
// CHECK: 6: B([B1.5]) (Base initializer)
|
||||
// CHECK: 7: (CXXConstructExpr, class A)
|
||||
// CHECK: 8: A([B1.7]) (Base initializer)
|
||||
// CHECK: 9: /*implicit*/int()
|
||||
// CHECK: 10: i([B1.9]) (Member initializer)
|
||||
// CHECK: 11: this
|
||||
// CHECK: 12: [B1.11]->i
|
||||
// CHECK: 13: r([B1.12]) (Member initializer)
|
||||
// CHECK: 14: (CXXConstructExpr, class A)
|
||||
// CHECK: 15: A a;
|
||||
// CHECK: Preds (1): B2
|
||||
// CHECK: Succs (1): B0
|
||||
// CHECK: [B0 (EXIT)]
|
||||
// CHECK: Preds (1): B1
|
||||
// CHECK: [B5 (ENTRY)]
|
||||
// CHECK: Succs (1): B4
|
||||
// CHECK: [B1]
|
||||
// CHECK: 1: [B4.4] ? [B2.1] : [B3.1]
|
||||
// CHECK: 2: y([B1.1]) (Member initializer)
|
||||
// CHECK: 3: this
|
||||
// CHECK: 4: [B1.3]->y
|
||||
// CHECK: 5: [B1.4] (ImplicitCastExpr, LValueToRValue, int)
|
||||
// CHECK: 6: z([B1.5]) (Member initializer)
|
||||
// CHECK: 7: int v;
|
||||
// CHECK: Preds (2): B2 B3
|
||||
// CHECK: Succs (1): B0
|
||||
// CHECK: [B2]
|
||||
// CHECK: 1: 0
|
||||
// CHECK: Preds (1): B4
|
||||
// CHECK: Succs (1): B1
|
||||
// CHECK: [B3]
|
||||
// CHECK: 1: 1
|
||||
// CHECK: Preds (1): B4
|
||||
// CHECK: Succs (1): B1
|
||||
// CHECK: [B4]
|
||||
// CHECK: 1: 0
|
||||
// CHECK: 2: x([B4.1]) (Member initializer)
|
||||
// CHECK: 3: b
|
||||
// CHECK: 4: [B4.3] (ImplicitCastExpr, LValueToRValue, _Bool)
|
||||
// CHECK: T: [B4.4] ? ... : ...
|
||||
// CHECK: Preds (1): B5
|
||||
// CHECK: Succs (2): B2 B3
|
||||
// CHECK: [B0 (EXIT)]
|
||||
// CHECK: Preds (1): B1
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue