llvm.org GIT mirror llvm / c7e789c
[llvm-cov] Ignore unclosed line segments when setting line counts This patch makes a slight change to the way llvm-cov determines line execution counts. If there are multiple line segments on a line, the line count is the max count among the regions which start *and* end on the line. This avoids an issue posed by deferred regions which start on the same line as a terminated region, e.g: if (false) return; //< The line count should be 0, even though a new region //< starts at the semi-colon. foo(); Another change is that counts from line segments which don't correspond to region entries are considered. This enables the first change, and corrects an outstanding issue (see the showLineExecutionCounts.cpp test change). This is related to D35925. Testing: check-profile, llvm-cov lit tests Differential Revision: https://reviews.llvm.org/D36014 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310012 91177308-0d34-0410-b5e6-96231b3b80d8 Vedant Kumar 2 years ago
6 changed file(s) with 122 addition(s) and 24 deletion(s). Raw diff Collapse all Expand all
0 // RUN: llvm-cov show %S/Inputs/deferred-regions.covmapping -instr-profile %S/Inputs/deferred-regions.profdata -show-line-counts-or-regions -dump -filename-equivalence %s 2>&1 | FileCheck %s
1
2 void foo(int x) {
3 if (x == 0) {
4 return; // CHECK: [[@LINE]]|{{ +}}1|
5 }
6
7 } // CHECK: [[@LINE]]|{{ +}}2|
8
9 void bar() {
10 return;
11
12 } // CHECK: [[@LINE]]|{{ +}}1|
13
14 void for_loop() {
15 if (false)
16 return; // CHECK: [[@LINE]]|{{ +}}0|
17
18 for (int i = 0; i < 10; ++i) { // CHECK: [[@LINE]]|{{ +}}2|
19 if (i % 2 == 0)
20 continue; // CHECK: [[@LINE]]|{{ +}}1|
21
22 if (i % 5 == 0)
23 break; // CHECK: [[@LINE]]|{{ +}}0|
24
25 int x = i;
26 return; // CHECK: [[@LINE]]|{{ +}}1|
27
28 } // CHECK: [[@LINE]]|{{ +}}1|
29 }
30
31 struct Error {};
32
33 void while_loop() {
34 if (false)
35 return; // CHECK: [[@LINE]]|{{ +}}0|
36
37 int x = 0;
38 while (++x < 10) { // CHECK: [[@LINE]]|{{ +}}3|
39 if (x == 1)
40 continue; // CHECK: [[@LINE]]|{{ +}}1|
41
42 while (++x < 4) { // CHECK: [[@LINE]]|{{ +}}1|
43 if (x == 3)
44 break; // CHECK: [[@LINE]]|{{ +}}1|
45 // CHECK: [[@LINE]]|{{ +}}0|
46 while (++x < 5) {} // CHECK: [[@LINE]]|{{ +}}0|
47 } // CHECK: [[@LINE]]|{{ +}}1|
48
49 if (x == 0)
50 throw Error(); // CHECK: [[@LINE]]|{{ +}}0|
51
52 while (++x < 9) { // CHECK: [[@LINE]]|{{ +}}6|
53 if (x == 0) // CHECK: [[@LINE]]|{{ +}}5|
54 break; // CHECK: [[@LINE]]|{{ +}}0|
55
56 }
57 }
58 }
59
60 void gotos() {
61 if (false)
62 goto out; // CHECK: [[@LINE]]|{{ +}}0|
63
64 return;
65
66 out: // CHECK: [[@LINE]]|{{ +}}1|
67 return;
68 }
69
70 int main() {
71 foo(0);
72 foo(1);
73 bar();
74 for_loop();
75 while_loop();
76 gotos();
77 return 0;
78 }
55 int main() { // TEXT: [[@LINE]]| 161|int main(
66 int x = 0; // TEXT: [[@LINE]]| 161| int x
77 // TEXT: [[@LINE]]| 161|
8 if (x) { // TEXT: [[@LINE]]| 0| if (x)
8 if (x) { // TEXT: [[@LINE]]| 161| if (x)
99 x = 0; // TEXT: [[@LINE]]| 0| x = 0
1010 } else { // TEXT: [[@LINE]]| 161| } else
1111 x = 1; // TEXT: [[@LINE]]| 161| x = 1
4949 // HTML:
[[@LINE-44]]
161
int main() {

                  
                
5050 // HTML:
[[@LINE-44]]
161
  int x = 0

                  
                
5151 // HTML:
[[@LINE-44]]
161

                  
                
52 // HTML:
[[@LINE-44]]
0
  if (x) {
                  
                
52 // HTML:
[[@LINE-44]]
161
  if (x) {
                  
                
5353 // HTML:
[[@LINE-44]]
0

                  
                
5454 // HTML:
[[@LINE-44]]
161
  }

                  
                
5555 // HTML:
[[@LINE-44]]
161
    x = 1;

                  
                
8080 return llvm::make_unique(Opts);
8181 }
8282 llvm_unreachable("Unknown coverage output format!");
83 }
84
85 LineCoverageStats::LineCoverageStats(
86 ArrayRef LineSegments,
87 const coverage::CoverageSegment *WrappedSegment) {
88 // Find the minimum number of regions which start in this line.
89 unsigned MinRegionCount = 0;
90 auto isStartOfRegion = [](const coverage::CoverageSegment *S) {
91 return S->HasCount && S->IsRegionEntry;
92 };
93 for (unsigned I = 0; I < LineSegments.size() && MinRegionCount < 2; ++I)
94 if (isStartOfRegion(LineSegments[I]))
95 ++MinRegionCount;
96
97 ExecutionCount = 0;
98 HasMultipleRegions = MinRegionCount > 1;
99 Mapped = (WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0);
100
101 if (!Mapped)
102 return;
103
104 // Pick the max count among regions which start and end on this line, to
105 // avoid erroneously using the wrapped count, and to avoid picking region
106 // counts which come from deferred regions.
107 if (LineSegments.size() > 1) {
108 for (unsigned I = 0; I < LineSegments.size() - 1; ++I)
109 ExecutionCount = std::max(ExecutionCount, LineSegments[I]->Count);
110 return;
111 }
112
113 // Just pick the maximum count.
114 if (WrappedSegment && WrappedSegment->HasCount)
115 ExecutionCount = WrappedSegment->Count;
116 if (!LineSegments.empty())
117 ExecutionCount = std::max(ExecutionCount, LineSegments[0]->Count);
83118 }
84119
85120 unsigned SourceCoverageView::getFirstUncoveredLineNo() {
206241 while (NextSegment != EndSegment && NextSegment->Line == LI.line_number())
207242 LineSegments.push_back(&*NextSegment++);
208243
209 // Calculate a count to be for the line as a whole.
210 LineCoverageStats LineCount;
211 if (WrappedSegment && WrappedSegment->HasCount)
212 LineCount.addRegionCount(WrappedSegment->Count);
213 for (const auto *S : LineSegments)
214 if (S->HasCount && S->IsRegionEntry)
215 LineCount.addRegionStartCount(S->Count);
216
217244 renderLinePrefix(OS, ViewDepth);
218245 if (getOptions().ShowLineNumbers)
219246 renderLineNumberColumn(OS, LI.line_number());
247
248 LineCoverageStats LineCount{LineSegments, WrappedSegment};
220249 if (getOptions().ShowLineStats)
221250 renderLineCoverageColumn(OS, LineCount);
222251
6666 /// \brief Coverage statistics for a single line.
6767 struct LineCoverageStats {
6868 uint64_t ExecutionCount;
69 unsigned RegionCount;
69 bool HasMultipleRegions;
7070 bool Mapped;
7171
72 LineCoverageStats() : ExecutionCount(0), RegionCount(0), Mapped(false) {}
72 LineCoverageStats(ArrayRef LineSegments,
73 const coverage::CoverageSegment *WrappedSegment);
7374
7475 bool isMapped() const { return Mapped; }
7576
76 bool hasMultipleRegions() const { return RegionCount > 1; }
77
78 void addRegionStartCount(uint64_t Count) {
79 // The max of all region starts is the most interesting value.
80 addRegionCount(RegionCount ? std::max(ExecutionCount, Count) : Count);
81 ++RegionCount;
82 }
83
84 void addRegionCount(uint64_t Count) {
85 Mapped = true;
86 ExecutionCount = Count;
87 }
77 bool hasMultipleRegions() const { return HasMultipleRegions; }
8878 };
8979
9080 /// \brief A file manager that handles format-aware file creation.