xref: /llvm-project/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp (revision 6a9d0e53ae04a60222c8e39d8ced3183aa30588a)
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