blob: 899487205047d1d0d82c026502692f2b1c60b804 [file] [log] [blame]
Alex Lorenze82d89c2014-08-22 22:56:03 +00001//===- CoverageSummaryInfo.cpp - Coverage summary for function/file -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// These structures are used to represent code coverage metrics
11// for functions/files.
12//
13//===----------------------------------------------------------------------===//
14
15#include "CoverageSummaryInfo.h"
16
17using namespace llvm;
18using namespace coverage;
19
Vedant Kumarb7fdaf22017-09-19 02:00:12 +000020LineCoverageStats::LineCoverageStats(
21 ArrayRef<const coverage::CoverageSegment *> LineSegments,
Vedant Kumar1963f512017-10-14 02:27:29 +000022 const coverage::CoverageSegment *WrappedSegment, unsigned Line)
23 : ExecutionCount(0), HasMultipleRegions(false), Mapped(false), Line(Line),
24 LineSegments(LineSegments), WrappedSegment(WrappedSegment) {
Vedant Kumarb7fdaf22017-09-19 02:00:12 +000025 // Find the minimum number of regions which start in this line.
26 unsigned MinRegionCount = 0;
27 auto isStartOfRegion = [](const coverage::CoverageSegment *S) {
28 return !S->IsGapRegion && S->HasCount && S->IsRegionEntry;
29 };
30 for (unsigned I = 0; I < LineSegments.size() && MinRegionCount < 2; ++I)
31 if (isStartOfRegion(LineSegments[I]))
32 ++MinRegionCount;
33
34 bool StartOfSkippedRegion = !LineSegments.empty() &&
35 !LineSegments.front()->HasCount &&
36 LineSegments.front()->IsRegionEntry;
37
Vedant Kumarb7fdaf22017-09-19 02:00:12 +000038 HasMultipleRegions = MinRegionCount > 1;
39 Mapped =
40 !StartOfSkippedRegion &&
41 ((WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0));
42
43 if (!Mapped)
44 return;
45
46 // Pick the max count among regions which start and end on this line, to
47 // avoid erroneously using the wrapped count, and to avoid picking region
48 // counts which come from deferred regions.
49 if (LineSegments.size() > 1) {
50 for (unsigned I = 0; I < LineSegments.size() - 1; ++I) {
51 if (!LineSegments[I]->IsGapRegion)
52 ExecutionCount = std::max(ExecutionCount, LineSegments[I]->Count);
53 }
54 return;
55 }
56
57 // If a non-gap region starts here, use its count. Otherwise use the wrapped
58 // count.
59 if (MinRegionCount == 1)
60 ExecutionCount = LineSegments[0]->Count;
61 else
62 ExecutionCount = WrappedSegment->Count;
63}
64
Vedant Kumar1963f512017-10-14 02:27:29 +000065LineCoverageIterator &LineCoverageIterator::operator++() {
66 if (Next == CD.end()) {
67 Stats = LineCoverageStats();
68 Ended = true;
69 return *this;
70 }
71 if (Segments.size())
72 WrappedSegment = Segments.back();
73 Segments.clear();
74 while (Next != CD.end() && Next->Line == Line)
75 Segments.push_back(&*Next++);
76 Stats = LineCoverageStats(Segments, WrappedSegment, Line);
77 ++Line;
78 return *this;
79}
80
Alex Lorenze82d89c2014-08-22 22:56:03 +000081FunctionCoverageSummary
Vedant Kumarb7fdaf22017-09-19 02:00:12 +000082FunctionCoverageSummary::get(const CoverageMapping &CM,
83 const coverage::FunctionRecord &Function) {
Ying Yi78db64e2016-07-22 09:20:21 +000084 // Compute the region coverage.
Alex Lorenze82d89c2014-08-22 22:56:03 +000085 size_t NumCodeRegions = 0, CoveredRegions = 0;
Justin Bogner8e8aa3f2014-09-09 05:32:14 +000086 for (auto &CR : Function.CountedRegions) {
87 if (CR.Kind != CounterMappingRegion::CodeRegion)
Alex Lorenze82d89c2014-08-22 22:56:03 +000088 continue;
89 ++NumCodeRegions;
Justin Bogner8e8aa3f2014-09-09 05:32:14 +000090 if (CR.ExecutionCount != 0)
Alex Lorenze82d89c2014-08-22 22:56:03 +000091 ++CoveredRegions;
92 }
93
94 // Compute the line coverage
95 size_t NumLines = 0, CoveredLines = 0;
Vedant Kumarb7fdaf22017-09-19 02:00:12 +000096 CoverageData CD = CM.getCoverageForFunction(Function);
Vedant Kumar1963f512017-10-14 02:27:29 +000097 for (const auto &LCS : getLineCoverageStats(CD)) {
98 if (!LCS.isMapped())
99 continue;
100 ++NumLines;
101 if (LCS.getExecutionCount())
102 ++CoveredLines;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000103 }
Vedant Kumarb7fdaf22017-09-19 02:00:12 +0000104
Alex Lorenze82d89c2014-08-22 22:56:03 +0000105 return FunctionCoverageSummary(
Alex Lorenzcb1702d2014-09-30 12:45:13 +0000106 Function.Name, Function.ExecutionCount,
107 RegionCoverageInfo(CoveredRegions, NumCodeRegions),
Vedant Kumarb8d06942016-09-19 01:46:01 +0000108 LineCoverageInfo(CoveredLines, NumLines));
Alex Lorenze82d89c2014-08-22 22:56:03 +0000109}
Vedant Kumar016111f2016-09-19 00:38:23 +0000110
Vedant Kumardde19c52017-08-02 23:35:25 +0000111FunctionCoverageSummary
112FunctionCoverageSummary::get(const InstantiationGroup &Group,
113 ArrayRef<FunctionCoverageSummary> Summaries) {
114 std::string Name;
115 if (Group.hasName()) {
116 Name = Group.getName();
117 } else {
118 llvm::raw_string_ostream OS(Name);
119 OS << "Definition at line " << Group.getLine() << ", column "
120 << Group.getColumn();
121 }
122
Vedant Kumar72c3a112017-09-08 18:44:49 +0000123 FunctionCoverageSummary Summary(Name);
Vedant Kumardde19c52017-08-02 23:35:25 +0000124 Summary.ExecutionCount = Group.getTotalExecutionCount();
125 Summary.RegionCoverage = Summaries[0].RegionCoverage;
126 Summary.LineCoverage = Summaries[0].LineCoverage;
127 for (const auto &FCS : Summaries.drop_front()) {
Vedant Kumarc445e652017-09-15 23:00:01 +0000128 Summary.RegionCoverage.merge(FCS.RegionCoverage);
129 Summary.LineCoverage.merge(FCS.LineCoverage);
Vedant Kumardde19c52017-08-02 23:35:25 +0000130 }
131 return Summary;
Vedant Kumar016111f2016-09-19 00:38:23 +0000132}