http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52069
--- Comment #8 from Thomas Betker <thomas.bet...@rohde-schwarz.com> 2012-02-01 10:51:58 UTC --- > There's a reason the standard says "no diagnostic required." > > When compiling libtmpl.so, how is the compiler supposed to know that a > different translation unit which it can't see (and which might not even have > been written yet) will implicitly instantiate the member? When compiling > main.o, how is the compiler supposed to know that an explicit specialization > exists in a separate translation unit which it can't see? Okay. So if I read the quote correctly, the standard does not require explicit specialization, it just requires that an explicit specialization, if present, is declared before any implicit instantiation. This explains why no there is no warning if the explicit specialization is missing. However, this also means that the test case does not violate the quoted rule because there is simply no explicit specialization at all. I am quite willing to believe that it is ill-formed, but the reason lies probably in the rules for implicit specialization; I will have to read up on this. > With optimisation enabled the compilation of main.o probably removes condition > because the constant is known to be zero because there has been no explicit > specialization declared. Without optimisation a weak symbol is emitted, which > may or may not be replaced by the weak symbol in libtmpl.so that has a > different value. objdump says that the symbol S<T>::id both in testbug and in libtmpl.so (with and without optimization) is a global, strong object in .bss; the symbol (exists and) is undefined in main.o. Without optimization, S<T>::id is initialized in libtmpl.so by __static_initialization_and_destruction_0(int, int) [which is called by '<global constructors keyed to S<T>::id']. When run on the target, the function is relocated to point to the object in testbug (i did a disassembly in gdb). So in some sense, it S<T>::id in libtmpl.so is indeed treated as a weak object. With optimization, S<T>::id is initialized in libtmpl.so directly by 'global constructors keyed to S<T>::id'. When run on the target, the function still points to the object in libtmpl.so, which no longer seems to be weak. I am afraid that this inconsistency still bothers me, apart from the fact that I couldn't reproduce the problem for x86. When the explicit specialization is added in tmpl.h, or just in tmpl.cpp, the symbol S<T>::id both in testbug and in libtmpl.so (with optimization) is a global, weak object in .bss.