r343239 - [analyzer] Highlight nodes which have error reports in them in red in exploded graph
George Karpenkov via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 27 10:26:41 PDT 2018
Author: george.karpenkov
Date: Thu Sep 27 10:26:41 2018
New Revision: 343239
URL: http://llvm.org/viewvc/llvm-project?rev=343239&view=rev
Log:
[analyzer] Highlight nodes which have error reports in them in red in exploded graph
Differential Revision: https://reviews.llvm.org/D52584
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=343239&r1=343238&r2=343239&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Thu Sep 27 10:26:41 2018
@@ -2953,49 +2953,89 @@ template<>
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,
- ExplodedGraph *G) {
- if (N->isSink())
- return "color=red";
- return {};
- }
-
- static bool isNodeHidden(const ExplodedNode *N) {
- return N->isTrivial();
+ static bool nodeHasBugReport(const ExplodedNode *N) {
+ BugReporter &BR = static_cast<ExprEngine *>(
+ N->getState()->getStateManager().getOwningEngine())->getBugReporter();
+
+ const auto EQClasses =
+ llvm::make_range(BR.EQClasses_begin(), BR.EQClasses_end());
+
+ for (const auto &EQ : EQClasses) {
+ for (const BugReport &Report : EQ) {
+ if (Report.getErrorNode() == N)
+ return true;
+ }
+ }
+ return false;
}
- static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G){
- std::string sbuf;
- llvm::raw_string_ostream Out(sbuf);
-
- // Find the first node which program point and tag has to be included in
- // the output.
+ /// \p PreCallback: callback before break.
+ /// \p PostCallback: callback after break.
+ /// \p Stop: stop iteration if returns {@code true}
+ /// \return Whether {@code Stop} ever returned {@code true}.
+ static bool traverseHiddenNodes(
+ const ExplodedNode *N,
+ llvm::function_ref<void(const ExplodedNode *)> PreCallback,
+ llvm::function_ref<void(const ExplodedNode *)> PostCallback,
+ llvm::function_ref<bool(const ExplodedNode *)> Stop) {
const ExplodedNode *FirstHiddenNode = N;
while (FirstHiddenNode->pred_size() == 1 &&
isNodeHidden(*FirstHiddenNode->pred_begin())) {
FirstHiddenNode = *FirstHiddenNode->pred_begin();
}
-
- ProgramStateRef State = N->getState();
-
- // Dump program point for all the previously skipped nodes.
const ExplodedNode *OtherNode = FirstHiddenNode;
while (true) {
- OtherNode->getLocation().print(/*CR=*/"\\l", Out);
-
- if (const ProgramPointTag *Tag = OtherNode->getLocation().getTag())
- Out << "\\lTag:" << Tag->getTagDescription();
+ if (Stop(OtherNode))
+ return true;
if (OtherNode == N)
break;
OtherNode = *OtherNode->succ_begin();
+ }
+ return false;
+ }
- Out << "\\l--------\\l";
+ static std::string getNodeAttributes(const ExplodedNode *N,
+ ExplodedGraph *G) {
+ SmallVector<StringRef, 10> Out;
+ auto Noop = [](const ExplodedNode*){};
+ if (traverseHiddenNodes(N, Noop, Noop, &nodeHasBugReport)) {
+ Out.push_back("style=filled");
+ Out.push_back("fillcolor=red");
}
+ if (traverseHiddenNodes(N, Noop, Noop,
+ [](const ExplodedNode *C) { return C->isSink(); }))
+ Out.push_back("color=blue");
+ return llvm::join(Out, ",");
+ }
+
+ static bool isNodeHidden(const ExplodedNode *N) {
+ return N->isTrivial();
+ }
+
+ static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G){
+ std::string sbuf;
+ llvm::raw_string_ostream Out(sbuf);
+
+ ProgramStateRef State = N->getState();
+
+ // Dump program point for all the previously skipped nodes.
+ traverseHiddenNodes(
+ N,
+ [&](const ExplodedNode *OtherNode) {
+ OtherNode->getLocation().print(/*CR=*/"\\l", Out);
+ if (const ProgramPointTag *Tag = OtherNode->getLocation().getTag())
+ Out << "\\lTag:" << Tag->getTagDescription();
+ if (N->isSink())
+ Out << "\\lNode is sink\\l";
+ if (nodeHasBugReport(N))
+ Out << "\\lBug report attached\\l";
+ },
+ [&](const ExplodedNode *OtherNode) { Out << "\\l--------\\l"; },
+ [&](const ExplodedNode *N) { return false; });
+
Out << "\\l\\|";
Out << "StateID: ST" << State->getID() << ", NodeID: N" << N->getID(G)
More information about the cfe-commits
mailing list