Skip to content

Commit 39dc203

Browse files
committed
Filter coverpoints on lines that look like compiler directives in C/C++.
llvm-cov seems to generate them when translating from profile to lcov format. The same effect can be achieved via '--omit-lines' - but filter option is easier for users, especially as this is a common case. Signed-off-by: Henry Cox <[email protected]>
1 parent ae2dbb4 commit 39dc203

File tree

5 files changed

+58
-18
lines changed

5 files changed

+58
-18
lines changed

lib/lcovutil.pm

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ our @EXPORT_OK = qw($tool_name $tool_dir $lcov_version $lcov_url
5050
$FILTER_BRANCH_NO_COND $FILTER_FUNCTION_ALIAS
5151
$FILTER_EXCLUDE_REGION $FILTER_EXCLUDE_BRANCH $FILTER_LINE
5252
$FILTER_LINE_CLOSE_BRACE $FILTER_BLANK_LINE $FILTER_LINE_RANGE
53-
$FILTER_TRIVIAL_FUNCTION
53+
$FILTER_TRIVIAL_FUNCTION $FILTER_DIRECTIVE
5454
@cov_filter
5555
$EXCL_START $EXCL_STOP $EXCL_BR_START $EXCL_BR_STOP
5656
$EXCL_EXCEPTION_BR_START $EXCL_EXCEPTION_BR_STOP
@@ -257,10 +257,13 @@ our $FILTER_LINE_RANGE = 6;
257257
our $FILTER_LINE = 7;
258258
# remove functions which have only a single line
259259
our $FILTER_TRIVIAL_FUNCTION = 8;
260+
# remove compiler directive lines which llvm-cov seems to generate
261+
our $FILTER_DIRECTIVE = 9;
260262

261263
our %COVERAGE_FILTERS = ("branch" => $FILTER_BRANCH_NO_COND,
262264
'brace' => $FILTER_LINE_CLOSE_BRACE,
263265
'blank' => $FILTER_BLANK_LINE,
266+
'directive' => $FILTER_DIRECTIVE,
264267
'range' => $FILTER_LINE_RANGE,
265268
'line' => $FILTER_LINE,
266269
'function' => $FILTER_FUNCTION_ALIAS,
@@ -1971,16 +1974,9 @@ sub check_parent_process
19711974
sub is_filter_enabled
19721975
{
19731976
# return true of there is an opportunity for filtering
1974-
return (defined($lcovutil::cov_filter[$lcovutil::FILTER_BRANCH_NO_COND]) ||
1975-
defined($lcovutil::cov_filter[$lcovutil::FILTER_LINE_CLOSE_BRACE])
1976-
|| defined($lcovutil::cov_filter[$lcovutil::FILTER_BLANK_LINE])
1977-
|| defined($lcovutil::cov_filter[$lcovutil::FILTER_LINE_RANGE])
1978-
|| defined($lcovutil::cov_filter[$lcovutil::FILTER_EXCLUDE_REGION])
1979-
|| defined($lcovutil::cov_filter[$lcovutil::FILTER_EXCLUDE_BRANCH])
1980-
|| defined(
1981-
$lcovutil::cov_filter[$lcovutil::FILTER_TRIVIAL_FUNCTION]) ||
1982-
0 != scalar(@lcovutil::omit_line_patterns) ||
1983-
0 != scalar(@lcovutil::exclude_function_patterns));
1977+
return (grep({ defined($_) } @lcovutil::cov_filter) ||
1978+
0 != scalar(@lcovutil::omit_line_patterns) ||
1979+
0 != scalar(@lcovutil::exclude_function_patterns));
19841980
}
19851981

19861982
sub parse_cov_filters(@)
@@ -4881,12 +4877,28 @@ sub parseLines
48814877
my $excl_ex_line = qr($lcovutil::EXCL_EXCEPTION_LINE);
48824878
# @todo: if we had annotated data here, then we could whine at the
48834879
# author of the unmatched start, extra end, etc.
4880+
4881+
my $exclude_directives =
4882+
qr/^\s*#\s*((else|endif)|((ifdef|if|elif|include|define|undef)\s+))/
4883+
if (TraceFile::is_language('c', $filename) &&
4884+
defined($lcovutil::cov_filter[$lcovutil::FILTER_DIRECTIVE]));
4885+
48844886
LINES: foreach (@$sourceLines) {
48854887
$line += 1;
48864888
my $exclude_branch_line = 0;
48874889
my $exclude_exception_branch_line = 0;
48884890
chomp($_);
48894891
s/\r//; # remove carriage return
4892+
if (defined($exclude_directives) &&
4893+
$_ =~ $exclude_directives) {
4894+
++$lcovutil::cov_filter[$lcovutil::FILTER_DIRECTIVE]->[0];
4895+
++$lcovutil::cov_filter[$lcovutil::FILTER_DIRECTIVE]->[1];
4896+
push(@excluded, 3); #everything excluded
4897+
lcovutil::info( #2,
4898+
"exclude '#$1' directive on $filename:$line\n");
4899+
next;
4900+
}
4901+
48904902
foreach my $d ([$excl_start, $excl_stop, \$exclude_region],
48914903
[$excl_br_start, $excl_br_stop, \$exclude_br_region],
48924904
[$excl_ex_start, $excl_ex_stop,
@@ -5186,6 +5198,10 @@ sub suppressCloseBrace
51865198
if ($prev == $count ||
51875199
($count == 0 &&
51885200
$prev > 0));
5201+
5202+
lcovutil::info(3,
5203+
"not skipping brace line $lineNo because previous line $prevLine hit count didn't match: $prev != $count"
5204+
) unless $suppress;
51895205
last;
51905206
} elsif ($count == 0 &&
51915207
# previous line not executable - was it an open brace?

man/genhtml.1

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1936,10 +1936,20 @@ These lines seem to appear and disappear in gcov output - and cause differential
19361936
ignore lines which contain only whitespace (or whitespace + comments) whose 'hit' count is zero. These appear to be a 'gcov' artifact related to compiler-generated code - such as exception handlers and destructor calls at the end of scope - and can confuse differential coverage criteria.
19371937
.PP
19381938

1939+
.IP directive: 3
1940+
ignore lines which look like C compiler directives: #ifdef, #include, #define,
1941+
.I etc.
1942+
These lines are sometimes included by
1943+
.I llvm\-cov
1944+
when LLVM profile data is translated to LCOV format.
1945+
.PP
1946+
1947+
.IP line: 3
1948+
alias for "\-\-filter brace,blank".
1949+
.PP
1950+
19391951
.IP range: 3
19401952
Ignore line and branch coverpoints on lines which are out-of range/whose line number is beyond the end of the source file. These appear to be gcov artifacts caused by a macro instantiation on the last line of the file.
1941-
.B line:
1942-
alias for "\-\-filter brace,blank".
19431953
.PP
19441954

19451955
.IP region: 3

tests/gendiffcov/filter/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ include ../../common.mak
33
TESTS := filter.pl
44

55
clean:
6-
rm -f *.orig *.filtered
6+
rm -f *.orig *.filtered *.directive

tests/gendiffcov/filter/brace.info

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ FN:1,set_brack_offset
44
FNDA:27,set_brack_offset
55
FNF:1
66
FNH:1
7+
DA:3,27
78
DA:1,27
89
DA:8,27
9-
LF:2
10-
LH:2
10+
LF:3
11+
LH:3
1112
end_of_record

tests/gendiffcov/filter/filter.pl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
}
5656

5757
# problematic brace filter example...
58-
$lcovutil::verbose = 2;
58+
$lcovutil::verbose = 3;
5959
$lcovutil::derive_function_end_line = 1;
6060
our $func_coverage = 1;
6161
foreach my $example (glob('*brace*.c')) {
@@ -75,10 +75,23 @@
7575
$trace->write_info_file($info . '.filtered');
7676
my @counts = $trace->count_totals();
7777
my ($filtered, $h2) = @{$counts[1]};
78-
print("$filtered filtered lines $h2 hit\n");
78+
print("$filtered brace-filtered lines $h2 hit\n");
7979
die("failed to filter $info")
8080
unless ($lines > $filtered &&
8181
$hit > $h2);
82+
83+
#simple test for compiler directive filtering
84+
lcovutil::parse_cov_filters(); # reset filters
85+
lcovutil::parse_cov_filters('directive');
86+
$reader = ReadCurrentSource->new('brace.c');
87+
my $directive = TraceFile->load('brace.info', $reader);
88+
$directive->write_info_file($info . '.directive');
89+
@counts = $directive->count_totals();
90+
my ($f3, $h3) = @{$counts[1]};
91+
print("$f3 directive-filtered lines $h3 hit\n");
92+
die("failed to filter $info")
93+
unless ($lines > $f3 &&
94+
$hit > $h3);
8295
}
8396

8497
exit(0);

0 commit comments

Comments
 (0)