forked from OSchip/llvm-project
Allow two codepaths for PathDiagnostic generation. This patch mainly consists of
refactoring to make this possible (no functionality change). llvm-svn: 68141
This commit is contained in:
parent
b046ffb002
commit
4e81c3ccac
|
|
@ -42,7 +42,10 @@ public:
|
||||||
|
|
||||||
virtual void HandlePathDiagnostic(const PathDiagnostic* D) = 0;
|
virtual void HandlePathDiagnostic(const PathDiagnostic* D) = 0;
|
||||||
|
|
||||||
|
enum PathGenerationScheme { Minimal, Extensive };
|
||||||
|
virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
|
||||||
virtual bool supportsLogicalOpControlFlow() const { return false; }
|
virtual bool supportsLogicalOpControlFlow() const { return false; }
|
||||||
|
virtual bool supportsAllBlockEdges() const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
||||||
|
|
@ -102,16 +102,37 @@ static inline Stmt* GetCurrentOrNextStmt(const ExplodedNode<GRState>* N) {
|
||||||
// Diagnostics for 'execution continues on line XXX'.
|
// Diagnostics for 'execution continues on line XXX'.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
typedef llvm::DenseMap<const ExplodedNode<GRState>*,
|
||||||
|
const ExplodedNode<GRState>*> NodeBackMap;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
class VISIBILITY_HIDDEN NodeMapClosure : public BugReport::NodeResolver {
|
||||||
|
NodeBackMap& M;
|
||||||
|
public:
|
||||||
|
NodeMapClosure(NodeBackMap *m) : M(*m) {}
|
||||||
|
~NodeMapClosure() {}
|
||||||
|
|
||||||
|
const ExplodedNode<GRState>* getOriginalNode(const ExplodedNode<GRState>* N) {
|
||||||
|
NodeBackMap::iterator I = M.find(N);
|
||||||
|
return I == M.end() ? 0 : I->second;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class VISIBILITY_HIDDEN PathDiagnosticBuilder {
|
class VISIBILITY_HIDDEN PathDiagnosticBuilder {
|
||||||
|
GRBugReporter &BR;
|
||||||
SourceManager &SMgr;
|
SourceManager &SMgr;
|
||||||
|
ExplodedGraph<GRState> *ReportGraph;
|
||||||
|
BugReport *R;
|
||||||
const Decl& CodeDecl;
|
const Decl& CodeDecl;
|
||||||
PathDiagnosticClient *PDC;
|
PathDiagnosticClient *PDC;
|
||||||
llvm::OwningPtr<ParentMap> PM;
|
llvm::OwningPtr<ParentMap> PM;
|
||||||
|
NodeMapClosure NMC;
|
||||||
public:
|
public:
|
||||||
PathDiagnosticBuilder(SourceManager &smgr, const Decl& codedecl,
|
PathDiagnosticBuilder(GRBugReporter &br, ExplodedGraph<GRState> *reportGraph,
|
||||||
PathDiagnosticClient *pdc)
|
BugReport *r, NodeBackMap *Backmap,
|
||||||
: SMgr(smgr), CodeDecl(codedecl), PDC(pdc) {}
|
const Decl& codedecl, PathDiagnosticClient *pdc)
|
||||||
|
: BR(br), SMgr(BR.getSourceManager()), ReportGraph(reportGraph), R(r),
|
||||||
|
CodeDecl(codedecl), PDC(pdc), NMC(Backmap) {}
|
||||||
|
|
||||||
PathDiagnosticLocation ExecutionContinues(const ExplodedNode<GRState>* N);
|
PathDiagnosticLocation ExecutionContinues(const ExplodedNode<GRState>* N);
|
||||||
|
|
||||||
|
|
@ -123,8 +144,20 @@ public:
|
||||||
return *PM.get();
|
return *PM.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExplodedGraph<GRState>& getGraph() { return *ReportGraph; }
|
||||||
|
NodeMapClosure& getNodeMapClosure() { return NMC; }
|
||||||
|
ASTContext& getContext() { return BR.getContext(); }
|
||||||
|
SourceManager& getSourceManager() { return SMgr; }
|
||||||
|
BugReport& getReport() { return *R; }
|
||||||
|
GRBugReporter& getBugReporter() { return BR; }
|
||||||
|
GRStateManager& getStateManager() { return BR.getStateManager(); }
|
||||||
|
|
||||||
PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
|
PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
|
||||||
|
|
||||||
|
PathDiagnosticClient::PathGenerationScheme getGenerationScheme() const {
|
||||||
|
return PDC ? PDC->getGenerationScheme() : PathDiagnosticClient::Extensive;
|
||||||
|
}
|
||||||
|
|
||||||
bool supportsLogicalOpControlFlow() const {
|
bool supportsLogicalOpControlFlow() const {
|
||||||
return PDC ? PDC->supportsLogicalOpControlFlow() : true;
|
return PDC ? PDC->supportsLogicalOpControlFlow() : true;
|
||||||
}
|
}
|
||||||
|
|
@ -352,9 +385,6 @@ void BugReporter::FlushReports() {
|
||||||
// PathDiagnostics generation.
|
// PathDiagnostics generation.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
typedef llvm::DenseMap<const ExplodedNode<GRState>*,
|
|
||||||
const ExplodedNode<GRState>*> NodeBackMap;
|
|
||||||
|
|
||||||
static std::pair<std::pair<ExplodedGraph<GRState>*, NodeBackMap*>,
|
static std::pair<std::pair<ExplodedGraph<GRState>*, NodeBackMap*>,
|
||||||
std::pair<ExplodedNode<GRState>*, unsigned> >
|
std::pair<ExplodedNode<GRState>*, unsigned> >
|
||||||
MakeReportGraph(const ExplodedGraph<GRState>* G,
|
MakeReportGraph(const ExplodedGraph<GRState>* G,
|
||||||
|
|
@ -655,20 +685,6 @@ public:
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
namespace {
|
|
||||||
class VISIBILITY_HIDDEN NodeMapClosure : public BugReport::NodeResolver {
|
|
||||||
NodeBackMap& M;
|
|
||||||
public:
|
|
||||||
NodeMapClosure(NodeBackMap *m) : M(*m) {}
|
|
||||||
~NodeMapClosure() {}
|
|
||||||
|
|
||||||
const ExplodedNode<GRState>* getOriginalNode(const ExplodedNode<GRState>* N) {
|
|
||||||
NodeBackMap::iterator I = M.find(N);
|
|
||||||
return I == M.end() ? 0 : I->second;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
|
/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
|
||||||
/// and collapses PathDiagosticPieces that are expanded by macros.
|
/// and collapses PathDiagosticPieces that are expanded by macros.
|
||||||
static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) {
|
static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) {
|
||||||
|
|
@ -761,6 +777,10 @@ static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
|
||||||
|
PathDiagnosticBuilder &PDB,
|
||||||
|
const ExplodedNode<GRState> *N);
|
||||||
|
|
||||||
void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
|
void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
|
||||||
BugReportEquivClass& EQ) {
|
BugReportEquivClass& EQ) {
|
||||||
|
|
||||||
|
|
@ -798,15 +818,32 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
PathDiagnosticBuilder PDB(*this, ReportGraph.get(), R, BackMap.get(),
|
||||||
|
getStateManager().getCodeDecl(),
|
||||||
|
getPathDiagnosticClient());
|
||||||
|
|
||||||
|
switch (PDB.getGenerationScheme()) {
|
||||||
|
case PathDiagnosticClient::Extensive:
|
||||||
|
case PathDiagnosticClient::Minimal:
|
||||||
|
GenerateMinimalPathDiagnostic(PD, PDB, N);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// After constructing the full PathDiagnostic, do a pass over it to compact
|
||||||
|
// PathDiagnosticPieces that occur within a macro.
|
||||||
|
CompactPathDiagnostic(PD, PDB.getSourceManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
|
||||||
|
PathDiagnosticBuilder &PDB,
|
||||||
|
const ExplodedNode<GRState> *N) {
|
||||||
|
|
||||||
|
|
||||||
|
ASTContext& Ctx = PDB.getContext();
|
||||||
|
SourceManager& SMgr = PDB.getSourceManager();
|
||||||
const ExplodedNode<GRState>* NextNode = N->pred_empty()
|
const ExplodedNode<GRState>* NextNode = N->pred_empty()
|
||||||
? NULL : *(N->pred_begin());
|
? NULL : *(N->pred_begin());
|
||||||
|
|
||||||
ASTContext& Ctx = getContext();
|
|
||||||
SourceManager& SMgr = Ctx.getSourceManager();
|
|
||||||
NodeMapClosure NMC(BackMap.get());
|
|
||||||
PathDiagnosticBuilder PDB(SMgr, getStateManager().getCodeDecl(),
|
|
||||||
getPathDiagnosticClient());
|
|
||||||
|
|
||||||
while (NextNode) {
|
while (NextNode) {
|
||||||
N = NextNode;
|
N = NextNode;
|
||||||
NextNode = GetPredecessorNode(N);
|
NextNode = GetPredecessorNode(N);
|
||||||
|
|
@ -1070,21 +1107,20 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PathDiagnosticPiece* p = R->VisitNode(N, NextNode, *ReportGraph, *this,
|
if (PathDiagnosticPiece* p =
|
||||||
NMC))
|
PDB.getReport().VisitNode(N, NextNode, PDB.getGraph(),
|
||||||
|
PDB.getBugReporter(),
|
||||||
|
PDB.getNodeMapClosure())) {
|
||||||
PD.push_front(p);
|
PD.push_front(p);
|
||||||
|
}
|
||||||
|
|
||||||
if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
|
if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
|
||||||
// Scan the region bindings, and see if a "notable" symbol has a new
|
// Scan the region bindings, and see if a "notable" symbol has a new
|
||||||
// lval binding.
|
// lval binding.
|
||||||
ScanNotableSymbols SNS(N, PS->getStmt(), *this, PD);
|
ScanNotableSymbols SNS(N, PS->getStmt(), PDB.getBugReporter(), PD);
|
||||||
getStateManager().iterBindings(N->getState(), SNS);
|
PDB.getStateManager().iterBindings(N->getState(), SNS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// After constructing the full PathDiagnostic, do a pass over it to compact
|
|
||||||
// PathDiagnosticPieces that occur within a macro.
|
|
||||||
CompactPathDiagnostic(PD, getSourceManager());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,9 @@ namespace {
|
||||||
~PlistDiagnostics();
|
~PlistDiagnostics();
|
||||||
void HandlePathDiagnostic(const PathDiagnostic* D);
|
void HandlePathDiagnostic(const PathDiagnostic* D);
|
||||||
|
|
||||||
|
PathGenerationScheme getGenerationScheme() const { return Extensive; }
|
||||||
bool supportsLogicalOpControlFlow() const { return true; }
|
bool supportsLogicalOpControlFlow() const { return true; }
|
||||||
|
bool supportsAllBlockEdges() const { return true; }
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue