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 void sumBranches(size_t &NumBranches, size_t &CoveredBranches, 20 const ArrayRef<CountedRegion> &Branches) { 21 for (const auto &BR : Branches) { 22 // Skip folded branches. 23 if (BR.Folded) 24 continue; 25 26 // "True" Condition Branches. 27 ++NumBranches; 28 if (BR.ExecutionCount > 0) 29 ++CoveredBranches; 30 // "False" Condition Branches. 31 ++NumBranches; 32 if (BR.FalseExecutionCount > 0) 33 ++CoveredBranches; 34 } 35 } 36 37 static void sumBranchExpansions(size_t &NumBranches, size_t &CoveredBranches, 38 const CoverageMapping &CM, 39 ArrayRef<ExpansionRecord> Expansions) { 40 for (const auto &Expansion : Expansions) { 41 auto CE = CM.getCoverageForExpansion(Expansion); 42 sumBranches(NumBranches, CoveredBranches, CE.getBranches()); 43 sumBranchExpansions(NumBranches, CoveredBranches, CM, CE.getExpansions()); 44 } 45 } 46 47 static std::pair<size_t, size_t> 48 sumMCDCPairs(const ArrayRef<MCDCRecord> &Records) { 49 size_t NumPairs = 0, CoveredPairs = 0; 50 for (const auto &Record : Records) { 51 const auto NumConditions = Record.getNumConditions(); 52 for (unsigned C = 0; C < NumConditions; C++) { 53 if (!Record.isCondFolded(C)) 54 ++NumPairs; 55 if (Record.isConditionIndependencePairCovered(C)) 56 ++CoveredPairs; 57 } 58 } 59 return {NumPairs, CoveredPairs}; 60 } 61 62 FunctionCoverageSummary 63 FunctionCoverageSummary::get(const CoverageMapping &CM, 64 const coverage::FunctionRecord &Function) { 65 // Compute the region coverage. 66 size_t NumCodeRegions = 0, CoveredRegions = 0; 67 for (auto &CR : Function.CountedRegions) { 68 if (CR.Kind != CounterMappingRegion::CodeRegion) 69 continue; 70 ++NumCodeRegions; 71 if (CR.ExecutionCount != 0) 72 ++CoveredRegions; 73 } 74 75 // Compute the line coverage 76 size_t NumLines = 0, CoveredLines = 0; 77 CoverageData CD = CM.getCoverageForFunction(Function); 78 for (const auto &LCS : getLineCoverageStats(CD)) { 79 if (!LCS.isMapped()) 80 continue; 81 ++NumLines; 82 if (LCS.getExecutionCount()) 83 ++CoveredLines; 84 } 85 86 // Compute the branch coverage, including branches from expansions. 87 size_t NumBranches = 0, CoveredBranches = 0; 88 sumBranches(NumBranches, CoveredBranches, CD.getBranches()); 89 sumBranchExpansions(NumBranches, CoveredBranches, CM, CD.getExpansions()); 90 91 size_t NumPairs = 0, CoveredPairs = 0; 92 std::tie(NumPairs, CoveredPairs) = sumMCDCPairs(CD.getMCDCRecords()); 93 94 return FunctionCoverageSummary( 95 Function.Name, Function.ExecutionCount, 96 RegionCoverageInfo(CoveredRegions, NumCodeRegions), 97 LineCoverageInfo(CoveredLines, NumLines), 98 BranchCoverageInfo(CoveredBranches, NumBranches), 99 MCDCCoverageInfo(CoveredPairs, NumPairs)); 100 } 101 102 FunctionCoverageSummary 103 FunctionCoverageSummary::get(const InstantiationGroup &Group, 104 ArrayRef<FunctionCoverageSummary> Summaries) { 105 std::string Name; 106 if (Group.hasName()) { 107 Name = std::string(Group.getName()); 108 } else { 109 llvm::raw_string_ostream OS(Name); 110 OS << "Definition at line " << Group.getLine() << ", column " 111 << Group.getColumn(); 112 } 113 114 FunctionCoverageSummary Summary(Name); 115 Summary.ExecutionCount = Group.getTotalExecutionCount(); 116 Summary.RegionCoverage = Summaries[0].RegionCoverage; 117 Summary.LineCoverage = Summaries[0].LineCoverage; 118 Summary.BranchCoverage = Summaries[0].BranchCoverage; 119 Summary.MCDCCoverage = Summaries[0].MCDCCoverage; 120 for (const auto &FCS : Summaries.drop_front()) { 121 Summary.RegionCoverage.merge(FCS.RegionCoverage); 122 Summary.LineCoverage.merge(FCS.LineCoverage); 123 Summary.BranchCoverage.merge(FCS.BranchCoverage); 124 Summary.MCDCCoverage.merge(FCS.MCDCCoverage); 125 } 126 return Summary; 127 } 128