Istvan Knebli
Istvan Knebli

Reputation: 43

GCC 4.6.3 - template specialization is influenced by the optimization level?

In an application I'm developing I have a template function like this:

template<class T>
void CIO::writeln(T item)
{
    stringstream ss;
    ss << item << '\r' << endl;
    write(ss.str());
}

This function is called from several places, with T = const char* and T=std::string. With CodeSourcery Lite 2008.03-41 (GCC 4.3.2) this compiled and linked fine with -O3 compiler flag. However, since I changed to CodeSourcery Lite 2012.03-57 (GCC 4.6.3), compiling with -O3 is OK, but then linking fails with undefined reference to void CIO::writeln<std::string>(std::string). With -O2 or lower everything is OK, linking succeeds.

I had a deeper look into this and I discovered something strange in the assembly output: when compiling with -O2, I can find two specializations of the function: one for const char* (_ZN3CIO7writelnIPKcEEvT_) and one for std::string (_ZN3CIO7writelnISsEEvT_), but when compiling with -O3, the second specialization is missing, which explains the linking error.

Is this a compiler bug? Is this some weird optimization turned evil?

Thanks in advance!

Edit: this function is in a source file. Following Mike Seymour's comment, I moved it to the header and everything's fine now. I admit that I should've realized this earlier. Nevertheless, it still frightens me that a language rule is checked or not depending on an optimization flag.

Upvotes: 4

Views: 414

Answers (1)

user743382
user743382

Reputation:

Unlike what the other answer says, this is probably not a compiler bug.

One of the optimisations that gets enabled by -O3 is function inlining. What I think is happening is:

Source file 1 is calling CIO::writeln without having its definition available. It is compiled to object file 1.

Source file 2 is calling CIO::writeln while having its definition available. It is compiled to object file 2.

Object file 1 will only be usable if object file 2 contains the definition of CIO::writeln. If the call in source file 2 gets inlined, object file 2 won't contain a definition for it. If the call does not get inlined, a definition will be available.

The solution given in the comments, move the definition to a header file, is correct.

Upvotes: 1

Related Questions