140 lines · cpp
1//===- CoverageSummaryInfo.cpp - Coverage summary for function/file -------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// These structures are used to represent code coverage metrics10// for functions/files.11//12//===----------------------------------------------------------------------===//13 14#include "CoverageSummaryInfo.h"15 16using namespace llvm;17using namespace coverage;18 19static auto sumBranches(const ArrayRef<CountedRegion> &Branches) {20 size_t NumBranches = 0;21 size_t CoveredBranches = 0;22 for (const auto &BR : Branches) {23 if (!BR.TrueFolded) {24 // "True" Condition Branches.25 ++NumBranches;26 if (BR.ExecutionCount > 0)27 ++CoveredBranches;28 }29 if (!BR.FalseFolded) {30 // "False" Condition Branches.31 ++NumBranches;32 if (BR.FalseExecutionCount > 0)33 ++CoveredBranches;34 }35 }36 return BranchCoverageInfo(CoveredBranches, NumBranches);37}38 39static BranchCoverageInfo40sumBranchExpansions(const CoverageMapping &CM,41 ArrayRef<ExpansionRecord> Expansions) {42 BranchCoverageInfo BranchCoverage;43 for (const auto &Expansion : Expansions) {44 auto CE = CM.getCoverageForExpansion(Expansion);45 BranchCoverage += sumBranches(CE.getBranches());46 BranchCoverage += sumBranchExpansions(CM, CE.getExpansions());47 }48 return BranchCoverage;49}50 51auto sumMCDCPairs(const ArrayRef<MCDCRecord> &Records) {52 size_t NumPairs = 0, CoveredPairs = 0;53 for (const auto &Record : Records) {54 const auto NumConditions = Record.getNumConditions();55 for (unsigned C = 0; C < NumConditions; C++) {56 if (!Record.isCondFolded(C)) {57 ++NumPairs;58 if (Record.isConditionIndependencePairCovered(C))59 ++CoveredPairs;60 }61 }62 }63 return MCDCCoverageInfo(CoveredPairs, NumPairs);64}65 66static std::pair<RegionCoverageInfo, LineCoverageInfo>67sumRegions(ArrayRef<CountedRegion> CodeRegions, const CoverageData &CD) {68 // Compute the region coverage.69 size_t NumCodeRegions = 0, CoveredRegions = 0;70 for (auto &CR : CodeRegions) {71 if (CR.Kind != CounterMappingRegion::CodeRegion)72 continue;73 ++NumCodeRegions;74 if (CR.ExecutionCount != 0)75 ++CoveredRegions;76 }77 78 // Compute the line coverage79 size_t NumLines = 0, CoveredLines = 0;80 for (const auto &LCS : getLineCoverageStats(CD)) {81 if (!LCS.isMapped())82 continue;83 ++NumLines;84 if (LCS.getExecutionCount())85 ++CoveredLines;86 }87 88 return {RegionCoverageInfo(CoveredRegions, NumCodeRegions),89 LineCoverageInfo(CoveredLines, NumLines)};90}91 92CoverageDataSummary::CoverageDataSummary(const CoverageData &CD,93 ArrayRef<CountedRegion> CodeRegions) {94 std::tie(RegionCoverage, LineCoverage) = sumRegions(CodeRegions, CD);95 BranchCoverage = sumBranches(CD.getBranches());96 MCDCCoverage = sumMCDCPairs(CD.getMCDCRecords());97}98 99FunctionCoverageSummary100FunctionCoverageSummary::get(const CoverageMapping &CM,101 const coverage::FunctionRecord &Function) {102 CoverageData CD = CM.getCoverageForFunction(Function);103 104 auto Summary =105 FunctionCoverageSummary(Function.Name, Function.ExecutionCount);106 107 Summary += CoverageDataSummary(CD, Function.CountedRegions);108 109 // Compute the branch coverage, including branches from expansions.110 Summary.BranchCoverage += sumBranchExpansions(CM, CD.getExpansions());111 112 return Summary;113}114 115FunctionCoverageSummary116FunctionCoverageSummary::get(const InstantiationGroup &Group,117 ArrayRef<FunctionCoverageSummary> Summaries) {118 std::string Name;119 if (Group.hasName()) {120 Name = std::string(Group.getName());121 } else {122 llvm::raw_string_ostream OS(Name);123 OS << "Definition at line " << Group.getLine() << ", column "124 << Group.getColumn();125 }126 127 FunctionCoverageSummary Summary(Name, Group.getTotalExecutionCount());128 Summary.RegionCoverage = Summaries[0].RegionCoverage;129 Summary.LineCoverage = Summaries[0].LineCoverage;130 Summary.BranchCoverage = Summaries[0].BranchCoverage;131 Summary.MCDCCoverage = Summaries[0].MCDCCoverage;132 for (const auto &FCS : Summaries.drop_front()) {133 Summary.RegionCoverage.merge(FCS.RegionCoverage);134 Summary.LineCoverage.merge(FCS.LineCoverage);135 Summary.BranchCoverage.merge(FCS.BranchCoverage);136 Summary.MCDCCoverage.merge(FCS.MCDCCoverage);137 }138 return Summary;139}140