NoQ created this revision.
NoQ added reviewers: dcoughlin, xazax.hun, Charusso.
Herald added subscribers: cfe-commits, dkrupp, donat.nagy, Szelethus, 
mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware.
Herald added a project: clang.

This patch fixes an accidental redundant `</td>` and disables generation of 
variable popups within macro popups due to 
https://bugs.llvm.org/show_bug.cgi?id=44782

I also added some tests for our HTML files because those were pretty much 
non-existent so far. Given that we can now also test scan-build (i actually 
landed D69781 <https://reviews.llvm.org/D69781> yesterday), there are no more 
excuses for not writing tests. Test `variable-popups.c` was passing previously, 
so it's here just for the sake of finally having a test, while the other two 
tests were failing on their respective `CHECK-NOT` directives.

Another interesting thing i did was apply `tidy-html5` to our HTML files. They 
seem to satisfy the linter now, and btw that's how i found the first issue 
(while trying to reduce the second issue by running `tidy-html5` under 
`creduce`).

@Charusso: I didn't manage to understand how `PopUpRanges` get passed around 
and why, so i removed them. If you have an example of where it matters, please 
send tests :)


Repository:
  rC Clang

https://reviews.llvm.org/D73993

Files:
  clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
  clang/test/Analysis/html_diagnostics/td-hotfix.c
  clang/test/Analysis/html_diagnostics/variable-popups-2.c
  clang/test/Analysis/html_diagnostics/variable-popups.c

Index: clang/test/Analysis/html_diagnostics/variable-popups.c
===================================================================
--- /dev/null
+++ clang/test/Analysis/html_diagnostics/variable-popups.c
@@ -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>
Index: clang/test/Analysis/html_diagnostics/variable-popups-2.c
===================================================================
--- /dev/null
+++ clang/test/Analysis/html_diagnostics/variable-popups-2.c
@@ -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>
Index: clang/test/Analysis/html_diagnostics/td-hotfix.c
===================================================================
--- /dev/null
+++ clang/test/Analysis/html_diagnostics/td-hotfix.c
@@ -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>
Index: clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -91,8 +91,7 @@
                              unsigned num);
 
   void HandlePiece(Rewriter &R, FileID BugFileID, const PathDiagnosticPiece &P,
-                   const std::vector<SourceRange> &PopUpRanges, unsigned num,
-                   unsigned max);
+                   unsigned num, unsigned max);
 
   void HighlightRange(Rewriter& R, FileID BugFileID, SourceRange Range,
                       const char *HighlightStart = "<span class=\"mrange\">",
@@ -607,50 +606,31 @@
 )<<<";
 }
 
