| //===- CoverageSummaryInfo.cpp - Coverage summary for function/file -------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // These structures are used to represent code coverage metrics |
| // for functions/files. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "CoverageSummaryInfo.h" |
| |
| using namespace llvm; |
| using namespace coverage; |
| |
| static auto sumBranches(const ArrayRef<CountedRegion> &Branches) { |
| size_t NumBranches = 0; |
| size_t CoveredBranches = 0; |
| for (const auto &BR : Branches) { |
| if (!BR.TrueFolded) { |
| // "True" Condition Branches. |
| ++NumBranches; |
| if (BR.ExecutionCount > 0) |
| ++CoveredBranches; |
| } |
| if (!BR.FalseFolded) { |
| // "False" Condition Branches. |
| ++NumBranches; |
| if (BR.FalseExecutionCount > 0) |
| ++CoveredBranches; |
| } |
| } |
| return BranchCoverageInfo(CoveredBranches, NumBranches); |
| } |
| |
| static BranchCoverageInfo |
| sumBranchExpansions(const CoverageMapping &CM, |
| ArrayRef<ExpansionRecord> Expansions) { |
| BranchCoverageInfo BranchCoverage; |
| for (const auto &Expansion : Expansions) { |
| auto CE = CM.getCoverageForExpansion(Expansion); |
| BranchCoverage += sumBranches(CE.getBranches()); |
| BranchCoverage += sumBranchExpansions(CM, CE.getExpansions()); |
| } |
| return BranchCoverage; |
| } |
| |
| auto sumMCDCPairs(const ArrayRef<MCDCRecord> &Records) { |
| size_t NumPairs = 0, CoveredPairs = 0; |
| for (const auto &Record : Records) { |
| const auto NumConditions = Record.getNumConditions(); |
| for (unsigned C = 0; C < NumConditions; C++) { |
| if (!Record.isCondFolded(C)) { |
| ++NumPairs; |
| if (Record.isConditionIndependencePairCovered(C)) |
| ++CoveredPairs; |
| } |
| } |
| } |
| return MCDCCoverageInfo(CoveredPairs, NumPairs); |
| } |
| |
| static std::pair<RegionCoverageInfo, LineCoverageInfo> |
| sumRegions(ArrayRef<CountedRegion> CodeRegions, const CoverageData &CD) { |
| // Compute the region coverage. |
| size_t NumCodeRegions = 0, CoveredRegions = 0; |
| for (auto &CR : CodeRegions) { |
| if (CR.Kind != CounterMappingRegion::CodeRegion) |
| continue; |
| ++NumCodeRegions; |
| if (CR.ExecutionCount != 0) |
| ++CoveredRegions; |
| } |
| |
| // Compute the line coverage |
| size_t NumLines = 0, CoveredLines = 0; |
| for (const auto &LCS : getLineCoverageStats(CD)) { |
| if (!LCS.isMapped()) |
| continue; |
| ++NumLines; |
| if (LCS.getExecutionCount()) |
| ++CoveredLines; |
| } |
| |
| return {RegionCoverageInfo(CoveredRegions, NumCodeRegions), |
| LineCoverageInfo(CoveredLines, NumLines)}; |
| } |
| |
| CoverageDataSummary::CoverageDataSummary(const CoverageData &CD, |
| ArrayRef<CountedRegion> CodeRegions) { |
| std::tie(RegionCoverage, LineCoverage) = sumRegions(CodeRegions, CD); |
| BranchCoverage = sumBranches(CD.getBranches()); |
| MCDCCoverage = sumMCDCPairs(CD.getMCDCRecords()); |
| } |
| |
| FunctionCoverageSummary |
| FunctionCoverageSummary::get(const CoverageMapping &CM, |
| const coverage::FunctionRecord &Function) { |
| CoverageData CD = CM.getCoverageForFunction(Function); |
| |
| auto Summary = |
| FunctionCoverageSummary(Function.Name, Function.ExecutionCount); |
| |
| Summary += CoverageDataSummary(CD, Function.CountedRegions); |
| |
| // Compute the branch coverage, including branches from expansions. |
| Summary.BranchCoverage += sumBranchExpansions(CM, CD.getExpansions()); |
| |
| return Summary; |
| } |
| |
| FunctionCoverageSummary |
| FunctionCoverageSummary::get(const InstantiationGroup &Group, |
| ArrayRef<FunctionCoverageSummary> 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; |
| } |