lcov icon indicating copy to clipboard operation
lcov copied to clipboard

C++ branch coverage false positives

Open carun opened this issue 5 years ago • 7 comments

When using g++, there are many false positives with branch coverage, caused by standard operators and libraries, caused by if (ptr != NULL) checks employed by the compiler. Is there a way to ignore such false positives? False positives with printf is not persistent if we use a gcc.

image

Sample code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>

int main(int argc, const char *argv[])
{
    bool b = false;
    if (strcmp(argv[1], "1") == 0)
        b = true;

    char *a = nullptr;
    if (b)
      printf("Hai\n");
    delete[] a;

    std::string str("asdads");
    str = "cd";

    std::cout << str << std::endl;
    return 0;
}

Steps

$ gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
$ g++ 1.cpp -fprofile-arcs -ftest-coverage -g -o 1 -std=c++11
$ lcov -c --rc lcov_branch_coverage=1 --no-external -d . -o 1.info
$ genhtml -s  --rc lcov_branch_coverage=1 --legend 1.info -o o

Output

image

With GCC 4.8.5 on RHEL7

image

carun avatar Nov 11 '20 23:11 carun

Yes.

See my earlier replies WRT ‘branch filtering’ – which is implemented in my version of the code. See “differential coverage” and the related descriptions and pull request.

henry2cox avatar Nov 12 '20 10:11 henry2cox

Reference PR of @henry2cox: #86

carun avatar Nov 12 '20 18:11 carun

@henry2cox your branch at https://github.com/henry2cox/lcov/tree/8728189f3e04a3efe0c2778de6c4a2e0cdb0d17d is unstable. I see incorrect result for the same input.

Reading data file 1.info
Found 8 entries.
Found common filename prefix "/usr/include/c++/9"
Writing .css and .png files.
Generating output.
processing dir /tmp/a
Processing file /tmp/a/1.cpp
  lines=12 hit=12
processing dir /usr/include/c++/9/bits
Processing file bits/stl_iterator_base_types.h
  lines=2 hit=0
Processing file bits/basic_string.h
  lines=6 hit=0
Processing file bits/char_traits.h
  lines=2 hit=0
Processing file bits/stl_iterator_base_funcs.h
  lines=5 hit=0
Processing file bits/basic_string.tcc
  lines=13 hit=0
processing dir /usr/include/c++/9/ext
Processing file ext/new_allocator.h
  lines=2 hit=0
Processing file ext/type_traits.h
  lines=2 hit=0
Writing directory view page.
Overall coverage rate:
  lines......: 27.3% (12 of 44 lines)
  functions......: 9.1% (1 of 11 functions)
  branches......: 23.8% (10 of 42 branches)

carun avatar Nov 13 '20 05:11 carun

I see a different result than you do...works for me. $ g++ -fprofile-arcs -ftest-coverage -g -o foo -std=c++11 foo.cpp $ ./foo 1 $ lcov --rc lcov_branch_coverage=1 --no-external -d . -o foo.info -c Capturing coverage data from . geninfo cmd: '/home/hcox/pwa/dspMethLibs/releng/coverage/lcov/bin/geninfo . --output-filename foo.info --no-external --rc lcov_branch_coverage=1'Found gcov version: 5.2.0 Using intermediate gcov format Scanning . for .gcda files ... Found 1 data files in . Processing foo.gcda Finished .info-file creation $ ../../bin/genhtml -s --rc lcov_branch_coverage=1 --branch-coverage --legend foo.info -o rpt Reading data file foo.info Found 2 entries. Found common filename prefix "/home/hcox/pwa/dspMethLibs/releng/coverage/lcov/tests" Writing .css and .png files. Generating output. processing dir /mtkoss/gcc/5.2.0-rhel6/x86_64/include/c++/5.2.0 Processing file /mtkoss/gcc/5.2.0-rhel6/x86_64/include/c++/5.2.0/iostream lines=1 hit=1 processing dir /home/hcox/pwa/dspMethLibs/releng/coverage/lcov/tests/foo Processing file foo/foo.cpp lines=13 hit=13 Writing directory view page. Overall coverage rate: lines......: 100.0% (14 of 14 lines) functions......: 100.0% (3 of 3 functions) branches......: 50.0% (10 of 20 branches) image

Running again with branch filtering... $ genhtml -s --rc lcov_branch_coverage=1 --branch-coverage --filter branch --legend foo.info -o rpt2 Reading data file foo.info reading /home/hcox/pwa/dspMethLibs/releng/coverage/lcov/tests/foo/foo.cpp (for bogus branch filtering) Found 2 entries. Found common filename prefix "/home/hcox/pwa/dspMethLibs/releng/coverage/lcov/tests" Writing .css and .png files. Generating output. processing dir /mtkoss/gcc/5.2.0-rhel6/x86_64/include/c++/5.2.0 Processing file /mtkoss/gcc/5.2.0-rhel6/x86_64/include/c++/5.2.0/iostream lines=1 hit=1 processing dir /home/hcox/pwa/dspMethLibs/releng/coverage/lcov/tests/foo Processing file foo/foo.cpp lines=13 hit=13 Writing directory view page. Overall coverage rate: lines......: 100.0% (14 of 14 lines) functions......: 100.0% (3 of 3 functions) branches......: 50.0% (2 of 4 branches) Filter suppressions 'branch': 6 instances 16 coverpoints image

henry2cox avatar Nov 13 '20 10:11 henry2cox

Nice to see the results. So here is what I did on my Ubuntu 20.04.1 LTS. Can you tell me what I'm missing?

2020-11-13 12:06:26 ~/code/foss
$ git clone https://github.com/henry2cox/lcov
Cloning into 'lcov'...
remote: Enumerating objects: 142, done.
remote: Counting objects: 100% (142/142), done.
remote: Compressing objects: 100% (70/70), done.
remote: Total 2201 (delta 81), reused 110 (delta 63), pack-reused 2059
Receiving objects: 100% (2201/2201), 1003.74 KiB | 7.22 MiB/s, done.
Resolving deltas: 100% (1559/1559), done.

2020-11-13 12:06:31 ~/code/foss
$ cd lcov

2020-11-13 12:06:35 ~/code/foss/lcov (master)
$ git co -t origin/diffcov_initial
Branch 'diffcov_initial' set up to track remote branch 'diffcov_initial' from 'origin' by rebasing.
Switched to a new branch 'diffcov_initial'

2020-11-13 12:06:45 ~/code/foss/lcov (diffcov_initial)
$ sudo make install
bin/install.sh bin/lcov /usr/local/bin/lcov -m 755                                                                                                                                                          [5/28161]
bin/install.sh bin/genhtml /usr/local/bin/genhtml -m 755
(cd /usr/local/bin ; rm -f gendiffcov ; ln -s genhtml gendiffcov)
bin/install.sh bin/geninfo /usr/local/bin/geninfo -m 755
bin/install.sh bin/genpng /usr/local/bin/genpng -m 755
(cd /usr/local/bin ; rm -f gendiffpng ; ln -s genpng gendiffpng)
bin/install.sh bin/gendesc /usr/local/bin/gendesc -m 755
bin/install.sh bin/p4udiff /usr/local/share/lcov/support-scripts/p4udiff -m 755
bin/install.sh bin/p4annotate /usr/local/share/lcov/support-scripts/p4annotate -m 755
bin/install.sh bin/gitblame /usr/local/share/lcov/support-scripts/gitblame -m 755
bin/install.sh lib/lcovutil.pm /usr/local/lib/lcovutil.pm -m 755
bin/install.sh man/lcov.1 /usr/local/share/man/man1/lcov.1 -m 644
bin/install.sh man/genhtml.1 /usr/local/share/man/man1/genhtml.1 -m 644
(cd /usr/local/share/man/man1 ; rm -f gendiffcov.1 ; ln -s genhtml.1 gendiffcov.1)
bin/install.sh man/geninfo.1 /usr/local/share/man/man1/geninfo.1 -m 644
bin/install.sh man/genpng.1 /usr/local/share/man/man1/genpng.1 -m 644
(cd /usr/local/share/man/man1 ; rm -f gendiffpng.1 ; ln -s genpng.1 gendiffpng.1)
bin/install.sh man/gendesc.1 /usr/local/share/man/man1/gendesc.1 -m 644
bin/install.sh man/lcovrc.5 /usr/local/share/man/man5/lcovrc.5 -m 644
bin/install.sh lcovrc /usr/local/etc/lcovrc -m 644
bin/updateversion.pl /usr/local/bin/lcov 1.14 36.g8728189 1.14-36-g8728189
Updating bin tool /usr/local/bin/lcov
Done.
bin/updateversion.pl /usr/local/bin/genhtml 1.14 36.g8728189 1.14-36-g8728189
Updating bin tool /usr/local/bin/genhtml
Done.
bin/updateversion.pl /usr/local/bin/geninfo 1.14 36.g8728189 1.14-36-g8728189
Updating bin tool /usr/local/bin/geninfo
Done.
bin/updateversion.pl /usr/local/bin/genpng 1.14 36.g8728189 1.14-36-g8728189
Updating bin tool /usr/local/bin/genpng
Done.
bin/updateversion.pl /usr/local/bin/gendesc 1.14 36.g8728189 1.14-36-g8728189
Updating bin tool /usr/local/bin/gendesc
Done.
bin/updateversion.pl /usr/local/share/man/man1/lcov.1 1.14 36.g8728189 1.14-36-g8728189
Updating man page /usr/local/share/man/man1/lcov.1
Done.
bin/updateversion.pl /usr/local/share/man/man1/genhtml.1 1.14 36.g8728189 1.14-36-g8728189
Updating man page /usr/local/share/man/man1/genhtml.1
Done.
bin/updateversion.pl /usr/local/share/man/man1/geninfo.1 1.14 36.g8728189 1.14-36-g8728189
Updating man page /usr/local/share/man/man1/geninfo.1
Done.
bin/updateversion.pl /usr/local/share/man/man1/genpng.1 1.14 36.g8728189 1.14-36-g8728189
Updating man page /usr/local/share/man/man1/genpng.1
Done.
bin/updateversion.pl /usr/local/share/man/man1/gendesc.1 1.14 36.g8728189 1.14-36-g8728189
Updating man page /usr/local/share/man/man1/gendesc.1
Done.
bin/updateversion.pl /usr/local/share/man/man5/lcovrc.5 1.14 36.g8728189 1.14-36-g8728189
Updating man page /usr/local/share/man/man5/lcovrc.5
Done.
2020-11-13 12:07:08 ~/code/foss/lcov (diffcov_initial)
$
2020-11-13 12:08:11 ~/code/foss/lcov (diffcov_initial)
$ cd /tmp/a

2020-11-13 12:08:14 /tmp/a
$ lcov --version
lcov: LCOV version 1.14-36-g8728189

2020-11-13 12:09:36 /tmp/a
$ g++ 1.cpp -fprofile-arcs -ftest-coverage -g -o 1 -std=c++11

2020-11-13 12:09:38 /tmp/a
$ lcov -c --rc lcov_branch_coverage=1 --no-external -d . -o 1.info
Capturing coverage data from .
Found gcov version: 9.3.0
Using intermediate gcov format
Scanning . for .gcda files ...
Found 1 data files in .
Processing 1.gcda
Finished .info-file creation

2020-11-13 12:12:59 /tmp/a
$ genhtml -s  --rc lcov_branch_coverage=1 --legend 1.info -o o
Can't locate DateTime.pm in @INC (you may need to install the DateTime module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.30.0 /usr/local/share/perl/5.30.0 /usr/lib/x86_64-linux-gnu/perl5/5.3
0 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.30 /usr/share/perl/5.30 /usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base) at /usr/local/bin/genhtml line 86.
BEGIN failed--compilation aborted at /usr/local/bin/genhtml line 86.

2020-11-13 12:13:02 /tmp/a
$ sudo apt install -yqq libdatetime-perl

2020-11-13 12:13:26 /tmp/a
$ genhtml -s  --rc lcov_branch_coverage=1 --legend 1.info -o o
Can't locate DateTime.pm in @INC (you may need to install the DateTime module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.30.0 /usr/local/share/perl/5.30.0 /usr/lib/x86_64-linux-gnu/perl5/5.3
0 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.30 /usr/share/perl/5.30 /usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base) at /usr/local/bin/genhtml line 86.
BEGIN failed--compilation aborted at /usr/local/bin/genhtml line 86.

2020-11-13 12:13:53 /tmp/a
$ sudo apt install -yqq libdatetime-format-w3cdtf-perl

2020-11-13 12:13:58 /tmp/a
$ genhtml -s  --rc lcov_branch_coverage=1 --legend 1.info -o o
Reading data file 1.info
Found 8 entries.
Found common filename prefix "/usr/include/c++/9"
Writing .css and .png files.
Generating output.
processing dir /tmp/a
Processing file /tmp/a/1.cpp
  lines=12 hit=12
processing dir /usr/include/c++/9/bits
Processing file bits/stl_iterator_base_funcs.h
  lines=5 hit=0
Processing file bits/char_traits.h
  lines=2 hit=0
Processing file bits/basic_string.h
  lines=6 hit=0
Processing file bits/basic_string.tcc
  lines=13 hit=0
Processing file bits/stl_iterator_base_types.h
  lines=2 hit=0
processing dir /usr/include/c++/9/ext
Processing file ext/type_traits.h
  lines=2 hit=0
Processing file ext/new_allocator.h
  lines=2 hit=0
Writing directory view page.
Overall coverage rate:
  lines......: 27.3% (12 of 44 lines)
  functions......: 9.1% (1 of 11 functions)
  branches......: 23.8% (10 of 42 branches)

carun avatar Nov 13 '20 18:11 carun

Thanks for your help. Passing --filter branch option to lcov removes the branch false positives altogether. Good work. However even with --no-external, genhtml produces coverage for external libraries. Let me dig a bit more.

image

carun avatar Nov 14 '20 00:11 carun

I've raised https://github.com/henry2cox/lcov/pull/1 to fix the issue with --no-external. Please review.

carun avatar Nov 14 '20 02:11 carun

Are there any news about this topic?

RafaelRey avatar Nov 14 '22 08:11 RafaelRey

Hi - I think I will let Peter add any update with respect to schedule - but the fixes described above (now in PR #169) will be merged "soon". :-) As discussed in other reports, please note that the filtering hack is something of a hack - and can be easily defeated by a bloody-minded user. You may also need to add 'noexcept' to some functions. With respect to the 'no external' issue mentioned above: I can't reproduce the issue :-( (works for me). Henry

henry2cox avatar Nov 14 '22 11:11 henry2cox

Resolved no-external issue by removing the option from ~/.lcovrc

carun avatar Nov 15 '22 18:11 carun

I think this issue (bogus branch coverpoints) is addressed in SHA 5f659f63801e (as discussed above). I also completely agree that this approach is a workaround verging on ugly hack :-)

If you think that the issue is resolved: please close this issue. If it isn't fixed: please clarify what else should be done. Note that all real solutions probably need to be done within the compiler infrastructure. I don't think that lcov will ever have such infrastructure (though tools feeding or filtering lcov might).

Henry

henry2cox avatar Dec 08 '22 08:12 henry2cox

Hey @henry2cox looks like your PR got merged. Congrats. Great work on that.

I'll test from the master branch of this repo when I get time and close this issue after that.

carun avatar Dec 09 '22 01:12 carun

