summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2018-09-27 17:26:41 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2018-09-27 17:26:41 +0000
commit2b7682d1b4ffa0e659cd178a5539c5d00eaf0cef (patch)
tree30c1a274be16b1258643261b47e04217fbe8a428 /clang/lib
parent86c7b07ecd3e9f54d7e88832541cd560daa3eef6 (diff)
downloadbcm5719-llvm-2b7682d1b4ffa0e659cd178a5539c5d00eaf0cef.tar.gz
bcm5719-llvm-2b7682d1b4ffa0e659cd178a5539c5d00eaf0cef.zip
[analyzer] Highlight nodes which have error reports in them in red in exploded graph
Differential Revision: https://reviews.llvm.org/D52584 llvm-svn: 343239
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp90
1 files changed, 65 insertions, 25 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 046ff9bd485..6fc862857ec 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -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 nodeHasBugReport(const ExplodedNode *N) {
+ BugReporter &BR = static_cast<ExprEngine *>(
+ N->getState()->getStateManager().getOwningEngine())->getBugReporter();
- static bool isNodeHidden(const ExplodedNode *N) {
- return N->isTrivial();
- }
+ const auto EQClasses =
+ llvm::make_range(BR.EQClasses_begin(), BR.EQClasses_end());
- static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G){
- std::string sbuf;
- llvm::raw_string_ostream Out(sbuf);
+ for (const auto &EQ : EQClasses) {
+ for (const BugReport &Report : EQ) {
+ if (Report.getErrorNode() == N)
+ return true;
+ }
+ }
+ return false;
+ }
- // 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)
OpenPOWER on IntegriCloud