[analyzer] Fix a couple of bugs in HTML report generation.
authorArtem Dergachev <artem.dergachev@gmail.com>
Tue, 4 Feb 2020 19:48:19 +0000 (22:48 +0300)
committerArtem Dergachev <artem.dergachev@gmail.com>
Wed, 5 Feb 2020 14:16:38 +0000 (17:16 +0300)
It should now produce valid HTML again.

Differential Revision: https://reviews.llvm.org/D73993

clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
clang/test/Analysis/html_diagnostics/td-hotfix.c [new file with mode: 0644]
clang/test/Analysis/html_diagnostics/variable-popups-macro.c [new file with mode: 0644]
clang/test/Analysis/html_diagnostics/variable-popups-multiple.c [new file with mode: 0644]
clang/test/Analysis/html_diagnostics/variable-popups-simple.c [new file with mode: 0644]

index a4918d7..002b607 100644 (file)
@@ -607,10 +607,17 @@ window.addEventListener("keydown", function (event) {
 )<<<";
 }
 
+static bool shouldDisplayPopUpRange(const SourceRange &Range) {
+  return !(Range.getBegin().isMacroID() || Range.getEnd().isMacroID());
+}
+
 static void
 HandlePopUpPieceStartTag(Rewriter &R,
                          const std::vector<SourceRange> &PopUpRanges) {
   for (const auto &Range : PopUpRanges) {
+    if (!shouldDisplayPopUpRange(Range))
+      continue;
+
     html::HighlightRange(R, Range.getBegin(), Range.getEnd(), "",
                          "<table class='variable_popup'><tbody>",
                          /*IsTokenRange=*/true);
@@ -626,6 +633,8 @@ static void HandlePopUpPieceEndTag(Rewriter &R,
   llvm::raw_svector_ostream Out(Buf);
 
   SourceRange Range(Piece.getLocation().asRange());
+  if (!shouldDisplayPopUpRange(Range))
+    return;
 
   // Write out the path indices with a right arrow and the message as a row.
   Out << "<tr><td valign='top'><div class='PathIndex PathIndexPopUp'>"
@@ -870,7 +879,7 @@ void HTMLDiagnostics::HandlePiece(Rewriter &R, FileID BugFileID,
          << (num - 1)
          << "\" title=\"Previous event ("
          << (num - 1)
-         << ")\">&#x2190;</a></div></td>";
+         << ")\">&#x2190;</a></div>";
     }
 
     os << "</td><td>";
diff --git a/clang/test/Analysis/html_diagnostics/td-hotfix.c b/clang/test/Analysis/html_diagnostics/td-hotfix.c
new file mode 100644 (file)
index 0000000..8595642
--- /dev/null
@@ -0,0 +1,31 @@
+// RUN: rm -fR %t
+// RUN: mkdir %t
+// RUN: %clang_analyze_cc1 -analyzer-checker=core \
+// RUN:                    -analyzer-output=html -o %t -verify %s
+// RUN: cat %t/report-*.html | FileCheck %s
+
+void bar(int);
+
+void foo() {
+  int a;
+  bar(a); // expected-warning{{1st function call argument is an uninitialized value}}
+}
+
+// CHECK-LABEL:    <div id="EndPath" class="msg msgEvent" style="margin-left:3ex">
+// CHECK-SAME:       <table class="msgT">
+// CHECK-SAME:         <tr>
+// CHECK-SAME:           <td valign="top">
+// CHECK-SAME:             <div class="PathIndex PathIndexEvent">2</div>
+// CHECK-SAME:           </td>
+// CHECK-SAME:           <td>
+// CHECK-SAME:             <div class="PathNav">
+// CHECK-SAME:               <a href="#Path1" title="Previous event (1)">&#x2190;</a>
+// CHECK-SAME:             </div>
+// CHECK-SAME:           </td>
+// CHECK-NOT:            </td>
+// CHECK-SAME:           <td>
+// CHECK-SAME:             1st function call argument is an uninitialized value
+// CHECK-SAME:           </td>
+// CHECK-SAME:         </tr>
+// CHECK-SAME:       </table>
+// CHECK-SAME:     </div>
diff --git a/clang/test/Analysis/html_diagnostics/variable-popups-macro.c b/clang/test/Analysis/html_diagnostics/variable-popups-macro.c
new file mode 100644 (file)
index 0000000..83bda14
--- /dev/null
@@ -0,0 +1,28 @@
+// RUN: rm -fR %t
+// RUN: mkdir %t
+// RUN: %clang_analyze_cc1 -analyzer-checker=core \
+// RUN:                    -analyzer-output=html -o %t -verify %s
+// RUN: cat %t/report-*.html | FileCheck %s
+
+void bar(int);
+
+#define MACRO if (b)
+
+void foo2() {
+  int a;
+  int b = 1;
+  MACRO
+    bar(a); // expected-warning{{1st function call argument is an uninitialized value}}
+}
+
+// For now we don't emit popups inside macros due to UI limitations.
+// Once we do, we should test it thoroughly.
+
+// CHECK-LABEL: <tr class="codeline" data-linenumber="14">
+// CHECK-NOT:   <span class='variable'>
+// CHECK-SAME:  <span class='macro'>
+// CHECK-SAME:    MACRO
+// CHECK-SAME:    <span class='macro_popup'>
+// CHECK-SAME:      if (b)
+// CHECK-SAME:    </span>
+// CHECK-SAME:  </span>
diff --git a/clang/test/Analysis/html_diagnostics/variable-popups-multiple.c b/clang/test/Analysis/html_diagnostics/variable-popups-multiple.c
new file mode 100644 (file)
index 0000000..d7a05b5
--- /dev/null
@@ -0,0 +1,29 @@
+// RUN: rm -fR %t
+// RUN: mkdir %t
+// RUN: %clang_analyze_cc1 -analyzer-checker=core \
+// RUN:                    -analyzer-output=html -o %t -verify %s
+// RUN: cat %t/report-*.html | FileCheck %s
+
+void bar(int);
+
+void foo() {
+  int a;
+  for (unsigned i = 0; i < 3; ++i)
+    if (i)
+      bar(a); // expected-warning{{1st function call argument is an uninitialized value}}
+}
+
+// CHECK:      <span class='variable'>i
+// CHECK-SAME:   <table class='variable_popup'><tbody><tr>
+// CHECK-SAME:     <td valign='top'>
+// CHECK-SAME:       <div class='PathIndex PathIndexPopUp'>2.1</div>
+// CHECK-SAME:     </td>
+// CHECK-SAME:     <td>'i' is 0</td>
+// CHECK-SAME:   </tr>
+// CHECK-SAME:   <tr>
+// CHECK-SAME:     <td valign='top'>
+// CHECK-SAME:       <div class='PathIndex PathIndexPopUp'>4.1</div>
+// CHECK-SAME:     </td>
+// CHECK-SAME:     <td>'i' is 1</td>
+// CHECK-SAME:   </tr></tbody></table>
+// CHECK-SAME: </span>
diff --git a/clang/test/Analysis/html_diagnostics/variable-popups-simple.c b/clang/test/Analysis/html_diagnostics/variable-popups-simple.c
new file mode 100644 (file)
index 0000000..cb2f3bf
--- /dev/null
@@ -0,0 +1,23 @@
+// RUN: rm -fR %t
+// RUN: mkdir %t
+// RUN: %clang_analyze_cc1 -analyzer-checker=core \
+// RUN:                    -analyzer-output=html -o %t -verify %s
+// RUN: cat %t/report-*.html | FileCheck %s
+
+void bar(int);
+
+void foo2() {
+  int a;
+  int b = 1;
+  if (b)
+    bar(a); // expected-warning{{1st function call argument is an uninitialized value}}
+}
+
+// CHECK:      <span class='variable'>b
+// CHECK-SAME:   <table class='variable_popup'><tbody><tr>
+// CHECK-SAME:     <td valign='top'>
+// CHECK-SAME:       <div class='PathIndex PathIndexPopUp'>1.1</div>
+// CHECK-SAME:     </td>
+// CHECK-SAME:     <td>'b' is 1</td>
+// CHECK-SAME:   </tr></tbody></table>
+// CHECK-SAME: </span>