[analyzer] Display cast kinds in program point dumps.

Because cast expressions have their own hierarchy, it's extremely useful
to have some information about what kind of casts are we dealing with.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@375185 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/ProgramPoint.cpp b/lib/Analysis/ProgramPoint.cpp
index 97e9096..0783fbe 100644
--- a/lib/Analysis/ProgramPoint.cpp
+++ b/lib/Analysis/ProgramPoint.cpp
@@ -188,7 +188,11 @@
 
     Out << "Statement\", \"stmt_kind\": \"" << S->getStmtClassName()
         << "\", \"stmt_id\": " << S->getID(Context)
-        << ", \"pointer\": \"" << (const void *)S << "\", \"pretty\": ";
+        << ", \"pointer\": \"" << (const void *)S << "\", ";
+    if (const auto *CS = dyn_cast<CastExpr>(S))
+      Out << "\"cast_kind\": \"" << CS->getCastKindName() << "\", ";
+
+    Out << "\"pretty\": ";
 
     S->printJson(Out, nullptr, PP, AddQuotes);
 
diff --git a/test/Analysis/exploded-graph-rewriter/program_points.dot b/test/Analysis/exploded-graph-rewriter/program_points.dot
index 2f49d7f..c27c230 100644
--- a/test/Analysis/exploded-graph-rewriter/program_points.dot
+++ b/test/Analysis/exploded-graph-rewriter/program_points.dot
@@ -116,3 +116,51 @@
       }
     ]}
 \l}"];
+
+// CHECK-NEXT: <b>Program point:</b>
+// CHECK-SAME: <table border="0" align="left" width="0">
+// CHECK-SAME:   <tr>
+// CHECK-SAME:     <td align="left" width="0">
+// CHECK-SAME:       main.cpp:<b>8</b>:<b>9</b>:
+// CHECK-SAME:     </td>
+// CHECK-SAME:     <td align="left" width="0">
+// CHECK-SAME:       <font color="cyan4">
+// CHECK-SAME:         ImplicitCastExpr (LValueToRValue)
+// CHECK-SAME:       </font>
+// CHECK-SAME:     </td>
+// CHECK-SAME:     <td align="left"><i>S5</i></td>
+// CHECK-SAME:     <td align="left">
+// CHECK-SAME:       <font color="cyan3">PreStmt</font>
+// CHECK-SAME:     </td>
+// CHECK-SAME:     <td align="left">y</td>
+// CHECK-SAME:   </tr>
+// CHECK-SAME:   <tr>
+// CHECK-SAME:     <td width="0">
+// CHECK-SAME:     </td>
+// CHECK-SAME:     <td colspan="3" align="left">
+// CHECK-SAME:       <b>Tag: </b>
+// CHECK-SAME:       <font color="crimson">ExprEngine : Clean Node</font>
+// CHECK-SAME:     </td>
+// CHECK-SAME:   </tr>
+// CHECK-SAME: </table>
+Node0x4 [shape=record,label=
+ "{
+    { "node_id": 4, "pointer": "0x4", "has_report": false, "is_sink": false,
+      "program_state": null, "program_points": [
+      {
+        "kind": "Statement",
+        "stmt_kind": "ImplicitCastExpr",
+        "cast_kind": "LValueToRValue",
+        "stmt_point_kind": "PreStmt",
+        "stmt_id": 5,
+        "pointer": "0x6",
+        "pretty": "y",
+        "location": {
+          "file": "main.cpp",
+          "line": 8,
+          "column": 9
+        },
+        "tag": "ExprEngine : Clean Node"
+      }
+    ]}
+\l}"];
diff --git a/utils/analyzer/exploded-graph-rewriter.py b/utils/analyzer/exploded-graph-rewriter.py
index 05b01b3..77da739 100755
--- a/utils/analyzer/exploded-graph-rewriter.py
+++ b/utils/analyzer/exploded-graph-rewriter.py
@@ -73,6 +73,8 @@
         elif self.kind == 'Statement':
             logging.debug(json_pp)
             self.stmt_kind = json_pp['stmt_kind']
+            self.cast_kind = json_pp['cast_kind'] \
+                if 'cast_kind' in json_pp else None
             self.stmt_point_kind = json_pp['stmt_point_kind']
             self.stmt_id = json_pp['stmt_id']
             self.pointer = json_pp['pointer']
@@ -497,7 +499,9 @@
                        '<td align="left"><i>S%s</i></td>'
                        '<td align="left"><font color="%s">%s</font></td>'
                        '<td align="left">%s</td></tr>'
-                       % (self._make_sloc(p.loc), color, p.stmt_kind,
+                       % (self._make_sloc(p.loc), color,
+                          '%s (%s)' % (p.stmt_kind, p.cast_kind)
+                          if p.cast_kind is not None else p.stmt_kind,
                           p.stmt_id, stmt_color, p.stmt_point_kind,
                           self._short_pretty(p.pretty)
                           if not skip_pretty else ''))