Skip to content

Commit 6ab84fd

Browse files
committed
Fix overcount of certain filters.
Signed-off-by: Henry Cox <henry.cox@mediatek.com>
1 parent 03a463e commit 6ab84fd

File tree

2 files changed

+143
-60
lines changed

2 files changed

+143
-60
lines changed

lib/lcovutil.pm

Lines changed: 140 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ our $FILTER_MISSING_FILE;
294294
our $FILTER_EXCEPTION_BRANCH;
295295
# remove lone branch in block - it can't be an actual conditional
296296
our $FILTER_ORPHAN_BRANCH;
297+
our $FILTER_OMIT_PATTERNS; # special/somewhat faked filter
297298

298299
our %COVERAGE_FILTERS = ("branch" => \$FILTER_BRANCH_NO_COND,
299300
'brace' => \$FILTER_LINE_CLOSE_BRACE,
@@ -2297,7 +2298,7 @@ sub parse_cov_filters(@)
22972298
{
22982299
my @filters = split($split_char, join($split_char, @_));
22992300

2300-
return if (!@filters);
2301+
goto final if (!@filters);
23012302

23022303
foreach my $item (@filters) {
23032304
die("unknown argument for --filter: '$item'\n")
@@ -2324,6 +2325,13 @@ sub parse_cov_filters(@)
23242325
$cov_filter[$FILTER_EXCEPTION_BRANCH] = ['exception', 0, 0];
23252326
$cov_filter[$FILTER_ORPHAN_BRANCH] = ['orphan', 0, 0];
23262327
}
2328+
final:
2329+
if (@lcovutil::omit_line_patterns) {
2330+
$lcovutil::FILTER_OMIT_PATTERNS = scalar(@lcovutil::cov_filter);
2331+
push(@lcovutil::cov_filter, ['omit_lines', 0, 0]);
2332+
$lcovutil::COVERAGE_FILTERS{'omit_lines'} =
2333+
$lcovutil::FILTER_OMIT_PATTERNS;
2334+
}
23272335
}
23282336

23292337
sub summarize_cov_filters
@@ -5350,6 +5358,12 @@ use constant {
53505358
PATH => 1,
53515359
SOURCE => 2,
53525360
EXCLUDE => 3,
5361+
5362+
# reasons: (bitfield)
5363+
EXCLUDE_REGION => 0x10,
5364+
EXCLUDE_BRANCH_REGION => 0x20,
5365+
EXCLUDE_DIRECTIVE => 0x40,
5366+
OMIT_LINE => 0x80,
53535367
};
53545368

53555369
sub new
@@ -5439,27 +5453,47 @@ sub parseLines
54395453
my ($self, $filename, $sourceLines) = @_;
54405454

54415455
my @excluded;
5442-
my $exclude_region = 0;
5443-
my $exclude_br_region = 0;
5444-
my $exclude_exception_region = 0;
5445-
my $line = 0;
5446-
my $excl_start = qr($lcovutil::EXCL_START);
5447-
my $excl_stop = qr($lcovutil::EXCL_STOP);
5448-
my $excl_line = qr($lcovutil::EXCL_LINE);
5449-
my $excl_br_start = qr($lcovutil::EXCL_BR_START);
5450-
my $excl_br_stop = qr($lcovutil::EXCL_BR_STOP);
5451-
my $excl_br_line = qr($lcovutil::EXCL_BR_LINE);
5452-
my $excl_ex_start = qr($lcovutil::EXCL_EXCEPTION_BR_START);
5453-
my $excl_ex_stop = qr($lcovutil::EXCL_EXCEPTION_BR_STOP);
5454-
my $excl_ex_line = qr($lcovutil::EXCL_EXCEPTION_LINE);
5456+
my $exclude_region;
5457+
my $exclude_br_region;
5458+
my $exclude_exception_region;
5459+
my $line = 0;
5460+
my $excl_start = qr($lcovutil::EXCL_START);
5461+
my $excl_stop = qr($lcovutil::EXCL_STOP);
5462+
my $excl_line = qr($lcovutil::EXCL_LINE);
5463+
my $excl_br_start = qr($lcovutil::EXCL_BR_START);
5464+
my $excl_br_stop = qr($lcovutil::EXCL_BR_STOP);
5465+
my $excl_br_line = qr($lcovutil::EXCL_BR_LINE);
5466+
my $excl_ex_start = qr($lcovutil::EXCL_EXCEPTION_BR_START);
5467+
my $excl_ex_stop = qr($lcovutil::EXCL_EXCEPTION_BR_STOP);
5468+
my $excl_ex_line = qr($lcovutil::EXCL_EXCEPTION_LINE);
54555469
# @todo: if we had annotated data here, then we could whine at the
54565470
# author of the unmatched start, extra end, etc.
54575471

54585472
my $exclude_directives =
5459-
qr/^\s*#\s*((else|endif)|((ifdef|if|elif|include|define|undef)\s+))/
5473+
qr/^\s*#\s*((else|endif)|((ifdef|ifndef|if|elif|include|define|undef)\s+))/
54605474
if (TraceFile::is_language('c', $filename) &&
54615475
defined($lcovutil::cov_filter[$lcovutil::FILTER_DIRECTIVE]));
54625476

5477+
my @excludes;
5478+
if (defined($lcovutil::cov_filter[$lcovutil::FILTER_EXCLUDE_REGION])) {
5479+
push(@excludes,
5480+
[$excl_start, $excl_stop, \$exclude_region, 3 | EXCLUDE_REGION]);
5481+
} else {
5482+
$excl_line = undef;
5483+
}
5484+
5485+
if (defined($lcovutil::cov_filter[$lcovutil::FILTER_EXCLUDE_BRANCH])) {
5486+
push(@excludes,
5487+
[$excl_ex_start, $excl_ex_stop,
5488+
\$exclude_exception_region, 4 | EXCLUDE_BRANCH_REGION
5489+
],
5490+
[$excl_br_start, $excl_br_stop,
5491+
\$exclude_br_region, 2 | EXCLUDE_BRANCH_REGION
5492+
]);
5493+
} else {
5494+
$excl_br_line = undef;
5495+
$excl_ex_line = undef;
5496+
}
54635497
LINES: foreach (@$sourceLines) {
54645498
$line += 1;
54655499
my $exclude_branch_line = 0;
@@ -5469,66 +5503,69 @@ sub parseLines
54695503
s/\r//; # remove carriage return
54705504
if (defined($exclude_directives) &&
54715505
$_ =~ $exclude_directives) {
5472-
++$lcovutil::cov_filter[$lcovutil::FILTER_DIRECTIVE]->[-2];
5473-
++$lcovutil::cov_filter[$lcovutil::FILTER_DIRECTIVE]->[-1];
5474-
push(@excluded, 3); #everything excluded
5475-
lcovutil::info(2, "exclude '#$1' directive on $filename:$line\n");
5506+
push(@excluded, 3 | EXCLUDE_DIRECTIVE); #everything excluded
5507+
lcovutil::info(2, "directive '#$1' on $filename:$line\n");
54765508
next;
54775509
}
54785510

5479-
foreach my $d ([$excl_start, $excl_stop, \$exclude_region],
5480-
[$excl_br_start, $excl_br_stop, \$exclude_br_region],
5481-
[$excl_ex_start, $excl_ex_stop,
5482-
\$exclude_exception_region
5483-
]
5484-
) {
5485-
my ($start, $stop, $ref) = @$d;
5511+
foreach my $d (@excludes) {
5512+
my ($start, $stop, $ref, $reason) = @$d;
54865513
if ($_ =~ $start) {
54875514
lcovutil::ignorable_error($lcovutil::ERROR_MISMATCH,
54885515
"$filename: overlapping exclude directives. Found $start at line $line - but no matching $stop for $start at line "
5489-
. $$ref)
5516+
. $ref->[0])
54905517
if $$ref;
5491-
$$ref = $line;
5518+
$$ref = [$line, $reason];
54925519
last;
54935520
} elsif ($_ =~ $stop) {
54945521
lcovutil::ignorable_error($lcovutil::ERROR_MISMATCH,
54955522
"$filename: found $stop directive at line $line without matching $start directive"
54965523
) unless $$ref;
5497-
$$ref = 0;
5524+
$$ref = undef;
54985525
last;
54995526
}
55005527
}
5501-
if ($_ =~ $excl_line) {
5502-
push(@excluded, 3); #everything excluded
5528+
if (defined($excl_line) &&
5529+
$_ =~ $excl_line) {
5530+
push(@excluded, 3 | EXCLUDE_REGION); #everything excluded
55035531
next;
5504-
} elsif ($_ =~ $excl_br_line) {
5505-
$exclude_branch_line = 2;
5506-
} elsif ($_ =~ $excl_ex_line) {
5507-
$exclude_branch_line = 4;
5532+
} elsif (defined($excl_br_line) &&
5533+
$_ =~ $excl_br_line) {
5534+
$exclude_branch_line = 2 | EXCLUDE_BRANCH_REGION;
5535+
} elsif (defined($excl_ex_line) &&
5536+
$_ =~ $excl_ex_line) {
5537+
$exclude_branch_line = 4 | EXCLUDE_BRANCH_REGION;
55085538
} elsif (0 != scalar(@lcovutil::omit_line_patterns)) {
55095539
foreach my $p (@lcovutil::omit_line_patterns) {
55105540
my $pat = $p->[0];
55115541
if ($_ =~ $pat) {
5512-
push(@excluded, 3); #everything excluded
5542+
push(@excluded, 3 | OMIT_LINE); #everything excluded
55135543
#lcovutil::info("'" . $p->[-2] . "' matched \"$_\", line \"$filename\":"$line\n");
55145544
++$p->[-1];
55155545
next LINES;
55165546
}
55175547
}
55185548
}
55195549
push(@excluded,
5520-
($exclude_region ? 1 : 0) | ($exclude_br_region ? 2 : 0) |
5521-
($exclude_exception_region ? 4 : 0) | $exclude_branch_line |
5522-
$exclude_exception_branch_line);
5550+
($exclude_region ? $exclude_region->[1] : 0) |
5551+
($exclude_br_region ? $exclude_br_region->[1] : 0) | (
5552+
$exclude_exception_region ? $exclude_exception_region->[1] : 0
5553+
) | $exclude_branch_line | $exclude_exception_branch_line);
55235554
}
55245555
lcovutil::ignorable_error($lcovutil::ERROR_MISMATCH,
5525-
"$filename: unmatched $lcovutil::EXCL_START at line $exclude_region - saw EOF while looking for matching $lcovutil::EXCL_STOP"
5556+
"$filename: unmatched $lcovutil::EXCL_START at line " .
5557+
$exclude_region->[0] .
5558+
" - saw EOF while looking for matching $lcovutil::EXCL_STOP"
55265559
) if $exclude_region;
55275560
lcovutil::ignorable_error($lcovutil::ERROR_MISMATCH,
5528-
"$filename: unmatched $lcovutil::EXCL_BR_START at line $exclude_br_region - saw EOF while looking for matching $lcovutil::EXCL_BR_STOP"
5561+
"$filename: unmatched $lcovutil::EXCL_BR_START at line " .
5562+
$exclude_br_region->[0] .
5563+
" - saw EOF while looking for matching $lcovutil::EXCL_BR_STOP"
55295564
) if $exclude_br_region;
55305565
lcovutil::ignorable_error($lcovutil::ERROR_MISMATCH,
5531-
"$filename: unmatched $lcovutil::EXCL_EXCEPTION_BR_START at line $exclude_exception_region - saw EOF while looking for matching $lcovutil::EXCL_EXCEPTION_BR_STOP"
5566+
"$filename: unmatched $lcovutil::EXCL_EXCEPTION_BR_START at line " .
5567+
$exclude_exception_region->[0] .
5568+
" - saw EOF while looking for matching $lcovutil::EXCL_EXCEPTION_BR_STOP"
55325569
) if $exclude_exception_region;
55335570

55345571
my $data = $self->[0];
@@ -5621,6 +5658,16 @@ sub isOutOfRange
56215658
return 0;
56225659
}
56235660

5661+
sub excludeReason
5662+
{
5663+
my ($self, $lineNo) = @_;
5664+
my $data = $self->[0];
5665+
die("missing data at $lineNo")
5666+
unless (defined($data->[EXCLUDE]) &&
5667+
scalar(@{$data->[EXCLUDE]}) >= $lineNo);
5668+
return $data->[EXCLUDE]->[$lineNo - 1] & 0xFF0;
5669+
}
5670+
56245671
sub isExcluded
56255672
{
56265673
my ($self, $lineNo, $branch) = @_;
@@ -6489,6 +6536,9 @@ sub _filterFile
64896536
my $trivial_histogram = $cov_filter[$FILTER_TRIVIAL_FUNCTION];
64906537
my $filter_initializer_list = $cov_filter[$FILTER_INITIALIZER_LIST]
64916538
if (is_language('c', $source_file));
6539+
my $directive = $cov_filter[$FILTER_DIRECTIVE];
6540+
my $omit = $cov_filter[$FILTER_OMIT_PATTERNS]
6541+
if defined($FILTER_OMIT_PATTERNS);
64926542

64936543
my $context = MessageContext->new("filtering $source_file");
64946544
if (lcovutil::is_filter_enabled()) {
@@ -6580,9 +6630,16 @@ sub _filterFile
65806630
"filter FN " . $data->name() .
65816631
' ' . $data->file() . ":$line\n");
65826632
++$range->[-2]; # one location where this applied
6583-
} elsif ($region && $srcReader->isExcluded($line)) {
6633+
} elsif ($srcReader->isExcluded($line)) {
65846634
$remove = 1;
6585-
$region->[-2] += scalar(keys %{$data->aliases()});
6635+
my $reason = $srcReader->excludeReason($line);
6636+
foreach my $f ([ReadCurrentSource::EXCLUDE_REGION, $region],
6637+
[ReadCurrentSource::OMIT_LINE, $omit]) {
6638+
if ($reason & $f->[0]) {
6639+
$f->[1]->[-2] += scalar(keys %{$data->aliases()});
6640+
last;
6641+
}
6642+
}
65866643
}
65876644
if ($remove) {
65886645
#remove this function from everywhere
@@ -6603,10 +6660,11 @@ sub _filterFile
66036660
if ($lcovutil::br_coverage &&
66046661
defined($testbrcount) &&
66056662
($branch_histogram ||
6606-
$region ||
6607-
$branch_region ||
6608-
$range ||
6609-
$filterExceptionBranches)
6663+
$region ||
6664+
$branch_region ||
6665+
$range ||
6666+
$filterExceptionBranches ||
6667+
$omit)
66106668
) {
66116669
foreach my $line ($testbrcount->keylist()) {
66126670
# for counting: keep track filter which triggered exclusion -
@@ -6616,11 +6674,24 @@ sub _filterFile
66166674
# only counting line coverpoints that got excluded
66176675
die("inconsistent state") unless $range;
66186676
$remove = $range;
6619-
} elsif (($region || $branch_region) &&
6620-
$srcReader->isExcluded($line, 2)) {
6677+
} elsif ($srcReader->isExcluded($line, 2)) {
66216678
# all branches here
6622-
$remove = $region ? $region : $branch_region;
6623-
die("inconsistent") unless $remove;
6679+
my $reason = $srcReader->excludeReason($line);
6680+
foreach my $f ([ReadCurrentSource::EXCLUDE_REGION, $region],
6681+
[ReadCurrentSource::OMIT_LINE, $omit],
6682+
[ReadCurrentSource::EXCLUDE_DIRECTIVE,
6683+
$directive
6684+
],
6685+
[ReadCurrentSource::EXCLUDE_BRANCH_REGION,
6686+
$branch_region
6687+
]
6688+
) {
6689+
if ($reason & $f->[0]) {
6690+
$remove = $f->[1];
6691+
last;
6692+
}
6693+
}
6694+
die("inconsistent reason $reason") unless $remove;
66246695
} elsif ($branch_histogram &&
66256696
!$srcReader->containsConditional($line)) {
66266697
$remove = $branch_histogram;
@@ -6659,6 +6730,8 @@ sub _filterFile
66596730
$range ||
66606731
$brace_histogram ||
66616732
$branch_histogram ||
6733+
$directive ||
6734+
$omit ||
66626735
$filter_initializer_list;
66636736

66646737
my %initializerListRange;
@@ -6697,9 +6770,20 @@ sub _filterFile
66976770
$outOfRange;
66986771
my $excluded = $srcReader->isExcluded($line)
66996772
unless $is_filtered;
6700-
$is_filtered =
6701-
$lcovutil::cov_filter[$lcovutil::FILTER_EXCLUDE_REGION]
6702-
if !defined($is_filtered) && defined($excluded) && $excluded;
6773+
if (defined($excluded) && $excluded) {
6774+
my $reason = $srcReader->excludeReason($line);
6775+
foreach my $f ([ReadCurrentSource::EXCLUDE_REGION, $region],
6776+
[ReadCurrentSource::OMIT_LINE, $omit],
6777+
[ReadCurrentSource::EXCLUDE_DIRECTIVE,
6778+
$directive
6779+
]
6780+
) {
6781+
if ($reason & $f->[0]) {
6782+
$is_filtered = $f->[1];
6783+
last;
6784+
}
6785+
}
6786+
}
67036787
my $l_hit = $testcount->value($line);
67046788
my $isCloseBrace =
67056789
($brace_histogram &&
@@ -6728,8 +6812,7 @@ sub _filterFile
67286812
"") .
67296813
" $source_file:$line\n");
67306814

6731-
unless ((defined($outOfRange) && $outOfRange) ||
6732-
(defined($excluded) && $excluded)) {
6815+
unless (defined($outOfRange) && $outOfRange) {
67336816
# some filters already counted...
67346817
++$is_filtered->[-2]; # one location where this applied
67356818
++$is_filtered->[-1]; # one coverpoint suppressed

tests/lcov/extract/extract.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ if [ "$NO_INITIAL_CAPTURE" != 1 ] ; then
400400
# does the result contain file 'uused'
401401
grep -E "SF:.+unused.c$" all_internal.info
402402
if [ $? != 0 ] ; then
403-
echo "Error: did not find 'unused'"
403+
echo "Error: did not find 'unused' 2"
404404
if [ $KEEP_GOING == 0 ] ; then
405405
exit 1
406406
fi
@@ -409,7 +409,7 @@ if [ "$NO_INITIAL_CAPTURE" != 1 ] ; then
409409
# should have found the branch in 'unused.c'
410410
C=`grep -c BRDA: all_internal.info`
411411
if [ "$C" != 18 ] ; then
412-
echo "Error: did not find 'unused'"
412+
echo "Error: unexpected branch count in 'unused'"
413413
if [ $KEEP_GOING == 0 ] ; then
414414
exit 1
415415
fi
@@ -556,7 +556,7 @@ fi
556556
EXCL_LINE_BRANCHES=`grep -c "^BRDA:" exclbrline.info`
557557
558558
if [ $EXCL_LINE_BRANCHES != $EXCL_BRANCHES ] ; then
559-
echo "did not honor br line marker override: expected $EXCL_BRANCHES foune $EXCL_LINE_BRANCHES"
559+
echo "did not honor br line marker override: expected $EXCL_BRANCHES found $EXCL_LINE_BRANCHES"
560560
if [ $KEEP_GOING == 0 ] ; then
561561
exit 1
562562
fi

0 commit comments

Comments
 (0)