aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2019-10-17 23:10:09 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2019-10-17 23:10:09 +0000
commitd0e3ed0b01ba7e55081e5b2593460b7b1486fd24 (patch)
tree38ef8ff2978259425fb6fc6a9cf218778cd7c4a0
parent40a1cfa0b13160d82f688daa7fbab9f249679617 (diff)
downloadclang-d0e3ed0b01ba7e55081e5b2593460b7b1486fd24.tar.gz
[analyzer] Assign truly stable identifiers to exploded nodes.
ExplodedGraph nodes will now have a numeric identifier stored in them which will keep track of the order in which the nodes were created and it will be fully deterministic both accross runs and across machines. This is extremely useful for debugging as it allows reliably setting conditional breakpoints by node IDs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@375186 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h11
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp3
-rw-r--r--lib/StaticAnalyzer/Core/ExplodedGraph.cpp14
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp18
-rw-r--r--test/Analysis/dump_egraph.c4
-rw-r--r--test/Analysis/exploded-graph-rewriter/checker_messages.dot9
-rw-r--r--test/Analysis/exploded-graph-rewriter/checker_messages_diff.dot44
-rw-r--r--test/Analysis/exploded-graph-rewriter/constraints.dot14
-rw-r--r--test/Analysis/exploded-graph-rewriter/constraints_diff.dot42
-rw-r--r--test/Analysis/exploded-graph-rewriter/edge.dot20
-rw-r--r--test/Analysis/exploded-graph-rewriter/environment.dot11
-rw-r--r--test/Analysis/exploded-graph-rewriter/environment_diff.dot42
-rw-r--r--test/Analysis/exploded-graph-rewriter/node_labels.dot43
-rw-r--r--test/Analysis/exploded-graph-rewriter/program_points.dot42
-rw-r--r--test/Analysis/exploded-graph-rewriter/store.dot15
-rw-r--r--test/Analysis/exploded-graph-rewriter/store_diff.dot37
-rw-r--r--test/Analysis/exploded-graph-rewriter/topology.dot14
-rw-r--r--test/Analysis/exploded-graph-rewriter/trimmers.dot40
-rwxr-xr-xutils/analyzer/exploded-graph-rewriter.py43
19 files changed, 305 insertions, 161 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index 9773a552bf..e87772c04b 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -131,10 +131,12 @@ class ExplodedNode : public llvm::FoldingSetNode {
/// Succs - The successors of this node.
NodeGroup Succs;
+ int64_t Id;
+
public:
explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state,
- bool IsSink)
- : Location(loc), State(std::move(state)), Succs(IsSink) {
+ int64_t Id, bool IsSink)
+ : Location(loc), State(std::move(state)), Succs(IsSink), Id(Id) {
assert(isSink() == IsSink);
}
@@ -258,7 +260,7 @@ public:
}
const_succ_range succs() const { return {Succs.begin(), Succs.end()}; }
- int64_t getID(ExplodedGraph *G) const;
+ int64_t getID() const { return Id; }
/// The node is trivial if it has only one successor, only one predecessor,
/// it's predecessor has only one successor,
@@ -324,7 +326,7 @@ protected:
BumpVectorContext BVC;
/// NumNodes - The number of nodes in the graph.
- unsigned NumNodes = 0;
+ int64_t NumNodes = 0;
/// A list of recently allocated nodes that can potentially be recycled.
NodeVector ChangedNodes;
@@ -358,6 +360,7 @@ public:
/// ExplodedGraph for further processing.
ExplodedNode *createUncachedNode(const ProgramPoint &L,
ProgramStateRef State,
+ int64_t Id,
bool IsSink = false);
std::unique_ptr<ExplodedGraph> MakeEmptyGraph() const {
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index f689d8e76a..1864bcef9b 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2566,7 +2566,8 @@ BugPathInfo *BugPathGetter::getNextBugPath() {
// Create the equivalent node in the new graph with the same state
// and location.
ExplodedNode *NewN = GNew->createUncachedNode(
- OrigN->getLocation(), OrigN->getState(), OrigN->isSink());
+ OrigN->getLocation(), OrigN->getState(),
+ OrigN->getID(), OrigN->isSink());
// Link up the new node with the previous node.
if (Succ)
diff --git a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index a8fa7ad2d9..c483849227 100644
--- a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -283,10 +283,6 @@ ExplodedNode * const *ExplodedNode::NodeGroup::end() const {
return Storage.getAddrOfPtr1() + 1;
}
-int64_t ExplodedNode::getID(ExplodedGraph *G) const {
- return G->getAllocator().identifyKnownAlignedObject<ExplodedNode>(this);
-}
-
bool ExplodedNode::isTrivial() const {
return pred_size() == 1 && succ_size() == 1 &&
getFirstPred()->getState()->getID() == getState()->getID() &&
@@ -417,14 +413,14 @@ ExplodedNode *ExplodedGraph::getNode(const ProgramPoint &L,
V = (NodeTy*) getAllocator().Allocate<NodeTy>();
}
- new (V) NodeTy(L, State, IsSink);
+ ++NumNodes;
+ new (V) NodeTy(L, State, NumNodes, IsSink);
if (ReclaimNodeInterval)
ChangedNodes.push_back(V);
// Insert the node into the node set and return it.
Nodes.InsertNode(V, InsertPos);
- ++NumNodes;
if (IsNew) *IsNew = true;
}
@@ -436,9 +432,10 @@ ExplodedNode *ExplodedGraph::getNode(const ProgramPoint &L,
ExplodedNode *ExplodedGraph::createUncachedNode(const ProgramPoint &L,
ProgramStateRef State,
+ int64_t Id,
bool IsSink) {
NodeTy *V = (NodeTy *) getAllocator().Allocate<NodeTy>();
- new (V) NodeTy(L, State, IsSink);
+ new (V) NodeTy(L, State, Id, IsSink);
return V;
}
@@ -498,7 +495,8 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks,
// Create the corresponding node in the new graph and record the mapping
// from the old node to the new node.
- ExplodedNode *NewN = G->createUncachedNode(N->getLocation(), N->State, N->isSink());
+ ExplodedNode *NewN = G->createUncachedNode(N->getLocation(), N->State,
+ N->getID(), N->isSink());
Pass2[N] = NewN;
// Also record the reverse mapping from the new node to the old node.
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 8629fd98db..ea1df1b0df 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -3061,16 +3061,7 @@ struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
const unsigned int Space = 1;
ProgramStateRef State = N->getState();
- auto Noop = [](const ExplodedNode*){};
- bool HasReport = traverseHiddenNodes(
- N, Noop, Noop, &nodeHasBugReport);
- bool IsSink = traverseHiddenNodes(
- N, Noop, Noop, [](const ExplodedNode *N) { return N->isSink(); });
-
- Out << "{ \"node_id\": " << N->getID(G) << ", \"pointer\": \""
- << (const void *)N << "\", \"state_id\": " << State->getID()
- << ", \"has_report\": " << (HasReport ? "true" : "false")
- << ", \"is_sink\": " << (IsSink ? "true" : "false")
+ Out << "{ \"state_id\": " << State->getID()
<< ",\\l";
Indent(Out, Space, IsDot) << "\"program_points\": [\\l";
@@ -3083,9 +3074,12 @@ struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
OtherNode->getLocation().printJson(Out, /*NL=*/"\\l");
Out << ", \"tag\": ";
if (const ProgramPointTag *Tag = OtherNode->getLocation().getTag())
- Out << '\"' << Tag->getTagDescription() << "\" }";
+ Out << '\"' << Tag->getTagDescription() << "\"";
else
- Out << "null }";
+ Out << "null";
+ Out << ", \"node_id\": " << OtherNode->getID() <<
+ ", \"is_sink\": " << OtherNode->isSink() <<
+ ", \"has_report\": " << nodeHasBugReport(OtherNode) << " }";
},
// Adds a comma and a new-line between each program point.
[&](const ExplodedNode *) { Out << ",\\l"; },
diff --git a/test/Analysis/dump_egraph.c b/test/Analysis/dump_egraph.c
index 99463da3e7..4ad04002c4 100644
--- a/test/Analysis/dump_egraph.c
+++ b/test/Analysis/dump_egraph.c
@@ -18,7 +18,7 @@ int foo() {
return *x + *y;
}
-// CHECK: \"program_points\": [\l&nbsp;&nbsp;&nbsp;&nbsp;\{ \"kind\": \"Edge\", \"src_id\": 2, \"dst_id\": 1, \"terminator\": null, \"term_kind\": null, \"tag\": null \}\l&nbsp;&nbsp;],\l&nbsp;&nbsp;\"program_state\": null
+// CHECK: \"program_points\": [\l&nbsp;&nbsp;&nbsp;&nbsp;\{ \"kind\": \"Edge\", \"src_id\": 2, \"dst_id\": 1, \"terminator\": null, \"term_kind\": null, \"tag\": null, \"node_id\": 1, \"is_sink\":0, \"has_report\": 0 \}\l&nbsp;&nbsp;],\l&nbsp;&nbsp;\"program_state\": null
// CHECK: \"program_points\": [\l&nbsp;&nbsp;&nbsp;&nbsp;\{ \"kind\": \"BlockEntrance\", \"block_id\": 1
@@ -27,4 +27,4 @@ int foo() {
// CHECK: \"pretty\": \"'\\\\x13'\"
-// CHECK: \"has_report\": true
+// CHECK: \"has_report\": 1
diff --git a/test/Analysis/exploded-graph-rewriter/checker_messages.dot b/test/Analysis/exploded-graph-rewriter/checker_messages.dot
index 84185db5af..2d054a8d48 100644
--- a/test/Analysis/exploded-graph-rewriter/checker_messages.dot
+++ b/test/Analysis/exploded-graph-rewriter/checker_messages.dot
@@ -14,7 +14,14 @@ Node0x1 [shape=record,label=
"has_report": false,
"is_sink": false,
"state_id": 2,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"store": null,
"constraints": null,
diff --git a/test/Analysis/exploded-graph-rewriter/checker_messages_diff.dot b/test/Analysis/exploded-graph-rewriter/checker_messages_diff.dot
index 2f0bcbd4e5..898f79600b 100644
--- a/test/Analysis/exploded-graph-rewriter/checker_messages_diff.dot
+++ b/test/Analysis/exploded-graph-rewriter/checker_messages_diff.dot
@@ -5,12 +5,15 @@
Node0x1 [shape=record,label=
"{
- { "node_id": 1,
- "pointer": "0x1",
- "has_report": false,
- "is_sink": false,
- "state_id": 2,
- "program_points": [],
+ { "state_id": 2,
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"environment": null,
"store": null,
@@ -59,12 +62,16 @@ Node0x1 -> Node0x4;
// CHECK-SAME: </tr>
Node0x4 [shape=record,label=
"{
- { "node_id": 4,
- "pointer": "0x4",
- "has_report": false,
- "is_sink": false,
+ {
"state_id": 5,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"environment": null,
"store": null,
@@ -88,12 +95,15 @@ Node0x4 -> Node0x6;
Node0x6 [shape=record,label=
"{
- { "node_id": 6,
- "pointer": "0x6",
- "has_report": false,
- "is_sink": false,
- "state_id": 7,
- "program_points": [],
+ { "state_id": 7,
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": null
}
\l}"];
diff --git a/test/Analysis/exploded-graph-rewriter/constraints.dot b/test/Analysis/exploded-graph-rewriter/constraints.dot
index 075df98ce9..f5ebcf1a60 100644
--- a/test/Analysis/exploded-graph-rewriter/constraints.dot
+++ b/test/Analysis/exploded-graph-rewriter/constraints.dot
@@ -12,12 +12,16 @@
// CHECK-SAME: </table></td></tr>
Node0x1 [shape=record,label=
"{
- { "node_id": 1,
- "pointer": "0x1",
- "has_report": false,
- "is_sink": false,
+ {
"state_id": 2,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"store": null,
"environment": null,
diff --git a/test/Analysis/exploded-graph-rewriter/constraints_diff.dot b/test/Analysis/exploded-graph-rewriter/constraints_diff.dot
index 00b2f1456f..53a87aa667 100644
--- a/test/Analysis/exploded-graph-rewriter/constraints_diff.dot
+++ b/test/Analysis/exploded-graph-rewriter/constraints_diff.dot
@@ -5,12 +5,16 @@
Node0x1 [shape=record,label=
"{
- { "node_id": 1,
- "pointer": "0x1",
- "has_report": false,
- "is_sink": false,
+ {
"state_id": 2,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"store": null,
"environment": null,
@@ -39,12 +43,16 @@ Node0x1 -> Node0x3;
// CHECK-SAME: </tr>
Node0x3 [shape=record,label=
"{
- { "node_id": 3,
- "pointer": "0x3",
- "has_report": false,
- "is_sink": false,
+ {
"state_id": 4,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"store": null,
"environment": null,
@@ -62,12 +70,16 @@ Node0x3 -> Node0x5;
Node0x5 [shape=record,label=
"{
- { "node_id": 5,
- "pointer": "0x5",
- "has_report": false,
- "is_sink": false,
+ {
"state_id": 6,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"store": null,
"environment": null,
diff --git a/test/Analysis/exploded-graph-rewriter/edge.dot b/test/Analysis/exploded-graph-rewriter/edge.dot
index 15e55612b8..3923f1f8ee 100644
--- a/test/Analysis/exploded-graph-rewriter/edge.dot
+++ b/test/Analysis/exploded-graph-rewriter/edge.dot
@@ -5,13 +5,25 @@
// UNSUPPORTED: system-windows
Node0x1 [shape=record,label=
- "{{ "node_id": 1, "pointer": "0x1", "has_report": false, "is_sink": false,
- "program_state": null, "program_points": []}\l}"];
+ "{{ "program_state": null, "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ]}\l}"];
// LIGHT: Node0x1 -> Node0x2;
// DARK: Node0x1 -> Node0x2 [color="white"];
Node0x1 -> Node0x2;
Node0x2 [shape=record,label=
- "{{ "node_id": 2, "pointer": "0x2", "has_report": false, "is_sink": false,
- "program_state": null, "program_points": []}\l}"];
+ "{{ "program_state": null, "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ]}\l}"];
diff --git a/test/Analysis/exploded-graph-rewriter/environment.dot b/test/Analysis/exploded-graph-rewriter/environment.dot
index 399484a7ee..733aae3036 100644
--- a/test/Analysis/exploded-graph-rewriter/environment.dot
+++ b/test/Analysis/exploded-graph-rewriter/environment.dot
@@ -11,7 +11,7 @@
// CHECK-SAME: </td>
// CHECK-SAME: <td align="left" colspan="2">
// CHECK-SAME: <font color="gray60">foo </font>
-// CHECK-SAME: (environment.cpp:<b>4</b>:<b>6</b>
+// CHECK-SAME: (environment.cpp:<b>4</b>:<b>6</b>
// CHECK-SAME: <font color="royalblue1">
// CHECK-SAME: (<i>spelling at </i> environment.h:<b>7</b>:<b>8</b>)
// CHECK-SAME: </font>)
@@ -36,7 +36,14 @@ Node0x1 [shape=record,label=
"has_report": false,
"is_sink": false,
"state_id": 2,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"store": null,
"constraints": null,
diff --git a/test/Analysis/exploded-graph-rewriter/environment_diff.dot b/test/Analysis/exploded-graph-rewriter/environment_diff.dot
index 475247bb98..05e8d4eef5 100644
--- a/test/Analysis/exploded-graph-rewriter/environment_diff.dot
+++ b/test/Analysis/exploded-graph-rewriter/environment_diff.dot
@@ -6,12 +6,16 @@
// No diffs on the first node, nothing to check.
Node0x1 [shape=record,label=
"{
- { "node_id": 1,
- "pointer": "0x1",
- "has_report": false,
- "is_sink": false,
+ {
"state_id": 2,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"store": null,
"constraints": null,
@@ -57,12 +61,16 @@ Node0x1 -> Node0x6;
// CHECK-SAME: </tr>
Node0x6 [shape=record,label=
"{
- { "node_id": 6,
- "pointer": "0x6",
- "has_report": false,
- "is_sink": false,
+ {
"state_id": 7,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"store": null,
"constraints": null,
@@ -102,12 +110,16 @@ Node0x6 -> Node0x9;
// CHECK-SAME: </tr>
Node0x9 [shape=record,label=
"{
- { "node_id": 9,
- "pointer": "0x9",
- "has_report": false,
- "is_sink": false,
+ {
"state_id": 7,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"store": null,
"constraints": null,
diff --git a/test/Analysis/exploded-graph-rewriter/node_labels.dot b/test/Analysis/exploded-graph-rewriter/node_labels.dot
index a434cd2307..a3d7420fed 100644
--- a/test/Analysis/exploded-graph-rewriter/node_labels.dot
+++ b/test/Analysis/exploded-graph-rewriter/node_labels.dot
@@ -15,30 +15,47 @@
// CHECK-SAME: <tr>
// LIGHT-SAME: <td bgcolor="gray70">
// DARK-SAME: <td bgcolor="gray20">
-// CHECK-SAME: <b>Node 1 (0x1) - State Unspecified</b>
+// CHECK-SAME: <b>State Unspecified</b>
// CHECK-SAME: </td>
// CHECK-SAME: </tr>
Node0x1 [shape=record,label=
"{
{ "node_id": 1, "pointer": "0x1", "has_report": false, "is_sink": false,
"program_state": null,
- "program_points": []
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ]
}
\l}"];
// CHECK: Node0x2 [
-// CHECK-SAME: <tr><td>
-// COLOR-SAME: <font color="red"><b>Bug Report Attached</b></font>
-// GRAY-SAME: <b>Bug Report Attached</b>
-// CHECK-SAME: </td></tr>
-// CHECK-SAME: <tr><td>
-// COLOR-SAME: <font color="cornflowerblue"><b>Sink Node</b></font>
-// GRAY-SAME: <b>Sink Node</b>
-// CHECK-SAME: </td></tr>
+// CHECK-SAME: <tr>
+// CHECK-SAME: <td colspan="3" align="left">
+// COLOR-SAME: <font color="red"><b>Bug Report Attached</b></font>
+// GRAY-SAME: <b>Bug Report Attached</b>
+// CHECK-SAME: </td>
+// CHECK-SAME: </tr>
+// CHECK-SAME: <tr>
+// CHECK-SAME: <td colspan="3" align="left">
+// COLOR-SAME: <font color="cornflowerblue"><b>Sink Node</b></font>
+// GRAY-SAME: <b>Sink Node</b>
+// CHECK-SAME: </td>
+// CHECK-SAME: </tr>
Node0x2 [shape=record,label=
"{
- { "node_id": 2, "pointer": "0x2", "has_report": true, "is_sink": true,
- "program_state": null,
- "program_points": []
+ { "program_state": null,
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 2,
+ "has_report": 1, "is_sink": 1
+ }
+ ]
}
\l}"];
diff --git a/test/Analysis/exploded-graph-rewriter/program_points.dot b/test/Analysis/exploded-graph-rewriter/program_points.dot
index c27c230ebf..c9492757c3 100644
--- a/test/Analysis/exploded-graph-rewriter/program_points.dot
+++ b/test/Analysis/exploded-graph-rewriter/program_points.dot
@@ -28,7 +28,7 @@
// CHECK-SAME: </table>
Node0x1 [shape=record,label=
"{
- { "node_id": 1, "pointer": "0x1", "has_report": false, "is_sink": false,
+ {
"program_state": null, "program_points": [
{
"kind": "Edge",
@@ -36,14 +36,20 @@ Node0x1 [shape=record,label=
"dst_id": 1,
"terminator": null,
"term_kind": null,
- "tag": null
+ "tag": null,
+ "node_id": 1,
+ "has_report": 0,
+ "is_sink": 0
},
{
"kind": "BlockEntrance",
"block_id": 1,
"terminator": null,
"term_kind": null,
- "tag": null
+ "tag": null,
+ "node_id": 2,
+ "has_report": 0,
+ "is_sink": 0
}
]}
\l}"];
@@ -72,10 +78,9 @@ Node0x1 [shape=record,label=
// CHECK-SAME: </td>
// CHECK-SAME: </tr>
// CHECK-SAME: </table>
-Node0x2 [shape=record,label=
+Node0x3 [shape=record,label=
"{
- { "node_id": 2, "pointer": "0x2", "has_report": false, "is_sink": false,
- "program_state": null, "program_points": [
+ { "program_state": null, "program_points": [
{
"kind": "Statement",
"stmt_kind": "DeclRefExpr",
@@ -88,7 +93,11 @@ Node0x2 [shape=record,label=
"line": 4,
"column": 5
},
- "tag": "ExprEngine : Clean Node"
+ "tag": "ExprEngine : Clean Node",
+ "node_id": 3,
+ "pointer": "0x3",
+ "has_report": 0,
+ "is_sink": 0
}
]}
\l}"];
@@ -97,9 +106,9 @@ Node0x2 [shape=record,label=
// CHECK-NEXT: <b>Program point:</b>
// CHECK-SAME: <td align="left">\{ ... \}</td>
-Node0x3 [shape=record,label=
+Node0x4 [shape=record,label=
"{
- { "node_id": 3, "pointer": "0x3", "has_report": false, "is_sink": false,
+ {
"program_state": null, "program_points": [
{
"kind": "Statement",
@@ -112,7 +121,10 @@ Node0x3 [shape=record,label=
"line": 7,
"column": 8
},
- "tag": "ExprEngine : Clean Node"
+ "tag": "ExprEngine : Clean Node",
+ "node_id": 4,
+ "has_report": 0,
+ "is_sink": 0
}
]}
\l}"];
@@ -143,10 +155,9 @@ Node0x3 [shape=record,label=
// CHECK-SAME: </td>
// CHECK-SAME: </tr>
// CHECK-SAME: </table>
-Node0x4 [shape=record,label=
+Node0x5 [shape=record,label=
"{
- { "node_id": 4, "pointer": "0x4", "has_report": false, "is_sink": false,
- "program_state": null, "program_points": [
+ { "program_state": null, "program_points": [
{
"kind": "Statement",
"stmt_kind": "ImplicitCastExpr",
@@ -160,7 +171,10 @@ Node0x4 [shape=record,label=
"line": 8,
"column": 9
},
- "tag": "ExprEngine : Clean Node"
+ "tag": "ExprEngine : Clean Node",
+ "node_id": 5,
+ "has_report": 0,
+ "is_sink": 0
}
]}
\l}"];
diff --git a/test/Analysis/exploded-graph-rewriter/store.dot b/test/Analysis/exploded-graph-rewriter/store.dot
index 7267dd43e8..c92901cbd7 100644
--- a/test/Analysis/exploded-graph-rewriter/store.dot
+++ b/test/Analysis/exploded-graph-rewriter/store.dot
@@ -23,12 +23,15 @@
// CHECK-SAME: </table>
Node0x1 [shape=record,label=
"{
- { "node_id": 1,
- "pointer": "0x1",
- "has_report": false,
- "is_sink": false,
- "state_id": 2,
- "program_points": [],
+ { "state_id": 2,
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"environment": null,
"constraints": null,
diff --git a/test/Analysis/exploded-graph-rewriter/store_diff.dot b/test/Analysis/exploded-graph-rewriter/store_diff.dot
index 94d1d8d9f1..8dd5fb44cd 100644
--- a/test/Analysis/exploded-graph-rewriter/store_diff.dot
+++ b/test/Analysis/exploded-graph-rewriter/store_diff.dot
@@ -10,7 +10,14 @@ Node0x1 [shape=record,label=
"has_report": false,
"is_sink": false,
"state_id": 2,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"environment": null,
"constraints": null,
@@ -55,12 +62,16 @@ Node0x1 -> Node0x4;
// CHECK-SAME: </tr>
Node0x4 [shape=record,label=
"{
- { "node_id": 4,
- "pointer": "0x4",
- "has_report": false,
- "is_sink": false,
+ {
"state_id": 5,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"environment": null,
"constraints": null,
@@ -91,12 +102,16 @@ Node0x4 -> Node0x6;
Node0x6 [shape=record,label=
"{
- { "node_id": 6,
- "pointer": "0x6",
- "has_report": false,
- "is_sink": false,
+ {
"state_id": 7,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": null
}
\l}"];
diff --git a/test/Analysis/exploded-graph-rewriter/topology.dot b/test/Analysis/exploded-graph-rewriter/topology.dot
index fa1b10f68b..b85115ebea 100644
--- a/test/Analysis/exploded-graph-rewriter/topology.dot
+++ b/test/Analysis/exploded-graph-rewriter/topology.dot
@@ -12,12 +12,16 @@
// TOPOLOGY-NOT: Checker State
Node0x1 [shape=record,label=
"{
- { "node_id": 1,
- "pointer": "0x1",
- "has_report": false,
- "is_sink": false,
+ {
"state_id": 2,
- "program_points": [],
+ "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ],
"program_state": {
"environment": null,
"constraints": null,
diff --git a/test/Analysis/exploded-graph-rewriter/trimmers.dot b/test/Analysis/exploded-graph-rewriter/trimmers.dot
index 8bdef649e0..2c441e02c7 100644
--- a/test/Analysis/exploded-graph-rewriter/trimmers.dot
+++ b/test/Analysis/exploded-graph-rewriter/trimmers.dot
@@ -17,20 +17,44 @@
// UNSUPPORTED: system-windows
Node0x1 [shape=record,label=
- "{{ "node_id": 1, "pointer": "0x1", "has_report": false, "is_sink": false,
- "program_state": null, "program_points": []}\l}"];
+ "{{ "program_state": null, "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 1,
+ "has_report": 0, "is_sink": 0
+ }
+ ]}\l}"];
Node0x2 [shape=record,label=
- "{{ "node_id": 2, "pointer": "0x2", "has_report": false, "is_sink": false,
- "program_state": null, "program_points": []}\l}"];
+ "{{ "program_state": null, "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 2,
+ "has_report": 0, "is_sink": 0
+ }
+ ]}\l}"];
Node0x3 [shape=record,label=
- "{{ "node_id": 3, "pointer": "0x3", "has_report": false, "is_sink": false,
- "program_state": null, "program_points": []}\l}"];
+ "{{ "program_state": null, "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 3,
+ "has_report": 0, "is_sink": 0
+ }
+ ]}\l}"];
Node0x4 [shape=record,label=
- "{{ "node_id": 4, "pointer": "0x4", "has_report": false, "is_sink": false,
- "program_state": null, "program_points": []}\l}"];
+ "{{ "program_state": null, "program_points": [
+ {
+ "kind": "BlockEntrance", "block_id": 1,
+ "terminator": null, "term_kind": null,
+ "tag": null, "node_id": 4,
+ "has_report": 0, "is_sink": 0
+ }
+ ]}\l}"];
Node0x1 -> Node0x2;
Node0x1 -> Node0x3;
diff --git a/utils/analyzer/exploded-graph-rewriter.py b/utils/analyzer/exploded-graph-rewriter.py
index 77da7392e3..79222bdbe9 100755
--- a/utils/analyzer/exploded-graph-rewriter.py
+++ b/utils/analyzer/exploded-graph-rewriter.py
@@ -67,6 +67,9 @@ class ProgramPoint(object):
super(ProgramPoint, self).__init__()
self.kind = json_pp['kind']
self.tag = json_pp['tag']
+ self.node_id = json_pp['node_id']
+ self.is_sink = bool(json_pp['is_sink'])
+ self.has_report = bool(json_pp['has_report'])
if self.kind == 'Edge':
self.src_id = json_pp['src_id']
self.dst_id = json_pp['dst_id']
@@ -309,11 +312,9 @@ class ExplodedNode(object):
def construct(self, node_id, json_node):
logging.debug('Adding ' + node_id)
- self.node_id = json_node['node_id']
- self.ptr = json_node['pointer']
- self.has_report = json_node['has_report']
- self.is_sink = json_node['is_sink']
+ self.ptr = node_id[4:]
self.points = [ProgramPoint(p) for p in json_node['program_points']]
+ self.node_id = self.points[-1].node_id
self.state = ProgramState(json_node['state_id'],
json_node['program_state']) \
if json_node['program_state'] is not None else None
@@ -488,12 +489,14 @@ class DotDumpVisitor(object):
else:
color = 'forestgreen'
+ self._dump('<tr><td align="left">%s.</td>' % p.node_id)
+
if p.kind == 'Statement':
# This avoids pretty-printing huge statements such as CompoundStmt.
# Such statements show up only at [Pre|Post]StmtPurgeDeadSymbols
skip_pretty = 'PurgeDeadSymbols' in p.stmt_point_kind
stmt_color = 'cyan3'
- self._dump('<tr><td align="left" width="0">%s:</td>'
+ self._dump('<td align="left" width="0">%s:</td>'
'<td align="left" width="0"><font color="%s">'
'%s</font> </td>'
'<td align="left"><i>S%s</i></td>'
@@ -506,30 +509,41 @@ class DotDumpVisitor(object):
self._short_pretty(p.pretty)
if not skip_pretty else ''))
elif p.kind == 'Edge':
- self._dump('<tr><td width="0"></td>'
+ self._dump('<td width="0"></td>'
'<td align="left" width="0">'
'<font color="%s">%s</font></td><td align="left">'
'[B%d] -\\> [B%d]</td></tr>'
% (color, 'BlockEdge', p.src_id, p.dst_id))
elif p.kind == 'BlockEntrance':
- self._dump('<tr><td width="0"></td>'
+ self._dump('<td width="0"></td>'
'<td align="left" width="0">'
'<font color="%s">%s</font></td>'
'<td align="left">[B%d]</td></tr>'
% (color, p.kind, p.block_id))
else:
# TODO: Print more stuff for other kinds of points.
- self._dump('<tr><td width="0"></td>'
+ self._dump('<td width="0"></td>'
'<td align="left" width="0" colspan="2">'
'<font color="%s">%s</font></td></tr>'
% (color, p.kind))
if p.tag is not None:
- self._dump('<tr><td width="0"></td>'
+ self._dump('<tr><td width="0"></td><td width="0"></td>'
'<td colspan="3" align="left">'
'<b>Tag: </b> <font color="crimson">'
'%s</font></td></tr>' % p.tag)
+ if p.has_report:
+ self._dump('<tr><td width="0"></td><td width="0"></td>'
+ '<td colspan="3" align="left">'
+ '<font color="red"><b>Bug Report Attached'
+ '</b></font></td></tr>')
+ if p.is_sink:
+ self._dump('<tr><td width="0"></td><td width="0"></td>'
+ '<td colspan="3" align="left">'
+ '<font color="cornflowerblue"><b>Sink Node'
+ '</b></font></td></tr>')
+
def visit_environment(self, e, prev_e=None):
self._dump('<table border="0">')
@@ -786,17 +800,10 @@ class DotDumpVisitor(object):
self._dump('color="white",fontcolor="gray80",')
self._dump('label=<<table border="0">')
- self._dump('<tr><td bgcolor="%s"><b>Node %d (%s) - '
- 'State %s</b></td></tr>'
+ self._dump('<tr><td bgcolor="%s"><b>State %s</b></td></tr>'
% ("gray20" if self._dark_mode else "gray70",
- node.node_id, node.ptr, node.state.state_id
+ node.state.state_id
if node.state is not None else 'Unspecified'))
- if node.has_report:
- self._dump('<tr><td><font color="red"><b>Bug Report Attached'
- '</b></font></td></tr>')
- if node.is_sink:
- self._dump('<tr><td><font color="cornflowerblue"><b>Sink Node'
- '</b></font></td></tr>')
if not self._topo_mode:
self._dump('<tr><td align="left" width="0">')
if len(node.points) > 1: