Imagine the following function:
int myFunction(my_enum_t x)
{
int result = 0;
if ((x != ENUM_VAL_A) &&
(x != ENUM_VAL_B) &&
(x != ENUM_VAL_C))
{
result = -1;
}
if (0 == result)
{
result = mutateSomething(x);
}
if (0 == result)
{
if (x == ENUM_VAL_A)
{
result = doOneThing();
}
else if (x == ENUM_VAL_B)
{
result = doThing2();
}
else if (x == ENUM_VAL_C)
{
result = doThing3();
}
/* Invisible else */
}
return result;
}
Whether in the interests of clarity or to avoid complicating mutateSomething(), I would like to keep the checks on x before that call, however, gcov will see the invisible else where I've commented. That branch cannot be covered. I am, for this reason, using the --exclude-unreachable-branches switch of gcovr, but this branch is still regarded as uncovered.
Is there any way to avoid this without removing the checks on x at the start of the function?
I sometimes wrap the whole final else if
else if (x == ENUM_VAL_C)
{...}
in exclusion tags, on the basis that I am allowed 2% uncovered code, but this is not possible in sources with one or two functions.
Since you have already verified that
xis one of the three permissible values at the start of the function, you can change your finalelse ifinto anelse, which means your logic ends with an explicitelse. i.e.I find it a bit horrible, but when you're doing code coverage and unit-testing, sometimes you've got to do things like that. Specifically, any "belts and braces" and "this can't happen" code paths can't be tested. Hopefully your tests will catch the case if, in the future, you add
ENUM_VAL_D.Aside: some standards (such as MISRA) demand that an
if...else if...chain ends with a finalelse. (MISRA-C-2012 rule 15.7). I can see the justification for it.