https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65579
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |msebor at gcc dot gnu.org Known to fail| |4.9.3, 5.3.0, 6.0 --- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> --- Re-confirmed with today's top of trunk (6.0) and all prior supported versions that implement constexpr. See below. The difference between the template and non-template case is the readonly bit that's set on the 's' field when S is an ordinary struct. The bit is clear when S is a template. The bit gets set in the c_apply_type_quals_to_decl() function in c-family/c-common.c called from the cp_apply_type_quals_to_decl() function defined in cp/typeck.c. The latter function executes the following condition just before calling c_apply_type_quals_to_decl(). COMPLETE_TYPE_P (type) is false when S is a (specialization of a template), causing the TYPE_QUAL_CONST to clear. /* Avoid setting TREE_READONLY incorrectly. */ /* We used to check TYPE_NEEDS_CONSTRUCTING here, but now a constexpr constructor can produce constant init, so rely on cp_finish_decl to clear TREE_READONLY if the variable has non-constant init. */ /* If the type has (or might have) a mutable component, that component might be modified. */ if (TYPE_HAS_MUTABLE_P (type) || !COMPLETE_TYPE_P (type)) type_quals &= ~TYPE_QUAL_CONST; c_apply_type_quals_to_decl (type_quals, decl); When S is made complete by this point (e.g., by causing S<int> to be instantiated, say by declaring an object of the type), the bit stays set and the test program links. The c_apply_type_quals_to_decl() function the does the following: if ((type_quals & TYPE_QUAL_CONST) || (type && TREE_CODE (type) == REFERENCE_TYPE)) /* We used to check TYPE_NEEDS_CONSTRUCTING here, but now a constexpr constructor can produce constant init, so rely on cp_finish_decl to clear TREE_READONLY if the variable has non-constant init. */ TREE_READONLY (decl) = 1; The comments referencing constexpr suggest that TREE_READONLY should perhaps be set here and then cleared in cp_finish_decl. $ cat z.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc -B/home/msebor/build/gcc-trunk-svn/gcc -Wall -Wextra -Wpedantic -xc++ z.c template <typename> struct S { int i; }; struct T { static constexpr S<int> s = { 1 }; }; int main() { return T::s.i; } /tmp/ccqP3dAP.o: In function `main': z.c:(.text+0x6): undefined reference to `T::s' collect2: error: ld returned 1 exit status