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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // These structures are used to represent code coverage metrics 10 // for functions/files. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "CoverageSummaryInfo.h" 15 16 using namespace llvm; 17 using namespace coverage; 18 19 static 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 39 static BranchCoverageInfo 40 sumBranchExpansions(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 51 auto 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 66 static std::pair<RegionCoverageInfo, LineCoverageInfo> 67 sumRegions(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 coverage 79 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 92 CoverageDataSummary::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 99 FunctionCoverageSummary 100 FunctionCoverageSummary::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 115 FunctionCoverageSummary 116 FunctionCoverageSummary::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