-static void
-HandlePopUpPieceStartTag(Rewriter &R,
-                         const std::vector<SourceRange> &PopUpRanges) {
-  for (const auto &Range : PopUpRanges) {
-    html::HighlightRange(R, Range.getBegin(), Range.getEnd(), "",
-                         "<table class='variable_popup'><tbody>",
-                         /*IsTokenRange=*/true);
-  }
-}
-
-static void HandlePopUpPieceEndTag(Rewriter &R,
-                                   const PathDiagnosticPopUpPiece &Piece,
-                                   std::vector<SourceRange> &PopUpRanges,
-                                   unsigned int LastReportedPieceIndex,
-                                   unsigned int PopUpPieceIndex) {
+static void HandlePopUpPieceTag(Rewriter &R,
+                                const PathDiagnosticPopUpPiece &Piece,
+                                unsigned int LastReportedPieceIndex,
+                                unsigned int PopUpPieceIndex) {
   SmallString<256> Buf;
   llvm::raw_svector_ostream Out(Buf);
 
   SourceRange Range(Piece.getLocation().asRange());
+  if (Range.getBegin().isMacroID() || Range.getEnd().isMacroID())
+    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'>"
+  Out << "<table class='variable_popup'><tbody><tr><td valign='top'>"
+         "<div class='PathIndex PathIndexPopUp'>"
       << LastReportedPieceIndex;
 
   // Also annotate the state transition with extra indices.
   Out << '.' << PopUpPieceIndex;
 
-  Out << "</div></td><td>" << Piece.getString() << "</td></tr>";
+  Out << "</div></td><td>" << Piece.getString() << "</td></tr>"
+      << "</tbody></table></span>";
 
-  // If no report made at this range mark the variable and add the end tags.
-  if (std::find(PopUpRanges.begin(), PopUpRanges.end(), Range) ==
-      PopUpRanges.end()) {
-    // Store that we create a report at this range.
-    PopUpRanges.push_back(Range);
-
-    Out << "</tbody></table></span>";
-    html::HighlightRange(R, Range.getBegin(), Range.getEnd(),
-                         "<span class='variable'>", Buf.c_str(),
-                         /*IsTokenRange=*/true);
-  } else {
-    // Otherwise inject just the new row at the end of the range.
-    html::HighlightRange(R, Range.getBegin(), Range.getEnd(), "", Buf.c_str(),
-                         /*IsTokenRange=*/true);
-  }
+  html::HighlightRange(R, Range.getBegin(), Range.getEnd(),
+                       "<span class='variable'>", Buf.c_str(),
+                       /*IsTokenRange=*/true);
 }
 
 void HTMLDiagnostics::RewriteFile(Rewriter &R,
@@ -674,7 +654,6 @@
   std::map<int, int> IndexMap;
 
   // Stores the different ranges where we have reported something.
-  std::vector<SourceRange> PopUpRanges;
   for (auto I = path.rbegin(), E = path.rend(); I != E; ++I) {
     const auto &Piece = *I->get();
 
@@ -684,17 +663,26 @@
       // This adds diagnostic bubbles, but not navigation.
       // Navigation through note pieces would be added later,
       // as a separate pass through the piece list.
-      HandlePiece(R, FID, Piece, PopUpRanges, NumNotePieces, TotalNotePieces);
+      HandlePiece(R, FID, Piece, NumNotePieces, TotalNotePieces);
       --NumNotePieces;
     } else {
-      HandlePiece(R, FID, Piece, PopUpRanges, NumRegularPieces,
-                  TotalRegularPieces);
+      HandlePiece(R, FID, Piece, NumRegularPieces, TotalRegularPieces);
       --NumRegularPieces;
     }
   }
 
+  // Add line numbers, header, footer, etc.
+  html::EscapeText(R, FID);
+  html::AddLineNumbers(R, FID);
+
+  // If we have a preprocessor, relex the file and syntax highlight.
+  // We might not have a preprocessor if we come from a deserialized AST file,
+  // for example.
+  html::SyntaxHighlight(R, FID, PP);
+  html::HighlightMacros(R, FID, PP);
+
   // Secondary indexing if we are having multiple pop-ups between two notes.
-  // (e.g. [(13) 'a' is 'true'];  [(13.1) 'b' is 'false'];  [(13.2) 'c' is...)
+  // (e.g. [(13) 'a' is 'true'];  [(13.1) 'b' is 'false'];  [(13.2) 'c' is...])
   NumRegularPieces = TotalRegularPieces;
   for (auto I = path.rbegin(), E = path.rend(); I != E; ++I) {
     const auto &Piece = *I->get();
@@ -707,8 +695,7 @@
       // This marks the variable, adds the </table> end tag and the message
       // (list element) as a row. The <table> start tag will be added after the
       // rows has been written out. Note: It stores every different range.
-      HandlePopUpPieceEndTag(R, *PopUpP, PopUpRanges, NumRegularPieces,
-                             PopUpPieceIndex);
+      HandlePopUpPieceTag(R, *PopUpP, NumRegularPieces, PopUpPieceIndex);
 
       if (PopUpPieceIndex > 0)
         --IndexMap[NumRegularPieces];
@@ -717,24 +704,10 @@
       --NumRegularPieces;
     }
   }
-
-  // Add the <table> start tag of pop-up pieces based on the stored ranges.
-  HandlePopUpPieceStartTag(R, PopUpRanges);
-
-  // Add line numbers, header, footer, etc.
-  html::EscapeText(R, FID);
-  html::AddLineNumbers(R, FID);
-
-  // If we have a preprocessor, relex the file and syntax highlight.
-  // We might not have a preprocessor if we come from a deserialized AST file,
-  // for example.
-  html::SyntaxHighlight(R, FID, PP);
-  html::HighlightMacros(R, FID, PP);
 }
 
 void HTMLDiagnostics::HandlePiece(Rewriter &R, FileID BugFileID,
                                   const PathDiagnosticPiece &P,
-                                  const std::vector<SourceRange> &PopUpRanges,
                                   unsigned num, unsigned max) {
   // For now, just draw a box above the line in question, and emit the
   // warning.
@@ -870,7 +843,7 @@
          << (num - 1)
          << "\" title=\"Previous event ("
          << (num - 1)
-         << ")\">&#x2190;</a></div></td>";
+         << ")\">&#x2190;</a></div>";
     }
 
     os << "</td><td>";
@@ -947,14 +920,8 @@
 
   // Now highlight the ranges.
   ArrayRef<SourceRange> Ranges = P.getRanges();
-  for (const auto &Range : Ranges) {
-    // If we have already highlighted the range as a pop-up there is no work.
-    if (std::find(PopUpRanges.begin(), PopUpRanges.end(), Range) !=
-        PopUpRanges.end())
-      continue;
-
+  for (const auto &Range : Ranges)
     HighlightRange(R, LPosInfo.first, Range);
-  }
 }
 
 static void EmitAlphaCounter(raw_ostream &os, unsigned n) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to