r365861 - [analyzer] exploded-graph-rewriter: Improve source location dumps.
Artem Dergachev via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 11 19:10:33 PDT 2019
Author: dergachev
Date: Thu Jul 11 19:10:33 2019
New Revision: 365861
URL: http://llvm.org/viewvc/llvm-project?rev=365861&view=rev
Log:
[analyzer] exploded-graph-rewriter: Improve source location dumps.
- Correctly display macro expansion and spelling locations.
- Use the same procedure to display location context call site locations.
- Display statement IDs for program points.
Added:
cfe/trunk/test/Analysis/exploded-graph-rewriter/macros.c
Modified:
cfe/trunk/include/clang/Basic/JsonSupport.h
cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp
cfe/trunk/lib/Analysis/ProgramPoint.cpp
cfe/trunk/test/Analysis/dump_egraph.cpp
cfe/trunk/test/Analysis/exploded-graph-rewriter/environment.dot
cfe/trunk/test/Analysis/exploded-graph-rewriter/environment_diff.dot
cfe/trunk/test/Analysis/exploded-graph-rewriter/program_points.dot
cfe/trunk/test/Analysis/expr-inspection.c
cfe/trunk/utils/analyzer/exploded-graph-rewriter.py
Modified: cfe/trunk/include/clang/Basic/JsonSupport.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/JsonSupport.h?rev=365861&r1=365860&r2=365861&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/JsonSupport.h (original)
+++ cfe/trunk/include/clang/Basic/JsonSupport.h Thu Jul 11 19:10:33 2019
@@ -10,6 +10,7 @@
#define LLVM_CLANG_BASIC_JSONSUPPORT_H
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
@@ -77,6 +78,42 @@ inline std::string JsonFormat(StringRef
return '\"' + Str + '\"';
}
+inline void printSourceLocationAsJson(raw_ostream &Out, SourceLocation Loc,
+ const SourceManager &SM,
+ bool AddBraces = true) {
+ // Mostly copy-pasted from SourceLocation::print.
+ if (!Loc.isValid()) {
+ Out << "null";
+ return;
+ }
+
+ if (Loc.isFileID()) {
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+
+ if (PLoc.isInvalid()) {
+ Out << "null";
+ return;
+ }
+ // The macro expansion and spelling pos is identical for file locs.
+ if (AddBraces)
+ Out << "{ ";
+ Out << "\"line\": " << PLoc.getLine()
+ << ", \"column\": " << PLoc.getColumn()
+ << ", \"file\": \"" << PLoc.getFilename() << "\"";
+ if (AddBraces)
+ Out << " }";
+ return;
+ }
+
+ // We want 'location: { ..., spelling: { ... }}' but not
+ // 'location: { ... }, spelling: { ... }', hence the dance
+ // with braces.
+ Out << "{ ";
+ printSourceLocationAsJson(Out, SM.getExpansionLoc(Loc), SM, false);
+ Out << ", \"spelling\": ";
+ printSourceLocationAsJson(Out, SM.getSpellingLoc(Loc), SM, true);
+ Out << " }";
+}
} // namespace clang
#endif // LLVM_CLANG_BASIC_JSONSUPPORT_H
Modified: cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp?rev=365861&r1=365860&r2=365861&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp (original)
+++ cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp Thu Jul 11 19:10:33 2019
@@ -538,11 +538,9 @@ void LocationContext::printJson(raw_ostr
else
Out << "anonymous code";
- Out << "\", \"call_line\": ";
+ Out << "\", \"location\": ";
if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
- Out << '\"';
- printLocation(Out, SM, S->getBeginLoc());
- Out << '\"';
+ printSourceLocationAsJson(Out, S->getBeginLoc(), SM);
} else {
Out << "null";
}
@@ -555,8 +553,8 @@ void LocationContext::printJson(raw_ostr
case Block:
Out << "Invoking block\" ";
if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
- Out << ", \"decl_line\": ";
- printLocation(Out, SM, D->getBeginLoc());
+ Out << ", \"location\": ";
+ printSourceLocationAsJson(Out, D->getBeginLoc(), SM);
Out << ' ';
}
break;
Modified: cfe/trunk/lib/Analysis/ProgramPoint.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ProgramPoint.cpp?rev=365861&r1=365860&r2=365861&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ProgramPoint.cpp (original)
+++ cfe/trunk/lib/Analysis/ProgramPoint.cpp Thu Jul 11 19:10:33 2019
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/JsonSupport.h"
using namespace clang;
@@ -46,19 +47,6 @@ LLVM_DUMP_METHOD void ProgramPoint::dump
return printJson(llvm::errs());
}
-static void printLocJson(raw_ostream &Out, SourceLocation Loc,
- const SourceManager &SM) {
- Out << "\"location\": ";
- if (!Loc.isFileID()) {
- Out << "null";
- return;
- }
-
- Out << "{ \"line\": " << SM.getExpansionLineNumber(Loc)
- << ", \"column\": " << SM.getExpansionColumnNumber(Loc)
- << ", \"file\": \"" << SM.getFilename(Loc) << "\" }";
-}
-
void ProgramPoint::printJson(llvm::raw_ostream &Out, const char *NL) const {
const ASTContext &Context =
getLocationContext()->getAnalysisDeclContext()->getASTContext();
@@ -112,16 +100,18 @@ void ProgramPoint::printJson(llvm::raw_o
case ProgramPoint::PreImplicitCallKind: {
ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
Out << "PreCall\", \"decl\": \""
- << PC.getDecl()->getAsFunction()->getQualifiedNameAsString() << "\", ";
- printLocJson(Out, PC.getLocation(), SM);
+ << PC.getDecl()->getAsFunction()->getQualifiedNameAsString()
+ << "\", \"location\": ";
+ printSourceLocationAsJson(Out, PC.getLocation(), SM);
break;
}
case ProgramPoint::PostImplicitCallKind: {
ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
Out << "PostCall\", \"decl\": \""
- << PC.getDecl()->getAsFunction()->getQualifiedNameAsString() << "\", ";
- printLocJson(Out, PC.getLocation(), SM);
+ << PC.getDecl()->getAsFunction()->getQualifiedNameAsString()
+ << "\", \"location\": ";
+ printSourceLocationAsJson(Out, PC.getLocation(), SM);
break;
}
@@ -153,8 +143,8 @@ void ProgramPoint::printJson(llvm::raw_o
E.getSrc()->printTerminatorJson(Out, Context.getLangOpts(),
/*AddQuotes=*/true);
- Out << ", ";
- printLocJson(Out, T->getBeginLoc(), SM);
+ Out << ", \"location\": ";
+ printSourceLocationAsJson(Out, T->getBeginLoc(), SM);
Out << ", \"term_kind\": \"";
if (isa<SwitchStmt>(T)) {
@@ -202,8 +192,8 @@ void ProgramPoint::printJson(llvm::raw_o
S->printJson(Out, nullptr, PP, AddQuotes);
- Out << ", ";
- printLocJson(Out, S->getBeginLoc(), SM);
+ Out << ", \"location\": ";
+ printSourceLocationAsJson(Out, S->getBeginLoc(), SM);
Out << ", \"stmt_point_kind\": \"";
if (getAs<PreLoad>())
Modified: cfe/trunk/test/Analysis/dump_egraph.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dump_egraph.cpp?rev=365861&r1=365860&r2=365861&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/dump_egraph.cpp (original)
+++ cfe/trunk/test/Analysis/dump_egraph.cpp Thu Jul 11 19:10:33 2019
@@ -18,9 +18,9 @@ void foo() {
new S;
}
-// CHECK: \"location_context\": \"#0 Call\", \"calling\": \"foo\", \"call_line\": null, \"items\": [\l \{ \"stmt_id\": {{[0-9]+}}, \"kind\": \"construct into local variable\", \"argument_index\": null, \"pretty\": \"T t;\", \"value\": \"&t\"
+// CHECK: \"location_context\": \"#0 Call\", \"calling\": \"foo\", \"location\": null, \"items\": [\l \{ \"stmt_id\": {{[0-9]+}}, \"kind\": \"construct into local variable\", \"argument_index\": null, \"pretty\": \"T t;\", \"value\": \"&t\"
-// CHECK: \"location_context\": \"#0 Call\", \"calling\": \"T::T\", \"call_line\": \"16\", \"items\": [\l \{ \"init_id\": {{[0-9]+}}, \"kind\": \"construct into member variable\", \"argument_index\": null, \"pretty\": \"s\", \"value\": \"&t-\>s\"
+// CHECK: \"location_context\": \"#0 Call\", \"calling\": \"T::T\", \"location\": \{ \"line\": 16, \"column\": 5, \"file\": \"{{.*}}dump_egraph.cpp\" \}, \"items\": [\l \{ \"init_id\": {{[0-9]+}}, \"kind\": \"construct into member variable\", \"argument_index\": null, \"pretty\": \"s\", \"value\": \"&t-\>s\"
// CHECK: \"cluster\": \"t\", \"pointer\": \"{{0x[0-9a-f]+}}\", \"items\": [\l \{ \"kind\": \"Default\", \"offset\": 0, \"value\": \"conj_$2\{int, LC5, no stmt, #1\}\"
Modified: cfe/trunk/test/Analysis/exploded-graph-rewriter/environment.dot
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exploded-graph-rewriter/environment.dot?rev=365861&r1=365860&r2=365861&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/exploded-graph-rewriter/environment.dot (original)
+++ cfe/trunk/test/Analysis/exploded-graph-rewriter/environment.dot Thu Jul 11 19:10:33 2019
@@ -10,7 +10,11 @@
// CHECK-SAME: <b>#0 Call</b>
// CHECK-SAME: </td>
// CHECK-SAME: <td align="left" colspan="2">
-// CHECK-SAME: <font color="gray60">foo </font>(line 4)
+// CHECK-SAME: <font color="gray60">foo </font>
+// 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>)
// CHECK-SAME: </td>
// CHECK-SAME: </tr>
// CHECK-SAME: <tr>
@@ -46,7 +50,16 @@ Node0x1 [shape=record,label=
"location_context": "#0 Call",
"lctx_id": 3,
"calling": "foo",
- "call_line": 4,
+ "location": {
+ "file": "environment.cpp",
+ "line": 4,
+ "column": 6,
+ "spelling": {
+ "file": "environment.h",
+ "line": 7,
+ "column": 8
+ }
+ },
"items": [
{
"stmt_id": 5,
Modified: cfe/trunk/test/Analysis/exploded-graph-rewriter/environment_diff.dot
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exploded-graph-rewriter/environment_diff.dot?rev=365861&r1=365860&r2=365861&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/exploded-graph-rewriter/environment_diff.dot (original)
+++ cfe/trunk/test/Analysis/exploded-graph-rewriter/environment_diff.dot Thu Jul 11 19:10:33 2019
@@ -25,7 +25,7 @@ Node0x1 [shape=record,label=
"location_context": "#0 Call",
"lctx_id": 3,
"calling": "foo",
- "call_line": 4,
+ "location": null,
"items": [
{
"stmt_id": 5,
@@ -76,7 +76,7 @@ Node0x6 [shape=record,label=
"location_context": "#0 Call",
"lctx_id": 3,
"calling": "foo",
- "call_line": 4,
+ "location": null,
"items": [
{
"stmt_id": 9,
@@ -121,7 +121,7 @@ Node0x9 [shape=record,label=
"location_context": "#0 Call",
"lctx_id": 3,
"calling": "foo",
- "call_line": 4,
+ "location": null,
"items": [
{
"stmt_id": 9,
Added: cfe/trunk/test/Analysis/exploded-graph-rewriter/macros.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exploded-graph-rewriter/macros.c?rev=365861&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/exploded-graph-rewriter/macros.c (added)
+++ cfe/trunk/test/Analysis/exploded-graph-rewriter/macros.c Thu Jul 11 19:10:33 2019
@@ -0,0 +1,18 @@
+// FIXME: Figure out how to use %clang_analyze_cc1 with our lit.local.cfg.
+// RUN: %clang_cc1 -analyze -triple x86_64-unknown-linux-gnu \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-dump-egraph=%t.dot %s
+// RUN: %exploded_graph_rewriter %t.dot | FileCheck %s
+// REQUIRES: asserts
+
+// FIXME: Substitution doesn't seem to work on Windows.
+// UNSUPPORTED: system-windows
+
+// CHECK: macros.c:<b>17</b>:<b>10</b>
+// CHECK-SAME: <font color="royalblue1">
+// CHECK-SAME: (<i>spelling at </i> macros.c:<b>15</b>:<b>14</b>)
+// CHECK-SAME: </font>
+#define NULL 0
+void *foo() {
+ return NULL;
+}
Modified: cfe/trunk/test/Analysis/exploded-graph-rewriter/program_points.dot
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exploded-graph-rewriter/program_points.dot?rev=365861&r1=365860&r2=365861&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/exploded-graph-rewriter/program_points.dot (original)
+++ cfe/trunk/test/Analysis/exploded-graph-rewriter/program_points.dot Thu Jul 11 19:10:33 2019
@@ -57,10 +57,11 @@ Node0x1 [shape=record,label=
// CHECK-SAME: <td align="left" width="0">
// CHECK-SAME: <font color="cyan4">DeclRefExpr</font>
// CHECK-SAME: </td>
+// CHECK-SAME: <td align="left"><i>S3</i></td>
// CHECK-SAME: <td align="left">
// CHECK-SAME: <font color="cyan3">PreStmt</font>
// CHECK-SAME: </td>
-// CHECK-SAME: <td>x</td>
+// CHECK-SAME: <td align="left">x</td>
// CHECK-SAME: </tr>
// CHECK-SAME: <tr>
// CHECK-SAME: <td width="0">
@@ -79,7 +80,7 @@ Node0x2 [shape=record,label=
"kind": "Statement",
"stmt_kind": "DeclRefExpr",
"stmt_point_kind": "PreStmt",
- "stmd_id": 3,
+ "stmt_id": 3,
"pointer": "0x3",
"pretty": "x",
"location": {
@@ -95,7 +96,7 @@ Node0x2 [shape=record,label=
// Test collapsing large pretty prints with braces.
// CHECK-NEXT: <b>Program point:</b>
-// CHECK-SAME: <td>\{ ... \}</td>
+// CHECK-SAME: <td align="left">\{ ... \}</td>
Node0x3 [shape=record,label=
"{
{ "node_id": 3, "pointer": "0x3", "has_report": false, "is_sink": false,
@@ -104,7 +105,7 @@ Node0x3 [shape=record,label=
"kind": "Statement",
"stmt_kind": "CompoundStmt",
"stmt_point_kind": "PostStmt",
- "stmd_id": 6,
+ "stmt_id": 6,
"pointer": "0x6",
"pretty": "{ very very very very very very long pretty print }",
"location": {
Modified: cfe/trunk/test/Analysis/expr-inspection.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/expr-inspection.c?rev=365861&r1=365860&r2=365861&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/expr-inspection.c (original)
+++ cfe/trunk/test/Analysis/expr-inspection.c Thu Jul 11 19:10:33 2019
@@ -30,7 +30,7 @@ void foo(int x) {
// CHECK-NEXT: ]}
// CHECK-NEXT: ]},
// CHECK-NEXT: "environment": { "pointer": "{{0x[0-9a-f]+}}", "items": [
-// CHECK-NEXT: { "lctx_id": 1, "location_context": "#0 Call", "calling": "foo", "call_line": null, "items": [
+// CHECK-NEXT: { "lctx_id": 1, "location_context": "#0 Call", "calling": "foo", "location": null, "items": [
// CHECK-NEXT: { "stmt_id": {{[0-9]+}}, "pretty": "clang_analyzer_printState", "value": "&code{clang_analyzer_printState}" }
// CHECK-NEXT: ]}
// CHECK-NEXT: ]},
Modified: cfe/trunk/utils/analyzer/exploded-graph-rewriter.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/analyzer/exploded-graph-rewriter.py?rev=365861&r1=365860&r2=365861&view=diff
==============================================================================
--- cfe/trunk/utils/analyzer/exploded-graph-rewriter.py (original)
+++ cfe/trunk/utils/analyzer/exploded-graph-rewriter.py Thu Jul 11 19:10:33 2019
@@ -49,10 +49,16 @@ class GenericMap(object):
class SourceLocation(object):
def __init__(self, json_loc):
super(SourceLocation, self).__init__()
+ logging.debug('json: %s' % json_loc)
self.line = json_loc['line']
self.col = json_loc['column']
self.filename = os.path.basename(json_loc['file']) \
if 'file' in json_loc else '(main file)'
+ self.spelling = SourceLocation(json_loc['spelling']) \
+ if 'spelling' in json_loc else None
+
+ def is_macro(self):
+ return self.spelling is not None
# A deserialized program point.
@@ -65,8 +71,10 @@ class ProgramPoint(object):
self.src_id = json_pp['src_id']
self.dst_id = json_pp['dst_id']
elif self.kind == 'Statement':
+ logging.debug(json_pp)
self.stmt_kind = json_pp['stmt_kind']
self.stmt_point_kind = json_pp['stmt_point_kind']
+ self.stmt_id = json_pp['stmt_id']
self.pointer = json_pp['pointer']
self.pretty = json_pp['pretty']
self.loc = SourceLocation(json_pp['location']) \
@@ -102,7 +110,8 @@ class LocationContext(object):
self.lctx_id = json_frame['lctx_id']
self.caption = json_frame['location_context']
self.decl = json_frame['calling']
- self.line = json_frame['call_line']
+ self.loc = SourceLocation(json_frame['location']) \
+ if json_frame['location'] is not None else None
def _key(self):
return self.lctx_id
@@ -432,6 +441,22 @@ class DotDumpVisitor(object):
return s
return candidate
+ @staticmethod
+ def _make_sloc(loc):
+ if loc is None:
+ return '<i>Invalid Source Location</i>'
+
+ def make_plain_loc(loc):
+ return '%s:<b>%s</b>:<b>%s</b>' \
+ % (loc.filename, loc.line, loc.col)
+
+ if loc.is_macro():
+ return '%s <font color="royalblue1">' \
+ '(<i>spelling at </i> %s)</font>' \
+ % (make_plain_loc(loc), make_plain_loc(loc.spelling))
+
+ return make_plain_loc(loc)
+
def visit_begin_graph(self, graph):
self._graph = graph
self._dump_raw('digraph "ExplodedGraph" {\n')
@@ -457,29 +482,16 @@ class DotDumpVisitor(object):
# Such statements show up only at [Pre|Post]StmtPurgeDeadSymbols
skip_pretty = 'PurgeDeadSymbols' in p.stmt_point_kind
stmt_color = 'cyan3'
- if p.loc is not None:
- self._dump('<tr><td align="left" width="0">'
- '%s:<b>%s</b>:<b>%s</b>:</td>'
- '<td align="left" width="0"><font color="%s">'
- '%s</font></td>'
- '<td align="left"><font color="%s">%s</font></td>'
- '<td>%s</td></tr>'
- % (p.loc.filename, p.loc.line,
- p.loc.col, color, p.stmt_kind,
- stmt_color, p.stmt_point_kind,
- self._short_pretty(p.pretty)
- if not skip_pretty else ''))
- else:
- self._dump('<tr><td align="left" width="0">'
- '<i>Invalid Source Location</i>:</td>'
- '<td align="left" width="0">'
- '<font color="%s">%s</font></td>'
- '<td align="left"><font color="%s">%s</font></td>'
- '<td>%s</td></tr>'
- % (color, p.stmt_kind,
- stmt_color, p.stmt_point_kind,
- self._short_pretty(p.pretty)
- if not skip_pretty else ''))
+ self._dump('<tr><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>'
+ '<td align="left"><font color="%s">%s</font></td>'
+ '<td align="left">%s</td></tr>'
+ % (self._make_sloc(p.loc), color, p.stmt_kind,
+ p.stmt_id, stmt_color, p.stmt_point_kind,
+ self._short_pretty(p.pretty)
+ if not skip_pretty else ''))
elif p.kind == 'Edge':
self._dump('<tr><td width="0"></td>'
'<td align="left" width="0">'
@@ -516,8 +528,8 @@ class DotDumpVisitor(object):
'%s</td></tr>'
% (self._diff_plus_minus(is_added),
lc.caption, lc.decl,
- ('(line %s)' % lc.line) if lc.line is not None
- else ''))
+ ('(%s)' % self._make_sloc(lc.loc))
+ if lc.loc is not None else ''))
def dump_binding(f, b, is_added=None):
self._dump('<tr><td>%s</td>'
More information about the cfe-commits
mailing list