@@ -294,6 +294,7 @@ our $FILTER_MISSING_FILE;
294294our $FILTER_EXCEPTION_BRANCH ;
295295# remove lone branch in block - it can't be an actual conditional
296296our $FILTER_ORPHAN_BRANCH ;
297+ our $FILTER_OMIT_PATTERNS ; # special/somewhat faked filter
297298
298299our %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
23292337sub 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
53555369sub 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+
56245671sub 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
0 commit comments