diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h index 72b66db271f1b..39acbedf0ca83 100644 --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -1023,7 +1023,9 @@ class CoverageMapping { /// The given filename must be the name as recorded in the coverage /// information. That is, only names returned from getUniqueSourceFiles will /// yield a result. - CoverageData getCoverageForFile(StringRef Filename) const; + CoverageData getCoverageForFile( + StringRef Filename, + const DenseSet &FilteredOutFunctions = {}) const; /// Get the coverage for a particular function. CoverageData getCoverageForFunction(const FunctionRecord &Function) const; diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index e6a789c16cdf7..bff22e2d6be9a 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -1448,7 +1448,9 @@ static bool isExpansion(const CountedRegion &R, unsigned FileID) { return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID; } -CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const { +CoverageData CoverageMapping::getCoverageForFile( + StringRef Filename, + const DenseSet &FilteredOutFunctions) const { assert(SingleByteCoverage); MergeableCoverageData FileCoverage(*SingleByteCoverage, Filename); @@ -1458,6 +1460,8 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const { getImpreciseRecordIndicesForFilename(Filename); for (unsigned RecordIndex : RecordIndices) { const FunctionRecord &Function = Functions[RecordIndex]; + if (FilteredOutFunctions.count(&Function)) + continue; auto MainFileID = findMainViewFileID(Filename, Function); auto FileIDs = gatherFileIDs(Filename, Function); FileCoverage.addFunctionRegions( diff --git a/llvm/test/tools/llvm-cov/branch-macros.test b/llvm/test/tools/llvm-cov/branch-macros.test index b60da157810cf..469f24dbcd810 100644 --- a/llvm/test/tools/llvm-cov/branch-macros.test +++ b/llvm/test/tools/llvm-cov/branch-macros.test @@ -19,6 +19,6 @@ // FILE: Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover Branches Missed Branches Cover // FILE-NEXT: --- -// FILE-NEXT: branch-macros.cpp 16 4 75.00% 3 0 100.00% 32 0 100.00% 40 16 60.00% +// FILE-NEXT: branch-macros.cpp 28 5 82.14% 3 0 100.00% 39 0 100.00% 40 16 60.00% // FILE-NEXT: --- -// FILE-NEXT: TOTAL 16 4 75.00% 3 0 100.00% 32 0 100.00% 40 16 60.00% +// FILE-NEXT: TOTAL 28 5 82.14% 3 0 100.00% 39 0 100.00% 40 16 60.00% diff --git a/llvm/test/tools/llvm-cov/branch-templates.test b/llvm/test/tools/llvm-cov/branch-templates.test index d5535022239f5..594a3ca533678 100644 --- a/llvm/test/tools/llvm-cov/branch-templates.test +++ b/llvm/test/tools/llvm-cov/branch-templates.test @@ -26,6 +26,6 @@ // REPORTFILE: Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover Branches Missed Branches Cover // REPORTFILE-NEXT: --- -// REPORTFILE-NEXT: branch-templates.cpp 12 3 75.00% 2 0 100.00% 17 4 76.47% 8 4 50.00% +// REPORTFILE-NEXT: branch-templates.cpp 12 2 83.33% 2 0 100.00% 17 3 82.35% 12 6 50.00% // REPORTFILE-NEXT: --- -// REPORTFILE-NEXT: TOTAL 12 3 75.00% 2 0 100.00% 17 4 76.47% 8 4 50.00% +// REPORTFILE-NEXT: TOTAL 12 2 83.33% 2 0 100.00% 17 3 82.35% 12 6 50.00% diff --git a/llvm/test/tools/llvm-cov/coverage_watermark.test b/llvm/test/tools/llvm-cov/coverage_watermark.test index 5c48b4f0fb4bf..818baa470bc38 100644 --- a/llvm/test/tools/llvm-cov/coverage_watermark.test +++ b/llvm/test/tools/llvm-cov/coverage_watermark.test @@ -18,15 +18,15 @@ ORIGIN: ORIGIN: 100.00% (2/2) ORIGIN: ORIGIN: 100.00% (3/3) -ORIGIN: -ORIGIN: 75.00% (9/12) -ORIGIN: -ORIGIN: 66.67% (4/6) +ORIGIN: +ORIGIN: 83.33% (10/12) +ORIGIN: +ORIGIN: 83.33% (5/6) ORIGIN: ORIGIN: - (0/0) ORIGIN: -RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -format html -show-region-summary -show-instantiation-summary -o %t.html.dir -path-equivalence=/tmp,%S -coverage-watermark 80,70 %S/showTemplateInstantiations.cpp +RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -format html -show-region-summary -show-instantiation-summary -o %t.html.dir -path-equivalence=/tmp,%S -coverage-watermark 90,70 %S/showTemplateInstantiations.cpp RUN: FileCheck -check-prefix=DOWNGRADE1 %s -input-file %t.html.dir/index.html DOWNGRADE:1 Totals @@ -35,9 +35,9 @@ DOWNGRADE1: 100.00% (2/2) DOWNGRADE1: DOWNGRADE1: 100.00% (3/3) DOWNGRADE1: -DOWNGRADE1: 75.00% (9/12) -DOWNGRADE1: -DOWNGRADE1: 66.67% (4/6) +DOWNGRADE1: 83.33% (10/12) +DOWNGRADE1: +DOWNGRADE1: 83.33% (5/6) DOWNGRADE1: DOWNGRADE1: - (0/0) DOWNGRADE1: @@ -51,9 +51,9 @@ DOWNGRADE2: 100.00% (2/2) DOWNGRADE2: DOWNGRADE2: 100.00% (3/3) DOWNGRADE2: -DOWNGRADE2: 75.00% (9/12) -DOWNGRADE2: -DOWNGRADE2: 66.67% (4/6) +DOWNGRADE2: 83.33% (10/12) +DOWNGRADE2: +DOWNGRADE2: 83.33% (5/6) DOWNGRADE1: DOWNGRADE1: - (0/0) DOWNGRADE1: diff --git a/llvm/test/tools/llvm-cov/mcdc-templates-merge.test b/llvm/test/tools/llvm-cov/mcdc-templates-merge.test index cacd3b6bc6d84..3ba8d159b9a19 100644 --- a/llvm/test/tools/llvm-cov/mcdc-templates-merge.test +++ b/llvm/test/tools/llvm-cov/mcdc-templates-merge.test @@ -19,9 +19,9 @@ CHECK: 3 0 100.00% CHECK: 19 1 94.74% # Branches -CHECK: 11 3 72.73% +CHECK: 24 9 62.50% # MC/DC Conditions -CHECK: 4 2 50.00% +CHECK: 10 7 30.00% REPORT: TOTAL diff --git a/llvm/test/tools/llvm-cov/zeroFunctionFile.c b/llvm/test/tools/llvm-cov/zeroFunctionFile.c index f463007fe7f60..28caa5ac24165 100644 --- a/llvm/test/tools/llvm-cov/zeroFunctionFile.c +++ b/llvm/test/tools/llvm-cov/zeroFunctionFile.c @@ -16,5 +16,4 @@ int main() { // RUN: llvm-cov show -j 1 %S/Inputs/zeroFunctionFile.covmapping -format html -instr-profile %t.profdata -o %t.dir // RUN: FileCheck %s -input-file=%t.dir/index.html -check-prefix=HTML // HTML-NO: 0.00% (0/0) -// HTML: Files which contain no functions -// HTML: zeroFunctionFile.h +// HTML-NOT: Files which contain no functions diff --git a/llvm/tools/llvm-cov/CoverageReport.cpp b/llvm/tools/llvm-cov/CoverageReport.cpp index 00aea4039bfde..0046b968756dd 100644 --- a/llvm/tools/llvm-cov/CoverageReport.cpp +++ b/llvm/tools/llvm-cov/CoverageReport.cpp @@ -446,27 +446,47 @@ void CoverageReport::prepareSingleFileReport(const StringRef Filename, const coverage::CoverageMapping *Coverage, const CoverageViewOptions &Options, const unsigned LCP, FileCoverageSummary *FileReport, const CoverageFilter *Filters) { + DenseSet FilteredOutFunctions; + assert(FileReport->empty()); for (const auto &Group : Coverage->getInstantiationGroups(Filename)) { - std::vector InstantiationSummaries; + bool Updated = false; for (const coverage::FunctionRecord *F : Group.getInstantiations()) { - if (!Filters->matches(*Coverage, *F)) + if (!Filters->matches(*Coverage, *F)) { + FilteredOutFunctions.insert(F); continue; - auto InstantiationSummary = FunctionCoverageSummary::get(*Coverage, *F); - FileReport->addInstantiation(InstantiationSummary); - InstantiationSummaries.push_back(InstantiationSummary); + } + FileReport->InstantiationCoverage.addFunction( + /*Covered=*/F->ExecutionCount > 0); + Updated = true; } - if (InstantiationSummaries.empty()) + if (!Updated) continue; - auto GroupSummary = - FunctionCoverageSummary::get(Group, InstantiationSummaries); + if (Options.Debug) { + std::string Name; + if (Group.hasName()) { + Name = std::string(Group.getName()); + } else { + llvm::raw_string_ostream OS(Name); + OS << "Definition at line " << Group.getLine() << ", column " + << Group.getColumn(); + } - if (Options.Debug) - outs() << "InstantiationGroup: " << GroupSummary.Name << " with " + outs() << "InstantiationGroup: " << Name << " with " << "size = " << Group.size() << "\n"; + } - FileReport->addFunction(GroupSummary); + FileReport->FunctionCoverage.addFunction( + /*Covered=*/Group.getTotalExecutionCount() > 0); } + + auto FileCoverage = + Coverage->getCoverageForFile(Filename, FilteredOutFunctions); + if (FileCoverage.empty()) + return; + + *static_cast(FileReport) += + CoverageDataSummary(FileCoverage); } std::vector CoverageReport::prepareFileReports( diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp index 86d11266ecdd7..745a92103bccc 100644 --- a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp +++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp @@ -110,29 +110,3 @@ FunctionCoverageSummary::get(const CoverageMapping &CM, return Summary; } - -FunctionCoverageSummary -FunctionCoverageSummary::get(const InstantiationGroup &Group, - ArrayRef Summaries) { - std::string Name; - if (Group.hasName()) { - Name = std::string(Group.getName()); - } else { - llvm::raw_string_ostream OS(Name); - OS << "Definition at line " << Group.getLine() << ", column " - << Group.getColumn(); - } - - FunctionCoverageSummary Summary(Name, Group.getTotalExecutionCount()); - Summary.RegionCoverage = Summaries[0].RegionCoverage; - Summary.LineCoverage = Summaries[0].LineCoverage; - Summary.BranchCoverage = Summaries[0].BranchCoverage; - Summary.MCDCCoverage = Summaries[0].MCDCCoverage; - for (const auto &FCS : Summaries.drop_front()) { - Summary.RegionCoverage.merge(FCS.RegionCoverage); - Summary.LineCoverage.merge(FCS.LineCoverage); - Summary.BranchCoverage.merge(FCS.BranchCoverage); - Summary.MCDCCoverage.merge(FCS.MCDCCoverage); - } - return Summary; -} diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.h b/llvm/tools/llvm-cov/CoverageSummaryInfo.h index 42398ee06100e..09ceba5de7271 100644 --- a/llvm/tools/llvm-cov/CoverageSummaryInfo.h +++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.h @@ -41,11 +41,6 @@ class RegionCoverageInfo { return *this; } - void merge(const RegionCoverageInfo &RHS) { - Covered = std::max(Covered, RHS.Covered); - NumRegions = std::max(NumRegions, RHS.NumRegions); - } - size_t getCovered() const { return Covered; } size_t getNumRegions() const { return NumRegions; } @@ -82,11 +77,6 @@ class LineCoverageInfo { return *this; } - void merge(const LineCoverageInfo &RHS) { - Covered = std::max(Covered, RHS.Covered); - NumLines = std::max(NumLines, RHS.NumLines); - } - size_t getCovered() const { return Covered; } size_t getNumLines() const { return NumLines; } @@ -123,11 +113,6 @@ class BranchCoverageInfo { return *this; } - void merge(const BranchCoverageInfo &RHS) { - Covered = std::max(Covered, RHS.Covered); - NumBranches = std::max(NumBranches, RHS.NumBranches); - } - size_t getCovered() const { return Covered; } size_t getNumBranches() const { return NumBranches; } @@ -164,11 +149,6 @@ class MCDCCoverageInfo { return *this; } - void merge(const MCDCCoverageInfo &RHS) { - CoveredPairs = std::max(CoveredPairs, RHS.CoveredPairs); - NumPairs = std::max(NumPairs, RHS.NumPairs); - } - size_t getCoveredPairs() const { return CoveredPairs; } size_t getNumPairs() const { return NumPairs; } @@ -232,6 +212,13 @@ struct CoverageDataSummary { CoverageDataSummary() = default; CoverageDataSummary(const coverage::CoverageData &CD); + bool empty() const { + return (RegionCoverage.getNumRegions() == 0 && + LineCoverage.getNumLines() == 0 && + BranchCoverage.getNumBranches() == 0 && + MCDCCoverage.getNumPairs() == 0); + } + auto &operator+=(const CoverageDataSummary &RHS) { RegionCoverage += RHS.RegionCoverage; LineCoverage += RHS.LineCoverage; @@ -253,12 +240,6 @@ struct FunctionCoverageSummary : CoverageDataSummary { /// mapping record. static FunctionCoverageSummary get(const coverage::CoverageMapping &CM, const coverage::FunctionRecord &Function); - - /// Compute the code coverage summary for an instantiation group \p Group, - /// given a list of summaries for each instantiation in \p Summaries. - static FunctionCoverageSummary - get(const coverage::InstantiationGroup &Group, - ArrayRef Summaries); }; /// A summary of file's code coverage. @@ -270,24 +251,18 @@ struct FileCoverageSummary : CoverageDataSummary { FileCoverageSummary() = default; FileCoverageSummary(StringRef Name) : Name(Name) {} + bool empty() const { + return (CoverageDataSummary::empty() && + FunctionCoverage.getNumFunctions() == 0 && + InstantiationCoverage.getNumFunctions() == 0); + } + FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) { *static_cast(this) += RHS; FunctionCoverage += RHS.FunctionCoverage; InstantiationCoverage += RHS.InstantiationCoverage; return *this; } - - void addFunction(const FunctionCoverageSummary &Function) { - RegionCoverage += Function.RegionCoverage; - LineCoverage += Function.LineCoverage; - BranchCoverage += Function.BranchCoverage; - MCDCCoverage += Function.MCDCCoverage; - FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0); - } - - void addInstantiation(const FunctionCoverageSummary &Function) { - InstantiationCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0); - } }; /// A cache for demangled symbols. diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp index c94d3853fc014..e53f7618dc0bf 100644 --- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp +++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp @@ -23,6 +23,16 @@ using namespace llvm; namespace { +template +bool isSummaryEmpty(const SummaryTy &Report, const CoverageViewOptions &Opts) { + return !(Report.FunctionCoverage.getNumFunctions() || + (Opts.ShowInstantiationSummary && + Report.InstantiationCoverage.getNumFunctions()) || + (Opts.ShowRegionSummary && Report.RegionCoverage.getNumRegions()) || + (Opts.ShowBranchSummary && Report.BranchCoverage.getNumBranches()) || + (Opts.ShowMCDCSummary && Report.MCDCCoverage.getNumPairs())); +} + // Return a string with the special characters in \p Str escaped. std::string escape(StringRef Str, const CoverageViewOptions &Opts) { std::string TabExpandedResult; @@ -666,7 +676,7 @@ Error CoveragePrinterHTML::createIndexFile( Coverage, Totals, SourceFiles, Opts, Filters); bool EmptyFiles = false; for (unsigned I = 0, E = FileReports.size(); I < E; ++I) { - if (FileReports[I].FunctionCoverage.getNumFunctions()) + if (!isSummaryEmpty(FileReports[I], Opts)) emitFileSummary(OSRef, SourceFiles[I], FileReports[I]); else EmptyFiles = true; @@ -734,7 +744,7 @@ struct CoveragePrinterHTMLDirectory::Reporter : public DirectoryCoverageReport { // Make directories at the top of the table. for (auto &&SubDir : SubDirs) { auto &Report = SubDir.second.first; - if (!Report.FunctionCoverage.getNumFunctions()) + if (isSummaryEmpty(Report, Printer.Opts)) EmptyFiles.push_back(&Report); else emitTableRow(OSRef, Options, buildRelLinkToFile(Report.Name), Report, @@ -743,7 +753,7 @@ struct CoveragePrinterHTMLDirectory::Reporter : public DirectoryCoverageReport { for (auto &&SubFile : SubFiles) { auto &Report = SubFile.second; - if (!Report.FunctionCoverage.getNumFunctions()) + if (isSummaryEmpty(Report, Printer.Opts)) EmptyFiles.push_back(&Report); else emitTableRow(OSRef, Options, buildRelLinkToFile(Report.Name), Report,