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
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 BranchCoverageInfo
40sumBranchExpansions(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(Branches: CE.getBranches());
46 BranchCoverage += sumBranchExpansions(CM, Expansions: 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(Condition: C)) {
57 ++NumPairs;
58 if (Record.isConditionIndependencePairCovered(Condition: 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 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
92CoverageDataSummary::CoverageDataSummary(const CoverageData &CD,
93 ArrayRef<CountedRegion> CodeRegions) {
94 std::tie(args&: RegionCoverage, args&: LineCoverage) = sumRegions(CodeRegions, CD);
95 BranchCoverage = sumBranches(Branches: CD.getBranches());
96 MCDCCoverage = sumMCDCPairs(Records: CD.getMCDCRecords());
97}
98
99FunctionCoverageSummary
100FunctionCoverageSummary::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, Expansions: CD.getExpansions());
111
112 return Summary;
113}
114
115FunctionCoverageSummary
116FunctionCoverageSummary::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(RHS: FCS.RegionCoverage);
134 Summary.LineCoverage.merge(RHS: FCS.LineCoverage);
135 Summary.BranchCoverage.merge(RHS: FCS.BranchCoverage);
136 Summary.MCDCCoverage.merge(RHS: FCS.MCDCCoverage);
137 }
138 return Summary;
139}
140