r309968 - [Analyzer] Add support for displaying cross-file diagnostic paths in HTML output

Devin Coughlin via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 3 11:12:23 PDT 2017


Author: dcoughlin
Date: Thu Aug  3 11:12:22 2017
New Revision: 309968

URL: http://llvm.org/viewvc/llvm-project?rev=309968&view=rev
Log:
[Analyzer] Add support for displaying cross-file diagnostic paths in HTML output

This change adds support for cross-file diagnostic paths in html output. If the
diagnostic path is not cross-file, there is no change in the output.

Patch by Vlad Tsyrklevich!

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

Added:
    cfe/trunk/test/Analysis/html-diag-singlefile.c
    cfe/trunk/test/Analysis/html-diag-singlefile.h
      - copied, changed from r309960, cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.h
    cfe/trunk/test/Analysis/html-diags-analyze-headers.c
    cfe/trunk/test/Analysis/html-diags-analyze-headers.h
    cfe/trunk/test/Coverage/html-multifile-diagnostics.c
      - copied, changed from r309960, cfe/trunk/test/Coverage/html-diagnostics.c
    cfe/trunk/test/Coverage/html-multifile-diagnostics.h
Removed:
    cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.c
    cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.h
Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/Analyses.def
    cfe/trunk/lib/Rewrite/HTMLRewrite.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
    cfe/trunk/test/Analysis/html-diags-multifile.c
    cfe/trunk/test/Analysis/html-diags.c
    cfe/trunk/test/Coverage/html-diagnostics.c
    cfe/trunk/www/analyzer/open_projects.html

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/Analyses.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/Analyses.def?rev=309968&r1=309967&r2=309968&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/Analyses.def (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/Analyses.def Thu Aug  3 11:12:22 2017
@@ -28,9 +28,10 @@ ANALYSIS_CONSTRAINTS(Z3Constraints, "z3"
 #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)
 #endif
 
-ANALYSIS_DIAGNOSTICS(HTML,  "html",  "Output analysis results using HTML",   createHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(HTML_SINGLE_FILE, "html-single-file", "Output analysis results using HTML (not allowing for multi-file bugs)", createHTMLSingleFileDiagnosticConsumer)
 ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer)
-ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for multi-file bugs)", createPlistMultiFileDiagnosticConsumer)
 ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer)
 ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer)
 

Modified: cfe/trunk/lib/Rewrite/HTMLRewrite.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/HTMLRewrite.cpp?rev=309968&r1=309967&r2=309968&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/HTMLRewrite.cpp (original)
+++ cfe/trunk/lib/Rewrite/HTMLRewrite.cpp Thu Aug  3 11:12:22 2017
@@ -289,6 +289,11 @@ void html::AddHeaderFooterInternalBuilti
       " body { color:#000000; background-color:#ffffff }\n"
       " body { font-family:Helvetica, sans-serif; font-size:10pt }\n"
       " h1 { font-size:14pt }\n"
+      " .FileName { margin-top: 5px; margin-bottom: 5px; display: inline; }\n"
+      " .FileNav { margin-left: 5px; margin-right: 5px; display: inline; }\n"
+      " .FileNav a { text-decoration:none; font-size: larger; }\n"
+      " .divider { margin-top: 30px; margin-bottom: 30px; height: 15px; }\n"
+      " .divider { background-color: gray; }\n"
       " .code { border-collapse:collapse; width:100%; }\n"
       " .code { font-family: \"Monospace\", monospace; font-size:10pt }\n"
       " .code { line-height: 1.2em }\n"

Modified: cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp?rev=309968&r1=309967&r2=309968&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp Thu Aug  3 11:12:22 2017
@@ -44,8 +44,12 @@ class HTMLDiagnostics : public PathDiagn
   bool createdDir, noDir;
   const Preprocessor &PP;
   AnalyzerOptions &AnalyzerOpts;
+  const bool SupportsCrossFileDiagnostics;
 public:
