Skip to content

Commit 1c99f65

Browse files
committed
[llvm-cov gcov] Fix calculating coverage of template functions
Template functions share the same lines in source files, so the common container of lines' properties cannot be used to calculate the coverage statistics of individual functions. > cat tmpl.cpp template <int N> int test() { return N; } int main() { return test<1>() + test<2>(); } > clang++ --coverage tmpl.cpp -o tmpl > ./tmpl > llvm-cov gcov tmpl.cpp -f ... Function '_Z4testILi1EEiv' Lines executed:100.00% of 1 Function '_Z4testILi2EEiv' Lines executed:-nan% of 0 ... > llvm-cov-patched gcov tmpl.cpp -f ... Function '_Z4testILi1EEiv' Lines executed:100.00% of 1 Function '_Z4testILi2EEiv' Lines executed:100.00% of 1 ... Differential Revision: https://reviews.llvm.org/D121390
1 parent 6583f01 commit 1c99f65

File tree

5 files changed

+28
-2
lines changed

5 files changed

+28
-2
lines changed

llvm/lib/ProfileData/GCOV.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "llvm/ProfileData/GCOV.h"
1515
#include "llvm/ADT/STLExtras.h"
16+
#include "llvm/ADT/SmallSet.h"
1617
#include "llvm/Config/llvm-config.h"
1718
#include "llvm/Demangle/Demangle.h"
1819
#include "llvm/Support/Debug.h"
@@ -662,6 +663,8 @@ void Context::collectFunction(GCOVFunction &f, Summary &summary) {
662663
if (f.startLine >= si.startLineToFunctions.size())
663664
si.startLineToFunctions.resize(f.startLine + 1);
664665
si.startLineToFunctions[f.startLine].push_back(&f);
666+
SmallSet<uint32_t, 16> lines;
667+
SmallSet<uint32_t, 16> linesExec;
665668
for (const GCOVBlock &b : f.blocksRange()) {
666669
if (b.lines.empty())
667670
continue;
@@ -670,9 +673,9 @@ void Context::collectFunction(GCOVFunction &f, Summary &summary) {
670673
si.lines.resize(maxLineNum + 1);
671674
for (uint32_t lineNum : b.lines) {
672675
LineInfo &line = si.lines[lineNum];
673-
if (!line.exists)
676+
if (lines.insert(lineNum).second)
674677
++summary.lines;
675-
if (line.count == 0 && b.count)
678+
if (b.count && linesExec.insert(lineNum).second)
676679
++summary.linesExec;
677680
line.exists = true;
678681
line.count += b.count;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
template <int N>
2+
int test() { return N; }
3+
4+
int main() { return test<1>() + test<2>(); }
148 Bytes
Binary file not shown.
504 Bytes
Binary file not shown.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Check that the coverage statistics for template functions are calculated as expected.
2+
3+
RUN: rm -rf %t
4+
RUN: mkdir %t
5+
RUN: cd %t
6+
RUN: cp %p/Inputs/tmpl* .
7+
8+
RUN: llvm-cov gcov tmpl.cpp -f | FileCheck %s --check-prefix=F
9+
RUN: llvm-cov gcov tmpl.cpp -t | FileCheck %s --check-prefix=T
10+
11+
F: Function '_Z4testILi1EEiv'
12+
F-NEXT: Lines executed:100.00% of 1
13+
F: Function '_Z4testILi2EEiv'
14+
F-NEXT: Lines executed:100.00% of 1
15+
16+
T: -: 1:template <int N>
17+
T-NEXT: 2: 2:int test() { return N; }
18+
T-NEXT: -: 3:
19+
T-NEXT: 1: 4:int main() { return test<1>() + test<2>(); }

0 commit comments

Comments
 (0)