What is the best way to find uninstantiated templates in C++ Code?
I have a code base that heavily uses templates.
Of course, we want to make sure that the test coverage is high.
For all used code, this works very well using gcov
.
However, unused templates are reported as non-executable by gcov
.
After some googling, it appears that there is no way to force g++
to emit code for these templates (which is only logical, how should the compiler guess any types?)
It also appears that there is no way to make gcov recognize the uninstantiated template code as runnable code.
Is there anything "out of the box" that allows me to augment the files generated by the GCC -ftest-coverage -fprofile-arcs
instrumentation? By the gcov option documentation of GCC, it would probably be enough to mark the whole template function body as one block since execution will never end up there.
EDIT (background information): I'm working on a header-only template library. My aim here is to find unused/untested functions.
I know that code coverage is flawed but finding uninstantiated code is a very important step towards better tested code.
Currently, we are putting checkpoint macros at the beginning of each function.
In testing mode, they expand to code that inserts a pair of (file, line)
into a global set of passed checkpoints.
After running the tests, we manually read all files and compare the reached checkpoints with the set of all available checkpoints.
Finding uninstantiated code is important, for example, because of unintuitive C++ template precedence behaviour, there might be dead code somewhere that the reader or even the author would expect to be used.
I think our C++ Test Coverage tool (not GCC-based) does this correctly from your point of view.
It instruments the source code before the compiler sees it; code inside templates get "coverage probes" regardless of whether the template gets used or not. The test coverage display portion of the tool knows where all the probes are; if the template code isn't instantiated, it clearly can't be executed that's what will get reported. You don't have to do any "custom" macro insertion or other, er, BS.
The downside is that if you have a template parameterized by several different types, and template method m1 and m2 are executed for different instantiated types, your coverage for m1 and m2 will be 100% (after all, you executed the instrumented template). It isn't clear this is bad; just that it is how this is interpreted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With