Skip to content

Mismatched exception tag in function template #467

@m7913d

Description

@m7913d

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions