Dear all,
I would like to instrument uninstantiated C++ function templates. When
compiling the program below with the -ftest-coverage and -fprofile-
arcs flags, I get according .gcno and .gcda files to run gcov and get
a coverage report.
In this report, the line marked with XXX will be marked with "00000"
executions. Function g, however, is not instantiated, so the line with
YYY will not be reported with any counter by gcov, i.e. it is
considered "not executable", similar to comments.
I would like to be able to change this behaviour so non-instantiated
code templates are considered as blocks (I think this is the term used
by GCC/GCov). This would help me greatly to uncover unused/untested
codes in a header/template-only library.
First of all: Is this feasible with the GCC infrastructure?
For this to work, one would probably need access to the internal
representation of the program. It is my understanding that there are
at least two distinct representations of a C++ program: (1) The AST
that only contains the parse tree, before any template instantiation
and (2) the intermediate language representation (GIMPLE?) that will
contain a representation of the instantiated templates. On which level
is coverage instrumentation added right now?
Second: Where would I start looking?
So far, I have discovered gcov*.{h,c} in the gcc directory. However, I
have not yet found where the .gcno files are written out in the
compiler.
Third: How hard would it be and how would I proceed?
Naively, my first guess at an approach would be: Locate where
the .gcno file is written out. After writing out all real blocks,
identify all uninitialized template functions, or member functions
that are members of templates, etc. etc. Add a "block" to the .gcno
file for each such function.
Since the blocks are not connected to the rest of the block graph,
they cannot be accessed by the program, there will be no reference to
them from the .gcda file and gcov will always report them as not
accessed.
Or is there maybe a simpler/better way?
Thanks,
Manuel
template <typename T>
T f(T x)
{
if (i % 2 == 0)
return x * 2; // XXX
else
return x * 3;
}
// This function template is never instantiated.
template <typename T>
T g(T x)
{
return x * 3; // YYY
}
int main(int argc, char ** argv)
{
int i = f(1);
return 0;
}