Works as expected with --filter branch

carun avatar Dec 20 '22 06:12 carun

I see a different result than you do...works for me. $ g++ -fprofile-arcs -ftest-coverage -g -o foo -std=c++11 foo.cpp $ ./foo 1 $ lcov --rc lcov_branch_coverage=1 --no-external -d . -o foo.info -c Capturing coverage data from . geninfo cmd: '/home/hcox/pwa/dspMethLibs/releng/coverage/lcov/bin/geninfo . --output-filename foo.info --no-external --rc lcov_branch_coverage=1'Found gcov version: 5.2.0 Using intermediate gcov format Scanning . for .gcda files ... Found 1 data files in . Processing foo.gcda Finished .info-file creation $ ../../bin/genhtml -s --rc lcov_branch_coverage=1 --branch-coverage --legend foo.info -o rpt Reading data file foo.info Found 2 entries. Found common filename prefix "/home/hcox/pwa/dspMethLibs/releng/coverage/lcov/tests" Writing .css and .png files. Generating output. processing dir /mtkoss/gcc/5.2.0-rhel6/x86_64/include/c++/5.2.0 Processing file /mtkoss/gcc/5.2.0-rhel6/x86_64/include/c++/5.2.0/iostream lines=1 hit=1 processing dir /home/hcox/pwa/dspMethLibs/releng/coverage/lcov/tests/foo Processing file foo/foo.cpp lines=13 hit=13 Writing directory view page. Overall coverage rate: lines......: 100.0% (14 of 14 lines) functions......: 100.0% (3 of 3 functions) branches......: 50.0% (10 of 20 branches) image

Running again with branch filtering... $ genhtml -s --rc lcov_branch_coverage=1 --branch-coverage --filter branch --legend foo.info -o rpt2 Reading data file foo.info reading /home/hcox/pwa/dspMethLibs/releng/coverage/lcov/tests/foo/foo.cpp (for bogus branch filtering) Found 2 entries. Found common filename prefix "/home/hcox/pwa/dspMethLibs/releng/coverage/lcov/tests" Writing .css and .png files. Generating output. processing dir /mtkoss/gcc/5.2.0-rhel6/x86_64/include/c++/5.2.0 Processing file /mtkoss/gcc/5.2.0-rhel6/x86_64/include/c++/5.2.0/iostream lines=1 hit=1 processing dir /home/hcox/pwa/dspMethLibs/releng/coverage/lcov/tests/foo Processing file foo/foo.cpp lines=13 hit=13 Writing directory view page. Overall coverage rate: lines......: 100.0% (14 of 14 lines) functions......: 100.0% (3 of 3 functions) branches......: 50.0% (2 of 4 branches) Filter suppressions 'branch': 6 instances 16 coverpoints image

image

ubuntu 2020.04 lcov 1.14 Follow your operation,but result is not same could you tell me ,what`s wrong with me,please

yi452873250 avatar Mar 30 '23 02:03 yi452873250

wrong version. looks like you are using lcov 1.14 (very, very old). --filter option is much newer and is not yet available in any numbered release. You need to download latest version and install from github.

henry2cox avatar Mar 30 '23 10:03 henry2cox

Just curious, how does this get downstreamed to different distros, say the next version of Ubuntu? Do you notify them or do they track and pull the latest?

carun avatar Mar 30 '23 15:03 carun

Now there you have me. No idea. Perhaps Peter knows.

henry2cox avatar Mar 30 '23 15:03 henry2cox

image

hi,I have updated the lcov ,bug not effect.it`s unblivable

yi452873250 avatar Mar 31 '23 02:03 yi452873250

Looks like you did not update to TOT (top of tree) - or you are not using the TOT version that you updated. which genhtml might be instructive. genhtml --version might also be useful. Similarly, just running /full/path/to/where/you/installed/genhtml ... would likely do what you wanted.

henry2cox avatar Apr 04 '23 14:04 henry2cox