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>' _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits