forked from OSchip/llvm-project
[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. llvm-svn: 375186
This commit is contained in:
parent
d325196f19
commit
14e9eb3d7c
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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"; },
|
||||
|
|
|
@ -18,7 +18,7 @@ int foo() {
|
|||
return *x + *y;
|
||||
}
|
||||
|
||||
// CHECK: \"program_points\": [\l \{ \"kind\": \"Edge\", \"src_id\": 2, \"dst_id\": 1, \"terminator\": null, \"term_kind\": null, \"tag\": null \}\l ],\l \"program_state\": null
|
||||
// CHECK: \"program_points\": [\l \{ \"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 ],\l \"program_state\": null
|
||||
|
||||
// CHECK: \"program_points\": [\l \{ \"kind\": \"BlockEntrance\", \"block_id\": 1
|
||||
|
||||
|
@ -27,4 +27,4 @@ int foo() {
|
|||
|
||||
// CHECK: \"pretty\": \"'\\\\x13'\"
|
||||
|
||||
// CHECK: \"has_report\": true
|
||||
// CHECK: \"has_report\": 1
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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}"];
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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}"];
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>
|
||||
// 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></tr>
|
||||
// CHECK-SAME: <tr><td>
|
||||
// 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></tr>
|
||||
// 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}"];
|
||||
|
|
|
@ -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}"];
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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}"];
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue