If the the (number of) branches depend on the template argument a mismatched exception tag may be generated as lcov assumes that a single line has the same branches on all invocations.
Example
Consider the following example:
#include <exception>
struct Throw {Throw () {throw std::exception();}};
struct NoThrow {NoThrow () {}};
static int a;
template<typename T>
bool test()
{
return new T() && a > 0 ? 1 : 0; // <-- this is the line lcov is complaining about
}
int main()
{
try {test<Throw>();} catch (...) {}
test<NoThrow>();
}
Generating branch coverage fails with the following error:
mismatched exception tag for id 3, 3: '0' -> '1'
I think this is an lcov issue, and not a gcov one as the output of gcov make sense:
...
{
"line_number": 11,
"function_name": "_Z4testI7NoThrowEbv",
"count": 3,
"unexecuted_block": true,
"branches": [
{
"count": 3,
"throw": false,
"fallthrough": true
},
{
"count": 0,
"throw": true,
"fallthrough": false
},
{
"count": 3,
"throw": false,
"fallthrough": true
},
{
"count": 0,
"throw": false, // <-- 4th branch is NOT an exception branch for test<NoThrow> function
"fallthrough": false
},
... 6 more branches
]
},
{
"line_number": 11,
"function_name": "_Z4testI5ThrowEbv",
"count": 3,
"unexecuted_block": true,
"branches": [
{
"count": 3,
"throw": false,
"fallthrough": true
},
{
"count": 0,
"throw": true,
"fallthrough": false
},
{
"count": 0,
"throw": false,
"fallthrough": true
},
{
"count": 3,
"throw": true, // <-- 4th branch is an exception branch for test<Throw> function
"fallthrough": false
},
... 8 more branches
]
},
...
test<Throw> contains more (exception) branches than test<NoThrow> because the Throw constructor throws an exception and the NoThrow constructor doesn't.
Possible solutions
- Create a separate coverage report per set of function template arguments. Disadvantage is that it may result in a very long coverage report in case the template is used with many different arguments.
- When merging branch coverage for template instantiations with a different set of template arguments (i.e. a different
function_name), merge the exception and non-exception branches separately, i.e. merge the 1th/2nd/3th/... exception branch with the 1th/2nd/3th/... exception branch and the merge the 1th/2nd/3th/... non-exception branch with the 1th/2nd/3th/... non-exception branch. This is not 100% correct either, but is at least better than the current approach.
If the the (number of) branches depend on the template argument a mismatched exception tag may be generated as
lcovassumes that a single line has the same branches on all invocations.Example
Consider the following example:
Generating branch coverage fails with the following error:
I think this is an lcov issue, and not a gcov one as the output of gcov make sense:
test<Throw>contains more (exception) branches thantest<NoThrow>because theThrowconstructor throws an exception and theNoThrowconstructor doesn't.Possible solutions
function_name), merge the exception and non-exception branches separately, i.e. merge the 1th/2nd/3th/... exception branch with the 1th/2nd/3th/... exception branch and the merge the 1th/2nd/3th/... non-exception branch with the 1th/2nd/3th/... non-exception branch. This is not 100% correct either, but is at least better than the current approach.