-  HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts, const std::string& prefix, const Preprocessor &pp);
+  HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts,
+                  const std::string& prefix,
+                  const Preprocessor &pp,
+                  bool supportsMultipleFiles);
 
   ~HTMLDiagnostics() override { FlushDiagnostics(nullptr); }
 
@@ -56,6 +60,10 @@ public:
     return "HTMLDiagnostics";
   }
 
+  bool supportsCrossFileDiagnostics() const override {
+    return SupportsCrossFileDiagnostics;
+  }
+
   unsigned ProcessMacroPiece(raw_ostream &os,
                              const PathDiagnosticMacroPiece& P,
                              unsigned num);
@@ -69,21 +77,47 @@ public:
 
   void ReportDiag(const PathDiagnostic& D,
                   FilesMade *filesMade);
+
+  // Generate the full HTML report
+  std::string GenerateHTML(const PathDiagnostic& D, Rewriter &R,
+                           const SourceManager& SMgr, const PathPieces& path,
+                           const char *declName);
+
+  // Add HTML header/footers to file specified by FID
+  void FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
+                    const SourceManager& SMgr, const PathPieces& path,
+                    FileID FID, const FileEntry *Entry, const char *declName);
+
+  // Rewrite the file specified by FID with HTML formatting.
+  void RewriteFile(Rewriter &R, const SourceManager& SMgr,
+                   const PathPieces& path, FileID FID);
 };
 
 } // end anonymous namespace
 
 HTMLDiagnostics::HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts,
                                  const std::string& prefix,
-                                 const Preprocessor &pp)
-    : Directory(prefix), createdDir(false), noDir(false), PP(pp), AnalyzerOpts(AnalyzerOpts) {
-}
+                                 const Preprocessor &pp,
+                                 bool supportsMultipleFiles)
+    : Directory(prefix),
+      createdDir(false),
+      noDir(false),
+      PP(pp),
+      AnalyzerOpts(AnalyzerOpts),
+      SupportsCrossFileDiagnostics(supportsMultipleFiles) {}
 
 void ento::createHTMLDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
                                         PathDiagnosticConsumers &C,
                                         const std::string& prefix,
                                         const Preprocessor &PP) {
-  C.push_back(new HTMLDiagnostics(AnalyzerOpts, prefix, PP));
+  C.push_back(new HTMLDiagnostics(AnalyzerOpts, prefix, PP, true));
+}
+
+void ento::createHTMLSingleFileDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
+                                                  PathDiagnosticConsumers &C,
+                                                  const std::string& prefix,
+                                                  const Preprocessor &PP) {
+  C.push_back(new HTMLDiagnostics(AnalyzerOpts, prefix, PP, false));
 }
 
 //===----------------------------------------------------------------------===//
@@ -121,24 +155,24 @@ void HTMLDiagnostics::ReportDiag(const P
   // First flatten out the entire path to make it easier to use.
   PathPieces path = D.path.flatten(/*ShouldFlattenMacros=*/false);
 
-  // The path as already been prechecked that all parts of the path are
-  // from the same file and that it is non-empty.
-  const SourceManager &SMgr = path.front()->getLocation().getManager();
+  // The path as already been prechecked that the path is non-empty.
   assert(!path.empty());
-  FileID FID =
-    path.front()->getLocation().asLocation().getExpansionLoc().getFileID();
-  assert(FID.isValid());
+  const SourceManager &SMgr = path.front()->getLocation().getManager();
 
   // Create a new rewriter to generate HTML.
   Rewriter R(const_cast<SourceManager&>(SMgr), PP.getLangOpts());
 
+  // The file for the first path element is considered the main report file, it
+  // will usually be equivalent to SMgr.getMainFileID(); however, it might be a
+  // header when -analyzer-opt-analyze-headers is used.
+  FileID ReportFile = path.front()->getLocation().asLocation().getExpansionLoc().getFileID();
+
   // Get the function/method name
   SmallString<128> declName("unknown");
   int offsetDecl = 0;
   if (const Decl *DeclWithIssue = D.getDeclWithIssue()) {
-      if (const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue)) {
+      if (const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue))
           declName = ND->getDeclName().getAsString();
-      }
 
       if (const Stmt *Body = DeclWithIssue->getBody()) {
           // Retrieve the relative position of the declaration which will be used
@@ -151,49 +185,144 @@ void HTMLDiagnostics::ReportDiag(const P
       }
   }
 
-  // Process the path.
-  // Maintain the counts of extra note pieces separately.
-  unsigned TotalPieces = path.size();
-  unsigned TotalNotePieces =
-      std::count_if(path.begin(), path.end(),
-                    [](const std::shared_ptr<PathDiagnosticPiece> &p) {
-                      return isa<PathDiagnosticNotePiece>(*p);
-                    });
+  std::string report = GenerateHTML(D, R, SMgr, path, declName.c_str());
+  if (report.empty()) {
+    llvm::errs() << "warning: no diagnostics generated for main file.\n";
+    return;
+  }
 
-  unsigned TotalRegularPieces = TotalPieces - TotalNotePieces;
-  unsigned NumRegularPieces = TotalRegularPieces;
-  unsigned NumNotePieces = TotalNotePieces;
+  // Create a path for the target HTML file.
+  int FD;
+  SmallString<128> Model, ResultPath;
 
-  for (auto I = path.rbegin(), E = path.rend(); I != E; ++I) {
-    if (isa<PathDiagnosticNotePiece>(I->get())) {
-      // 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, **I, NumNotePieces, TotalNotePieces);
-      --NumNotePieces;
-    } else {
-      HandlePiece(R, FID, **I, NumRegularPieces, TotalRegularPieces);
-      --NumRegularPieces;
-    }
+  if (!AnalyzerOpts.shouldWriteStableReportFilename()) {
+      llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
+      if (std::error_code EC =
+          llvm::sys::fs::make_absolute(Model)) {
+          llvm::errs() << "warning: could not make '" << Model
+                       << "' absolute: " << EC.message() << '\n';
+        return;
+      }
+      if (std::error_code EC =
+          llvm::sys::fs::createUniqueFile(Model, FD, ResultPath)) {
+          llvm::errs() << "warning: could not create file in '" << Directory
+                       << "': " << EC.message() << '\n';
+          return;
+      }
+
+  } else {
+      int i = 1;
+      std::error_code EC;
+      do {
+          // Find a filename which is not already used
+          const FileEntry* Entry = SMgr.getFileEntryForID(ReportFile);
+          std::stringstream filename;
+          Model = "";
+          filename << "report-"
+                   << llvm::sys::path::filename(Entry->getName()).str()
+                   << "-" << declName.c_str()
+                   << "-" << offsetDecl
+                   << "-" << i << ".html";
+          llvm::sys::path::append(Model, Directory,
+                                  filename.str());
+          EC = llvm::sys::fs::openFileForWrite(Model,
+                                               FD,
+                                               llvm::sys::fs::F_RW |
+                                               llvm::sys::fs::F_Excl);
+          if (EC && EC != llvm::errc::file_exists) {
+              llvm::errs() << "warning: could not create file '" << Model
+                           << "': " << EC.message() << '\n';
+              return;
+          }
+          i++;
+      } while (EC);
   }
 
-  // Add line numbers, header, footer, etc.
+  llvm::raw_fd_ostream os(FD, true);
 
-  // unsigned FID = R.getSourceMgr().getMainFileID();
-  html::EscapeText(R, FID);
-  html::AddLineNumbers(R, FID);
+  if (filesMade)
+    filesMade->addDiagnostic(D, getName(),
+                             llvm::sys::path::filename(ResultPath));
 
-  // 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.
+  // Emit the HTML to disk.
+  os << report;
+}
 
-  html::SyntaxHighlight(R, FID, PP);
-  html::HighlightMacros(R, FID, PP);
+std::string HTMLDiagnostics::GenerateHTML(const PathDiagnostic& D, Rewriter &R,
+    const SourceManager& SMgr, const PathPieces& path, const char *declName) {
+
+  // Rewrite source files as HTML for every new file the path crosses
+  std::vector<FileID> FileIDs;
+  for (auto I : path) {
+    FileID FID = I->getLocation().asLocation().getExpansionLoc().getFileID();
+    if (std::find(FileIDs.begin(), FileIDs.end(), FID) != FileIDs.end())
+      continue;
+
+    FileIDs.push_back(FID);
+    RewriteFile(R, SMgr, path, FID);
+  }
+
+  if (SupportsCrossFileDiagnostics && FileIDs.size() > 1) {
+    // Prefix file names, anchor tags, and nav cursors to every file
+    for (auto I = FileIDs.begin(), E = FileIDs.end(); I != E; I++) {
+      std::string s;
+      llvm::raw_string_ostream os(s);
+
+      if (I != FileIDs.begin())
+        os << "<hr class=divider>\n";
+
+      os << "<div id=File" << I->getHashValue() << ">\n";
+
+      // Left nav arrow
+      if (I != FileIDs.begin())
+        os << "<div class=FileNav><a href=\"#File" << (I - 1)->getHashValue()
+           << "\">&#x2190;</a></div>";
 
-  // Get the full directory name of the analyzed file.
+      os << "<h4 class=FileName>" << SMgr.getFileEntryForID(*I)->getName()
+         << "</h4>\n";
 
-  const FileEntry* Entry = SMgr.getFileEntryForID(FID);
+      // Right nav arrow
+      if (I + 1 != E)
+        os << "<div class=FileNav><a href=\"#File" << (I + 1)->getHashValue()
+           << "\">&#x2192;</a></div>";
 
+      os << "</div>\n";
+
+      R.InsertTextBefore(SMgr.getLocForStartOfFile(*I), os.str());
+    }
+
+    // Append files to the main report file in the order they appear in the path
+    for (auto I : llvm::make_range(FileIDs.begin() + 1, FileIDs.end())) {
+      std::string s;
+      llvm::raw_string_ostream os(s);
+
+      const RewriteBuffer *Buf = R.getRewriteBufferFor(I);
+      for (auto BI : *Buf)
+        os << BI;
+
+      R.InsertTextAfter(SMgr.getLocForEndOfFile(FileIDs[0]), os.str());
+    }
+  }
+
+  const RewriteBuffer *Buf = R.getRewriteBufferFor(FileIDs[0]);
+  if (!Buf)
+    return "";
+
+  // Add CSS, header, and footer.
+  const FileEntry* Entry = SMgr.getFileEntryForID(FileIDs[0]);
+  FinalizeHTML(D, R, SMgr, path, FileIDs[0], Entry, declName);
+
+  std::string file;
+  llvm::raw_string_ostream os(file);
+  for (auto BI : *Buf)
+    os << BI;
+
+  return os.str();
+}
+
+void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
+    const SourceManager& SMgr, const PathPieces& path, FileID FID,
+    const FileEntry *Entry, const char *declName) {
   // This is a cludge; basically we want to append either the full
   // working directory if we have no directory information.  This is
   // a work in progress.
@@ -306,73 +435,48 @@ void HTMLDiagnostics::ReportDiag(const P
     R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
   }
 
-  // Add CSS, header, and footer.
-
   html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName());
+}
 
-  // Get the rewrite buffer.
-  const RewriteBuffer *Buf = R.getRewriteBufferFor(FID);
-
-  if (!Buf) {
-    llvm::errs() << "warning: no diagnostics generated for main file.\n";
-    return;
-  }
-
-  // Create a path for the target HTML file.
-  int FD;
-  SmallString<128> Model, ResultPath;
+void HTMLDiagnostics::RewriteFile(Rewriter &R, const SourceManager& SMgr,
+    const PathPieces& path, FileID FID) {
+  // Process the path.
+  // Maintain the counts of extra note pieces separately.
+  unsigned TotalPieces = path.size();
+  unsigned TotalNotePieces =
+      std::count_if(path.begin(), path.end(),
+                    [](const std::shared_ptr<PathDiagnosticPiece> &p) {
+                      return isa<PathDiagnosticNotePiece>(*p);
+                    });
 
-  if (!AnalyzerOpts.shouldWriteStableReportFilename()) {
-      llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
-      if (std::error_code EC =
-          llvm::sys::fs::make_absolute(Model)) {
-          llvm::errs() << "warning: could not make '" << Model
-                       << "' absolute: " << EC.message() << '\n';
-        return;
-      }
-      if (std::error_code EC =
-          llvm::sys::fs::createUniqueFile(Model, FD, ResultPath)) {
-          llvm::errs() << "warning: could not create file in '" << Directory
-                       << "': " << EC.message() << '\n';
-          return;
-      }
+  unsigned TotalRegularPieces = TotalPieces - TotalNotePieces;
+  unsigned NumRegularPieces = TotalRegularPieces;
+  unsigned NumNotePieces = TotalNotePieces;
 
-  } else {
-      int i = 1;
-      std::error_code EC;
-      do {
-          // Find a filename which is not already used
-          std::stringstream filename;
-          Model = "";
-          filename << "report-"
-                   << llvm::sys::path::filename(Entry->getName()).str()
-                   << "-" << declName.c_str()
-                   << "-" << offsetDecl
-                   << "-" << i << ".html";
-          llvm::sys::path::append(Model, Directory,
-                                  filename.str());
-          EC = llvm::sys::fs::openFileForWrite(Model,
-                                               FD,
-                                               llvm::sys::fs::F_RW |
-                                               llvm::sys::fs::F_Excl);
-          if (EC && EC != llvm::errc::file_exists) {
-              llvm::errs() << "warning: could not create file '" << Model
-                           << "': " << EC.message() << '\n';
-              return;
-          }
-          i++;
-      } while (EC);
+  for (auto I = path.rbegin(), E = path.rend(); I != E; ++I) {
+    if (isa<PathDiagnosticNotePiece>(I->get())) {
+      // 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, **I, NumNotePieces, TotalNotePieces);
+      --NumNotePieces;
+    } else {
+      HandlePiece(R, FID, **I, NumRegularPieces, TotalRegularPieces);
+      --NumRegularPieces;
+    }
   }
 
-  llvm::raw_fd_ostream os(FD, true);
+  // Add line numbers, header, footer, etc.
 
-  if (filesMade)
-    filesMade->addDiagnostic(D, getName(),
-                             llvm::sys::path::filename(ResultPath));
+  html::EscapeText(R, FID);
+  html::AddLineNumbers(R, FID);
 
-  // Emit the HTML to disk.
-  for (RewriteBuffer::iterator I = Buf->begin(), E = Buf->end(); I!=E; ++I)
-      os << *I;
+  // 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,

Removed: cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.c?rev=309967&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.c (original)
+++ cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.c (removed)
@@ -1,12 +0,0 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=html -o PR12421.html %s 2>&1 | FileCheck %s
-
-// Test for PR12421
-#include "diag-cross-file-boundaries.h"
-
-int main(){
-  f();
-  return 0;
-}
-
-// CHECK: warning: Path diagnostic report is not generated.

Removed: cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.h?rev=309967&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.h (original)
+++ cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.h (removed)
@@ -1,4 +0,0 @@
-static void f() {
-  int *p = 0;
-  *p = 1;       // expected-warning{{Dereference of null pointer}}
-}

Added: cfe/trunk/test/Analysis/html-diag-singlefile.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/html-diag-singlefile.c?rev=309968&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/html-diag-singlefile.c (added)
+++ cfe/trunk/test/Analysis/html-diag-singlefile.c Thu Aug  3 11:12:22 2017
@@ -0,0 +1,14 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=html-single-file -o D30406.html %s 2>&1 | FileCheck %s
+
+// Check that single file HTML output does not process multi-file diagnostics.
+// (This used to test for PR12421, before the introduction of the html-single-file format)
+
+#include "html-diag-singlefile.h"
+
+int main(){
+  f();
+  return 0;
+}
+
+// CHECK: warning: Path diagnostic report is not generated.

Copied: cfe/trunk/test/Analysis/html-diag-singlefile.h (from r309960, cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.h)
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/html-diag-singlefile.h?p2=cfe/trunk/test/Analysis/html-diag-singlefile.h&p1=cfe/trunk/test/Analysis/diagnostics/diag-cross-file-boundaries.h&r1=309960&r2=309968&rev=309968&view=diff
==============================================================================
    (empty)

Added: cfe/trunk/test/Analysis/html-diags-analyze-headers.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/html-diags-analyze-headers.c?rev=309968&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/html-diags-analyze-headers.c (added)
+++ cfe/trunk/test/Analysis/html-diags-analyze-headers.c Thu Aug  3 11:12:22 2017
@@ -0,0 +1,10 @@
+// RUN: mkdir -p %t.dir
+// RUN: %clang_analyze_cc1 -analyzer-opt-analyze-headers -analyzer-output=html -analyzer-checker=core -o %t.dir %s
+// RUN: ls %t.dir | grep report
+// RUN: rm -rf %t.dir
+
+// This tests that we emit HTML diagnostics for reports in headers when the
+// analyzer is run with -analyzer-opt-analyze-headers. This was handled
+// incorrectly in the first iteration of D30406.
+
+#include "html-diags-analyze-headers.h"

Added: cfe/trunk/test/Analysis/html-diags-analyze-headers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/html-diags-analyze-headers.h?rev=309968&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/html-diags-analyze-headers.h (added)
+++ cfe/trunk/test/Analysis/html-diags-analyze-headers.h Thu Aug  3 11:12:22 2017
@@ -0,0 +1,5 @@
+#include "html-diags-multifile.h"
+
+void test_call_macro() {
+  has_bug(0);
+}

Modified: cfe/trunk/test/Analysis/html-diags-multifile.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/html-diags-multifile.c?rev=309968&r1=309967&r2=309968&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/html-diags-multifile.c (original)
+++ cfe/trunk/test/Analysis/html-diags-multifile.c Thu Aug  3 11:12:22 2017
@@ -1,10 +1,9 @@
 // RUN: mkdir -p %t.dir
 // RUN: %clang_analyze_cc1 -analyzer-output=html -analyzer-checker=core -o %t.dir %s
-// RUN: ls %t.dir | not grep report
+// RUN: ls %t.dir | grep report
 // RUN: rm -fR %t.dir
 
-// This tests that we do not currently emit HTML diagnostics for reports that
-// cross file boundaries.
+// This tests that we emit HTML diagnostics for reports that cross file boundaries.
 
 #include "html-diags-multifile.h"
 

Modified: cfe/trunk/test/Analysis/html-diags.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/html-diags.c?rev=309968&r1=309967&r2=309968&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/html-diags.c (original)
+++ cfe/trunk/test/Analysis/html-diags.c Thu Aug  3 11:12:22 2017
@@ -3,6 +3,12 @@
 // RUN: %clang_analyze_cc1 -analyzer-output=html -analyzer-checker=core -o %T/dir %s
 // RUN: ls %T/dir | grep report
 
+// D30406: Test new html-single-file output
+// RUN: rm -fR %T/dir
+// RUN: mkdir %T/dir
+// RUN: %clang_analyze_cc1 -analyzer-output=html-single-file -analyzer-checker=core -o %T/dir %s
+// RUN: ls %T/dir | grep report
+
 // PR16547: Test relative paths
 // RUN: cd %T/dir
 // RUN: %clang_analyze_cc1 -analyzer-output=html -analyzer-checker=core -o testrelative %s

Modified: cfe/trunk/test/Coverage/html-diagnostics.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Coverage/html-diagnostics.c?rev=309968&r1=309967&r2=309968&view=diff
==============================================================================
--- cfe/trunk/test/Coverage/html-diagnostics.c (original)
+++ cfe/trunk/test/Coverage/html-diagnostics.c Thu Aug  3 11:12:22 2017
@@ -1,11 +1,18 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -analyze -analyzer-output=html -analyzer-checker=core -o %t %s
 // RUN: find %t -name "*.html" -exec cat "{}" ";" | FileCheck %s
+//
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -analyze -analyzer-output=html-single-file -analyzer-checker=core -o %t %s
+// RUN: find %t -name "*.html" -exec cat "{}" ";" | FileCheck %s
 
 // REQUIRES: staticanalyzer
 
 // CHECK: <h3>Annotated Source Code</h3>
 
+// Make sure it's not generated as a multi-file HTML output
+// CHECK-NOT: <h4 class=FileName>{{.*}}
+
 // Without tweaking expr, the expr would hit to the line below
 // emitted to the output as comment.
 // CHECK: {{[D]ereference of null pointer}}

Copied: cfe/trunk/test/Coverage/html-multifile-diagnostics.c (from r309960, cfe/trunk/test/Coverage/html-diagnostics.c)
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Coverage/html-multifile-diagnostics.c?p2=cfe/trunk/test/Coverage/html-multifile-diagnostics.c&p1=cfe/trunk/test/Coverage/html-diagnostics.c&r1=309960&r2=309968&rev=309968&view=diff
==============================================================================
--- cfe/trunk/test/Coverage/html-diagnostics.c (original)
+++ cfe/trunk/test/Coverage/html-multifile-diagnostics.c Thu Aug  3 11:12:22 2017
@@ -6,19 +6,16 @@
 
 // CHECK: <h3>Annotated Source Code</h3>
 
+// Make sure it's generated as multi-file HTML output
+// CHECK: <h4 class=FileName>{{.*}}html-multifile-diagnostics.c</h4>
+// CHECK: <h4 class=FileName>{{.*}}html-multifile-diagnostics.h</h4>
+
 // Without tweaking expr, the expr would hit to the line below
 // emitted to the output as comment.
 // CHECK: {{[D]ereference of null pointer}}
 
-void f0(int x) {
-  int *p = &x;
-
-  if (x > 10) {
-    if (x == 22)
-      p = 0;
-  }
+#include "html-multifile-diagnostics.h"
 
-  *p = 10;
+void f0() {
+  f1((int*)0);
 }
-
-

Added: cfe/trunk/test/Coverage/html-multifile-diagnostics.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Coverage/html-multifile-diagnostics.h?rev=309968&view=auto
==============================================================================
--- cfe/trunk/test/Coverage/html-multifile-diagnostics.h (added)
+++ cfe/trunk/test/Coverage/html-multifile-diagnostics.h Thu Aug  3 11:12:22 2017
@@ -0,0 +1,3 @@
+void f1(int *ptr) {
+  *ptr = 0;
+}

Modified: cfe/trunk/www/analyzer/open_projects.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/analyzer/open_projects.html?rev=309968&r1=309967&r2=309968&view=diff
==============================================================================
--- cfe/trunk/www/analyzer/open_projects.html (original)
+++ cfe/trunk/www/analyzer/open_projects.html Thu Aug  3 11:12:22 2017
@@ -107,13 +107,6 @@ mailing list</a> to notify other members
 
   <li>Bug Reporting 
   <ul>
-    <li>Add support for displaying cross-file diagnostic paths in HTML output
-    (used by <tt>scan-build</tt>).
-    <p>Currently <tt>scan-build</tt> output does not display reports that span 
-    multiple files. The main problem is that we do not have a good format to
-    display such paths in HTML output. <i>(Difficulty: Medium)</i> </p>
-    </li>
-    
     <li>Refactor path diagnostic generation in <a href="http://clang.llvm.org/doxygen/BugReporter_8cpp_source.html">BugReporter.cpp</a>.
     <p>It would be great to have more code reuse between "Minimal" and 
     "Extensive" PathDiagnostic generation algorithms. One idea is to create an 




More information about the cfe-commits mailing list