forked from OSchip/llvm-project
[analyzer] ExplodedGraph printing fixes
Fixes a number of issues: - Global variables are not used for communication - Trait should be defined on a graph, not on a node - Defining the trait on a graph allows us to use a correct allocator, no longer crashing while printing trimmed graphs Differential Revision: https://reviews.llvm.org/D52183 llvm-svn: 342413
This commit is contained in:
parent
b1f9e4d285
commit
8639c5d565
|
@ -461,12 +461,15 @@ public:
|
|||
|
||||
namespace llvm {
|
||||
|
||||
template<> struct GraphTraits<clang::ento::ExplodedNode*> {
|
||||
template <> struct GraphTraits<clang::ento::ExplodedGraph *> {
|
||||
using GraphTy = clang::ento::ExplodedGraph *;
|
||||
using NodeRef = clang::ento::ExplodedNode *;
|
||||
using ChildIteratorType = clang::ento::ExplodedNode::succ_iterator;
|
||||
using nodes_iterator = llvm::df_iterator<NodeRef>;
|
||||
using nodes_iterator = llvm::df_iterator<GraphTy>;
|
||||
|
||||
static NodeRef getEntryNode(NodeRef N) { return N; }
|
||||
static NodeRef getEntryNode(const GraphTy G) {
|
||||
return *G->roots_begin();
|
||||
}
|
||||
|
||||
static ChildIteratorType child_begin(NodeRef N) {
|
||||
if (N->succ_size() == 1 && (*N->succ_begin())->isTrivial()) {
|
||||
|
@ -482,27 +485,14 @@ namespace llvm {
|
|||
return N->succ_end();
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_begin(NodeRef N) { return df_begin(N); }
|
||||
static nodes_iterator nodes_begin(const GraphTy G) {
|
||||
return df_begin(G);
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_end(NodeRef N) { return df_end(N); }
|
||||
static nodes_iterator nodes_end(const GraphTy G) {
|
||||
return df_end(G);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct GraphTraits<const clang::ento::ExplodedNode*> {
|
||||
using NodeRef = const clang::ento::ExplodedNode *;
|
||||
using ChildIteratorType = clang::ento::ExplodedNode::const_succ_iterator;
|
||||
using nodes_iterator = llvm::df_iterator<NodeRef>;
|
||||
|
||||
static NodeRef getEntryNode(NodeRef N) { return N; }
|
||||
|
||||
static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); }
|
||||
|
||||
static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); }
|
||||
|
||||
static nodes_iterator nodes_begin(NodeRef N) { return df_begin(N); }
|
||||
|
||||
static nodes_iterator nodes_end(NodeRef N) { return df_end(N); }
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
|
||||
|
|
|
@ -226,7 +226,7 @@ void Environment::print(raw_ostream &Out, const char *NL,
|
|||
|
||||
PrintingPolicy PP = Context.getPrintingPolicy();
|
||||
|
||||
Out << NL << NL << "Expressions by stack frame:" << NL;
|
||||
Out << NL << "Expressions by stack frame:" << NL;
|
||||
WithLC->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) {
|
||||
for (auto I : ExprBindings) {
|
||||
if (I.first.getLocationContext() != LC)
|
||||
|
|
|
@ -2947,35 +2947,37 @@ void ExprEngine::VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef NDEBUG
|
||||
static ExprEngine* GraphPrintCheckerState;
|
||||
static SourceManager* GraphPrintSourceManager;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template<>
|
||||
struct DOTGraphTraits<ExplodedNode*> : public DefaultDOTGraphTraits {
|
||||
struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
|
||||
DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
|
||||
|
||||
// FIXME: Since we do not cache error nodes in ExprEngine now, this does not
|
||||
// work.
|
||||
static std::string getNodeAttributes(const ExplodedNode *N, void*) {
|
||||
static std::string getNodeAttributes(const ExplodedNode *N,
|
||||
ExplodedGraph *G) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// De-duplicate some source location pretty-printing.
|
||||
static void printLocation(raw_ostream &Out, SourceLocation SLoc) {
|
||||
static void printLocation(raw_ostream &Out,
|
||||
SourceLocation SLoc,
|
||||
const SourceManager &SM,
|
||||
StringRef Postfix="\\l") {
|
||||
if (SLoc.isFileID()) {
|
||||
Out << "\\lline="
|
||||
<< GraphPrintSourceManager->getExpansionLineNumber(SLoc)
|
||||
<< SM.getExpansionLineNumber(SLoc)
|
||||
<< " col="
|
||||
<< GraphPrintSourceManager->getExpansionColumnNumber(SLoc)
|
||||
<< "\\l";
|
||||
<< SM.getExpansionColumnNumber(SLoc)
|
||||
<< Postfix;
|
||||
}
|
||||
}
|
||||
|
||||
static void dumpProgramPoint(ProgramPoint Loc,
|
||||
const ASTContext &Context,
|
||||
llvm::raw_string_ostream &Out) {
|
||||
const SourceManager &SM = Context.getSourceManager();
|
||||
switch (Loc.getKind()) {
|
||||
case ProgramPoint::BlockEntranceKind:
|
||||
Out << "Block Entrance: B"
|
||||
|
@ -3020,7 +3022,7 @@ struct DOTGraphTraits<ExplodedNode*> : public DefaultDOTGraphTraits {
|
|||
ImplicitCallPoint PC = Loc.castAs<ImplicitCallPoint>();
|
||||
Out << "PreCall: ";
|
||||
PC.getDecl()->print(Out, Context.getLangOpts());
|
||||
printLocation(Out, PC.getLocation());
|
||||
printLocation(Out, PC.getLocation(), SM);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3028,7 +3030,7 @@ struct DOTGraphTraits<ExplodedNode*> : public DefaultDOTGraphTraits {
|
|||
ImplicitCallPoint PC = Loc.castAs<ImplicitCallPoint>();
|
||||
Out << "PostCall: ";
|
||||
PC.getDecl()->print(Out, Context.getLangOpts());
|
||||
printLocation(Out, PC.getLocation());
|
||||
printLocation(Out, PC.getLocation(), SM);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3056,13 +3058,7 @@ struct DOTGraphTraits<ExplodedNode*> : public DefaultDOTGraphTraits {
|
|||
|
||||
Out << "\\|Terminator: ";
|
||||
E.getSrc()->printTerminator(Out, Context.getLangOpts());
|
||||
|
||||
if (SLoc.isFileID()) {
|
||||
Out << "\\lline="
|
||||
<< GraphPrintSourceManager->getExpansionLineNumber(SLoc)
|
||||
<< " col="
|
||||
<< GraphPrintSourceManager->getExpansionColumnNumber(SLoc);
|
||||
}
|
||||
printLocation(Out, SLoc, SM, /*Postfix=*/"");
|
||||
|
||||
if (isa<SwitchStmt>(T)) {
|
||||
const Stmt *Label = E.getDst()->getLabel();
|
||||
|
@ -3112,7 +3108,7 @@ struct DOTGraphTraits<ExplodedNode*> : public DefaultDOTGraphTraits {
|
|||
<< S->getID(Context) << " <" << (const void *)S << "> ";
|
||||
S->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(),
|
||||
/*Indentation=*/2, /*NewlineSymbol=*/"\\l");
|
||||
printLocation(Out, S->getBeginLoc());
|
||||
printLocation(Out, S->getBeginLoc(), SM, /*Postfix=*/"");
|
||||
|
||||
if (Loc.getAs<PreStmt>())
|
||||
Out << "\\lPreStmt\\l";
|
||||
|
@ -3134,7 +3130,7 @@ struct DOTGraphTraits<ExplodedNode*> : public DefaultDOTGraphTraits {
|
|||
return N->isTrivial();
|
||||
}
|
||||
|
||||
static std::string getNodeLabel(const ExplodedNode *N, void*){
|
||||
static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G){
|
||||
std::string sbuf;
|
||||
llvm::raw_string_ostream Out(sbuf);
|
||||
|
||||
|
@ -3167,11 +3163,7 @@ struct DOTGraphTraits<ExplodedNode*> : public DefaultDOTGraphTraits {
|
|||
|
||||
Out << "\\l\\|";
|
||||
|
||||
ExplodedGraph &Graph =
|
||||
static_cast<ExprEngine *>(State->getStateManager().getOwningEngine())
|
||||
->getGraph();
|
||||
|
||||
Out << "StateID: ST" << State->getID() << ", NodeID: N" << N->getID(&Graph)
|
||||
Out << "StateID: ST" << State->getID() << ", NodeID: N" << N->getID(G)
|
||||
<< " <" << (const void *)N << ">\\|";
|
||||
|
||||
bool SameAsAllPredecessors =
|
||||
|
@ -3205,32 +3197,20 @@ void ExprEngine::ViewGraph(bool trim) {
|
|||
}
|
||||
|
||||
ViewGraph(Src);
|
||||
}
|
||||
else {
|
||||
GraphPrintCheckerState = this;
|
||||
GraphPrintSourceManager = &getContext().getSourceManager();
|
||||
|
||||
llvm::ViewGraph(*G.roots_begin(), "ExprEngine");
|
||||
|
||||
GraphPrintCheckerState = nullptr;
|
||||
GraphPrintSourceManager = nullptr;
|
||||
} else {
|
||||
llvm::ViewGraph(&G, "ExprEngine");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ExprEngine::ViewGraph(ArrayRef<const ExplodedNode*> Nodes) {
|
||||
#ifndef NDEBUG
|
||||
GraphPrintCheckerState = this;
|
||||
GraphPrintSourceManager = &getContext().getSourceManager();
|
||||
|
||||
std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Nodes));
|
||||
|
||||
if (!TrimmedG.get())
|
||||
if (!TrimmedG.get()) {
|
||||
llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";
|
||||
else
|
||||
llvm::ViewGraph(*TrimmedG->roots_begin(), "TrimmedExprEngine");
|
||||
|
||||
GraphPrintCheckerState = nullptr;
|
||||
GraphPrintSourceManager = nullptr;
|
||||
} else {
|
||||
llvm::ViewGraph(TrimmedG.get(), "TrimmedExprEngine");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue