Index: test/tools/llvm-cov/native_separators.c
===================================================================
--- test/tools/llvm-cov/native_separators.c
+++ test/tools/llvm-cov/native_separators.c
@@ -19,3 +19,9 @@
// HTML: tools\llvm-cov\Inputs\native_separators.covmapping
int main() {}
+
+// Re-purpose this file to test that "Go to first unexecuted line" feature.
+
+// RUN: llvm-cov show %S/Inputs/native_separators.covmapping -instr-profile %t.profdata -filename-equivalence -format html -o %t.dir %s
+// RUN: FileCheck -input-file %t.dir/coverage/tmp/native_separators.c.html %s
+// CHECK:
Go to first unexecuted line
Index: test/tools/llvm-cov/showProjectSummary.cpp
===================================================================
--- test/tools/llvm-cov/showProjectSummary.cpp
+++ test/tools/llvm-cov/showProjectSummary.cpp
@@ -24,9 +24,9 @@
// Test html output.
// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata -filename-equivalence %s
-// RUN: FileCheck -check-prefixes=HTML,HTML-FILE,HTML-HEADER -input-file %t.dir/coverage/tmp/showProjectSummary.cpp.html %s
+// RUN: FileCheck -check-prefixes=HTML,HTML-FILE,HTML-HEADER,HTML-UNCOVEREDLINE -input-file %t.dir/coverage/tmp/showProjectSummary.cpp.html %s
// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata -project-title "Test Suite" -filename-equivalence %s
-// RUN: FileCheck -check-prefixes=HTML-TITLE,HTML,HTML-FILE,HTML-HEADER -input-file %t.dir/coverage/tmp/showProjectSummary.cpp.html %s
+// RUN: FileCheck -check-prefixes=HTML-TITLE,HTML,HTML-FILE,HTML-HEADER,HTML-UNCOVEREDLINE -input-file %t.dir/coverage/tmp/showProjectSummary.cpp.html %s
// RUN: FileCheck -check-prefixes=HTML-TITLE,HTML -input-file %t.dir/index.html %s
// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata -project-title "Test Suite" -filename-equivalence -name=main %s
// RUN: FileCheck -check-prefixes=HTML-FUNCTION,HTML-HEADER -input-file %t.dir/functions.html %s
@@ -41,6 +41,7 @@
// HTML-FILE: Binary:
// HTML-FILE: showProjectSummary.covmapping
// HTML-FUNCTION: Function: main
+// HTML-UNCOVEREDLINE: Go to first unexecuted line
// HTML-HEADER: Line No. |
// HTML-HEADER: Count |
// HTML-HEADER: Source |
Index: tools/llvm-cov/CodeCoverage.cpp
===================================================================
--- tools/llvm-cov/CodeCoverage.cpp
+++ tools/llvm-cov/CodeCoverage.cpp
@@ -693,6 +693,12 @@
for (StringRef SourceFile : SourceFiles) {
Pool.async([this, SourceFile, &Coverage, &Printer, ShowFilenames] {
+ FileCoverageSummary Summary(SourceFile);
+ for (const auto &F : Coverage->getCoveredFunctions(SourceFile)) {
+ FunctionCoverageSummary Function = FunctionCoverageSummary::get(F);
+ Summary.addFunction(Function);
+ }
+ bool IsFullyCovered = Summary.LineCoverage.isFullyCovered();
auto View = createSourceFileView(SourceFile, *Coverage);
if (!View) {
warning("The file '" + SourceFile.str() + "' isn't covered.");
@@ -707,7 +713,8 @@
auto OS = std::move(OSOrErr.get());
View->print(*OS.get(), /*Wholefile=*/true,
- /*ShowSourceName=*/ShowFilenames);
+ /*ShowSourceName=*/ShowFilenames, /*ViewDepth=*/0,
+ /*FullyCovered=*/IsFullyCovered);
Printer->closeViewFile(std::move(OS));
});
}
Index: tools/llvm-cov/SourceCoverageView.h
===================================================================
--- tools/llvm-cov/SourceCoverageView.h
+++ tools/llvm-cov/SourceCoverageView.h
@@ -195,7 +195,8 @@
virtual void renderViewFooter(raw_ostream &OS) = 0;
/// \brief Render the source name for the view.
- virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0;
+ virtual void renderSourceName(raw_ostream &OS, bool WholeFile,
+ bool FullyCovered, unsigned LineNo) = 0;
/// \brief Render the line prefix at the given \p ViewDepth.
virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0;
@@ -289,7 +290,7 @@
/// \brief Print the code coverage information for a specific portion of a
/// source file to the output stream.
void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName,
- unsigned ViewDepth = 0);
+ unsigned ViewDepth = 0, bool FullyCovered = false);
};
} // namespace llvm
Index: tools/llvm-cov/SourceCoverageView.cpp
===================================================================
--- tools/llvm-cov/SourceCoverageView.cpp
+++ tools/llvm-cov/SourceCoverageView.cpp
@@ -136,14 +136,43 @@
}
void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
- bool ShowSourceName, unsigned ViewDepth) {
+ bool ShowSourceName, unsigned ViewDepth,
+ bool FullyCovered) {
if (WholeFile)
renderCellInTitle(OS, "Code Coverage Report");
renderViewHeader(OS);
+ unsigned FirstUncoveredLineNo = 0;
+ if (!FullyCovered) {
+ // Get the first uncovered line for the file.
+ auto NextSegment = CoverageInfo.begin();
+ auto EndSegment = CoverageInfo.end();
+ SmallVector LineSegments;
+ for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof(); ++LI) {
+ bool IsUncoveredLine = true;
+ // Collect the coverage information relevant to this line.
+ LineSegments.clear();
+ while (NextSegment != EndSegment && NextSegment->Line == LI.line_number())
+ LineSegments.push_back(&*NextSegment++);
+
+ if (LineSegments.empty())
+ continue;
+ for (const auto *S : LineSegments)
+ if (S->IsRegionEntry && S->HasCount && S->Count) {
+ IsUncoveredLine = false;
+ break;
+ }
+
+ if (IsUncoveredLine) {
+ FirstUncoveredLineNo = LI.line_number();
+ break;
+ }
+ }
+ }
+
if (ShowSourceName)
- renderSourceName(OS, WholeFile);
+ renderSourceName(OS, WholeFile, FullyCovered, FirstUncoveredLineNo);
renderTableHeader(OS, ViewDepth);
// We need the expansions and instantiations sorted so we can go through them
Index: tools/llvm-cov/SourceCoverageViewHTML.h
===================================================================
--- tools/llvm-cov/SourceCoverageViewHTML.h
+++ tools/llvm-cov/SourceCoverageViewHTML.h
@@ -38,7 +38,8 @@
void renderViewFooter(raw_ostream &OS) override;
- void renderSourceName(raw_ostream &OS, bool WholeFile) override;
+ void renderSourceName(raw_ostream &OS, bool WholeFile, bool FullyCovered,
+ unsigned LineNo) override;
void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override;
Index: tools/llvm-cov/SourceCoverageViewHTML.cpp
===================================================================
--- tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -338,7 +338,9 @@
OS << EndTable << EndCenteredDiv;
}
-void SourceCoverageViewHTML::renderSourceName(raw_ostream &OS, bool WholeFile) {
+void SourceCoverageViewHTML::renderSourceName(raw_ostream &OS, bool WholeFile,
+ bool FullyCovered,
+ unsigned LineNo) {
OS << BeginSourceNameDiv;
// Render the source name for the view.
std::string SourceFile = isFunctionView() ? "Function: " : "Source: ";
@@ -347,10 +349,16 @@
sys::path::remove_dots(SourceText, /*remove_dot_dots=*/true);
sys::path::native(SourceText);
OS << tag("pre", escape(SourceText, getOptions()));
- // Render the object file name for the view.
- if (WholeFile)
+ if (WholeFile) {
+ // Render the object file name for the view.
OS << tag("pre",
escape("Binary: " + getOptions().ObjectFilename, getOptions()));
+ // Render the "Go to first unexecuted line" link for the view.
+ std::string LinkText = escape("Go to first unexecuted line", getOptions());
+ std::string LinkTarget = "#L" + utostr(uint64_t(LineNo));
+ OS << (FullyCovered ? tag("pre", LinkText)
+ : tag("pre", a(LinkTarget, LinkText)));
+ }
OS << EndSourceNameDiv;
}
Index: tools/llvm-cov/SourceCoverageViewText.h
===================================================================
--- tools/llvm-cov/SourceCoverageViewText.h
+++ tools/llvm-cov/SourceCoverageViewText.h
@@ -38,7 +38,8 @@
void renderViewFooter(raw_ostream &OS) override;
- void renderSourceName(raw_ostream &OS, bool WholeFile) override;
+ void renderSourceName(raw_ostream &OS, bool WholeFile, bool FullyCovered,
+ unsigned LineNo) override;
void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override;
Index: tools/llvm-cov/SourceCoverageViewText.cpp
===================================================================
--- tools/llvm-cov/SourceCoverageViewText.cpp
+++ tools/llvm-cov/SourceCoverageViewText.cpp
@@ -63,7 +63,9 @@
void SourceCoverageViewText::renderViewFooter(raw_ostream &) {}
-void SourceCoverageViewText::renderSourceName(raw_ostream &OS, bool WholeFile) {
+void SourceCoverageViewText::renderSourceName(raw_ostream &OS, bool WholeFile,
+ bool FullyCovered,
+ unsigned LineNo) {
getOptions().colored_ostream(OS, raw_ostream::CYAN) << getSourceName()
<< ":\n";
if (WholeFile) {