This revision was automatically updated to reflect the committed changes. Closed by commit rC323251: [analyzer] Mark lines as relevant even if they weren't executed but have a… (authored by george.karpenkov, committed by ). Herald added a subscriber: cfe-commits.
Repository: rC Clang https://reviews.llvm.org/D42320 Files: lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp test/Analysis/html_diagnostics/relevant_lines/notexecutedlines.c
Index: test/Analysis/html_diagnostics/relevant_lines/notexecutedlines.c =================================================================== --- test/Analysis/html_diagnostics/relevant_lines/notexecutedlines.c +++ test/Analysis/html_diagnostics/relevant_lines/notexecutedlines.c @@ -0,0 +1,12 @@ +int f() { + int zzz = 200; + zzz += 100; + return 0; +} + +// Show line with the warning even if it wasn't executed (e.g. warning given +// by path-insensitive analysis). +// RUN: rm -rf %t.output +// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core,deadcode -analyzer-output html -o %t.output %s +// RUN: cat %t.output/* | FileCheck %s --match-full-lines +// CHECK: var relevant_lines = {"1": {"3": 1}}; Index: lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp =================================================================== --- lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -28,6 +28,8 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" +#include <map> +#include <set> #include <sstream> using namespace clang; @@ -96,11 +98,6 @@ std::string generateKeyboardNavigationJavascript(); private: - /// \return JavaScript for an option to only show relevant lines. - std::string showRelevantLinesJavascript(const PathDiagnostic &D); - - /// \return Executed lines from \p D in JSON format. - std::string serializeExecutedLines(const PathDiagnostic &D); /// \return Javascript for displaying shortcuts help; std::string showHelpJavascript(); @@ -333,6 +330,115 @@ return os.str(); } +/// Write executed lines from \p D in JSON format into \p os. +static void serializeExecutedLines( + const PathDiagnostic &D, + const PathPieces &path, + llvm::raw_string_ostream &os) { + + // Copy executed lines from path diagnostics. + std::map<unsigned, std::set<unsigned>> ExecutedLines; + for (auto I = D.executedLines_begin(), + E = D.executedLines_end(); I != E; ++I) { + std::set<unsigned> &LinesInFile = ExecutedLines[I->first]; + for (unsigned LineNo : I->second) { + LinesInFile.insert(LineNo); + } + } + + // We need to include all lines for which any kind of diagnostics appears. + for (const auto &P : path) { + FullSourceLoc Loc = P->getLocation().asLocation().getExpansionLoc(); + FileID FID = Loc.getFileID(); + unsigned LineNo = Loc.getLineNumber(); + ExecutedLines[FID.getHashValue()].insert(LineNo); + } + + os << "var relevant_lines = {"; + for (auto I = ExecutedLines.begin(), + E = ExecutedLines.end(); I != E; ++I) { + if (I != ExecutedLines.begin()) + os << ", "; + + os << "\"" << I->first << "\": {"; + for (unsigned LineNo : I->second) { + if (LineNo != *(I->second.begin())) + os << ", "; + + os << "\"" << LineNo << "\": 1"; + } + os << "}"; + } + + os << "};"; +} + +/// \return JavaScript for an option to only show relevant lines. +static std::string showRelevantLinesJavascript( + const PathDiagnostic &D, const PathPieces &path) { + std::string s; + llvm::raw_string_ostream os(s); + os << "<script type='text/javascript'>\n"; + serializeExecutedLines(D, path, os); + os << R"<<<( + +var filterCounterexample = function (hide) { + var tables = document.getElementsByClassName("code"); + for (var t=0; t<tables.length; t++) { + var table = tables[t]; + var file_id = table.getAttribute("data-fileid"); + var lines_in_fid = relevant_lines[file_id]; + if (!lines_in_fid) { + lines_in_fid = {}; + } + var lines = table.getElementsByClassName("codeline"); + for (var i=0; i<lines.length; i++) { + var el = lines[i]; + var lineNo = el.getAttribute("data-linenumber"); + if (!lines_in_fid[lineNo]) { + if (hide) { + el.setAttribute("hidden", ""); + } else { + el.removeAttribute("hidden"); + } + } + } + } +} + +window.addEventListener("keydown", function (event) { + if (event.defaultPrevented) { + return; + } + if (event.key == "S") { + var checked = document.getElementsByName("showCounterexample")[0].checked; + filterCounterexample(!checked); + document.getElementsByName("showCounterexample")[0].checked = !checked; + } else { + return; + } + event.preventDefault(); +}, true); + +document.addEventListener("DOMContentLoaded", function() { + document.querySelector('input[name="showCounterexample"]').onchange= + function (event) { + filterCounterexample(this.checked); + }; +}); +</script> + +<form> + <input type="checkbox" name="showCounterexample" id="showCounterexample" /> + <label for="showCounterexample"> + Show only relevant lines + </label> +</form> +)<<<"; + + 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) { @@ -357,7 +463,7 @@ // Checkbox and javascript for filtering the output to the counterexample. R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), - showRelevantLinesJavascript(D)); + showRelevantLinesJavascript(D, path)); // Add the name of the file as an <h1> tag. { @@ -507,93 +613,8 @@ )<<<"; } -std::string -HTMLDiagnostics::showRelevantLinesJavascript(const PathDiagnostic &D) { - std::string s; - llvm::raw_string_ostream os(s); - os << "<script type='text/javascript'>\n"; - os << serializeExecutedLines(D); - os << R"<<<( -var filterCounterexample = function (hide) { - var tables = document.getElementsByClassName("code"); - for (var t=0; t<tables.length; t++) { - var table = tables[t]; - var file_id = table.getAttribute("data-fileid"); - var lines_in_fid = relevant_lines[file_id]; - if (!lines_in_fid) { - lines_in_fid = {}; - } - var lines = table.getElementsByClassName("codeline"); - for (var i=0; i<lines.length; i++) { - var el = lines[i]; - var lineNo = el.getAttribute("data-linenumber"); - if (!lines_in_fid[lineNo]) { - if (hide) { - el.setAttribute("hidden", ""); - } else { - el.removeAttribute("hidden"); - } - } - } - } -} -window.addEventListener("keydown", function (event) { - if (event.defaultPrevented) { - return; - } - if (event.key == "S") { - var checked = document.getElementsByName("showCounterexample")[0].checked; - filterCounterexample(!checked); - document.getElementsByName("showCounterexample")[0].checked = !checked; - } else { - return; - } - event.preventDefault(); -}, true); - -document.addEventListener("DOMContentLoaded", function() { - document.querySelector('input[name="showCounterexample"]').onchange= - function (event) { - filterCounterexample(this.checked); - }; -}); -</script> - -<form> - <input type="checkbox" name="showCounterexample" /> - <label for="showCounterexample"> - Show only relevant lines - </label> -</form> -)<<<"; - - return os.str(); -} - -std::string HTMLDiagnostics::serializeExecutedLines(const PathDiagnostic &D) { - std::string s; - llvm::raw_string_ostream os(s); - os << "var relevant_lines = {"; - for (auto I = D.executedLines_begin(), - E = D.executedLines_end(); I != E; ++I) { - if (I != D.executedLines_begin()) - os << ", "; - - os << "\"" << I->first << "\": {"; - for (unsigned LineNo : I->second) { - if (LineNo != *(I->second.begin())) - os << ", "; - - os << "\"" << LineNo << "\": 1"; - } - os << "}"; - } - - os << "};"; - return os.str(); -} void HTMLDiagnostics::RewriteFile(Rewriter &R, const SourceManager& SMgr, const PathPieces& path, FileID FID) { @@ -1007,7 +1028,7 @@ navigateTo(/*up=*/true); } else { return; - } + } event.preventDefault(); }, true); </script>
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits