1 //===- 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 17 using namespace llvm; 18 using namespace coverage; 19 20 LineCoverageStats::LineCoverageStats( 21 ArrayRef<const coverage::CoverageSegment *> LineSegments, 22 const coverage::CoverageSegment *WrappedSegment, unsigned Line) 23 : ExecutionCount(0), HasMultipleRegions(false), Mapped(false), Line(Line), 24 LineSegments(LineSegments), WrappedSegment(WrappedSegment) { 25 // 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 38 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 65 LineCoverageIterator &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 81 FunctionCoverageSummary 82 FunctionCoverageSummary::get(const CoverageMapping &CM, 83 const coverage::FunctionRecord &Function) { 84 // Compute the region coverage. 85 size_t NumCodeRegions = 0, CoveredRegions = 0; 86 for (auto &CR : Function.CountedRegions) { 87 if (CR.Kind != CounterMappingRegion::CodeRegion) 88 continue; 89 ++NumCodeRegions; 90 if (CR.ExecutionCount != 0) 91 ++CoveredRegions; 92 } 93 94 // Compute the line coverage 95 size_t NumLines = 0, CoveredLines = 0; 96 CoverageData CD = CM.getCoverageForFunction(Function); 97 for (const auto &LCS : getLineCoverageStats(CD)) { 98 if (!LCS.isMapped()) 99 continue; 100 ++NumLines; 101 if (LCS.getExecutionCount()) 102 ++CoveredLines; 103 } 104 105 return FunctionCoverageSummary( 106 Function.Name, Function.ExecutionCount, 107 RegionCoverageInfo(CoveredRegions, NumCodeRegions), 108 LineCoverageInfo(CoveredLines, NumLines)); 109 } 110 111 FunctionCoverageSummary 112 FunctionCoverageSummary::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 123 FunctionCoverageSummary Summary(Name); 124 Summary.ExecutionCount = Group.getTotalExecutionCount(); 125 Summary.RegionCoverage = Summaries[0].RegionCoverage; 126 Summary.LineCoverage = Summaries[0].LineCoverage; 127 for (const auto &FCS : Summaries.drop_front()) { 128 Summary.RegionCoverage.merge(FCS.RegionCoverage); 129 Summary.LineCoverage.merge(FCS.LineCoverage); 130 } 131 return Summary; 132 } 133