How to interpret the coverage report, specifically which branch is which branch #413
Description
Activity
Not clear if you are using gcc, llvm, or some other tool - but they all have similar issues, I fear.
Let's assume gcc for the moment.First - some background about what you see/what the underlying issue is:
Basically: the gcc/gcov data shows a branch point wherever the compiler decided to insert one - not necessarily on an explicit conditional in your source code. C++ exception handlers are one quite substantial cause.
We see this on line 103 where your actual conditional is basicalyif (!clone && ! empty) ...- but the compiler generated a bunch of handlers for you.To answer your original quesstion: given a conditional expression, your compiler builds an expression tree. The branch indices which appear in the lcov report are vertex labels from a traversal of that tree.
There may be multiple independent expressions on the same line - in which case the traversal order is "undefined" (gcc and llvm tend to evaluate in opposite orders).To work around this/to make it easier for lcov to filter out the bogus branches, you need to restructure your code so that the exception handlers don't get mixed into the conditionals (...this is not always possible/not always easy).
One way to do that is create two explicit booleans - but you can't completely do that in your code because your 'msg' temporary appears to be assigned in the caller (...possibly throwing an exception...) and only conditionally used.Filtering fails in this instance in your code because
--filter branchis looking for statements which contain branch data but do not contain conditionals...but it finds a conditional and so gives up.If you are using a new enough compiler (gcc/14 or newer, llvm/16 or newer) - then MC/DC metrics are somewhat cleaner in this respect (but not perfect).
Environment
GCC 9.3.0
Lcov 2.3.1 (with --filter branch,exception)We are given a line of code in C++ and the branch coverage report from lcov (with gcc 9.3.0). The line is:
if (!job->start(m_cloneSetting->getQueueName(), m_cloneSetting->getJobName(), m_cloneSetting->getLsfMisc(), m_cloneSetting->getThreadNumber(), msg) && !msg.isEmpty())
Without the --filter for branch and exception, there were 20 branches, and after applying the filter, it became 14.
The user wants to know the order of the branches in the report [ + + + + + - + - - - + - - - ] (note: the example has 14 signs) and specifically whether the first '+' corresponds to the parameters inside the function call (like m_cloneSetting->getQueueName()) or the function call itself. Also, they are asking for the pattern or rule of how branches are generated.
- locked and limited conversation to collaborators
on Sep 19, 2025
When using genhtml with --rc branch_coverage=1 --rc c_file_extensions=c,cpp,hpp,h,inl --filter branch,exception, how to identify exactly which branches are covered/uncovered in the generated report? Specifically:
For line 103 in my report (which shows 14 branches), which specific branches are covered (+) and which are not (-)?
Is there a quick method to locate uncovered branches in the report?