GCC 7 fails to compile the following code: ---- test.cpp ---- template <class T> struct StaticObject { static T& create() { static T t; return t; } static T & instance; }; template <class T> T & StaticObject<T>::instance = StaticObject<T>::create(); extern template class StaticObject<int>; void test() { StaticObject<int>::instance; } ---- command line ----- $ g++-7.3.0 -v Using built-in specs. COLLECT_GCC=g++-7.3.0 COLLECT_LTO_WRAPPER=/home/brd/soft/gcc-7.3.0/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: ./configure --prefix=/home/brd/soft/gcc-7.3.0 Thread model: posix gcc version 7.3.0 (GCC) $ g++-7.3.0 -c test.cpp test.cpp: In instantiation of ‘int& StaticObject<int>::instance’: test.cpp:19:24: required from here test.cpp:13:75: error: call to non-constexpr function ‘static T& StaticObject<T>::create() [with T = int]’ template <class T> T & StaticObject<T>::instance = StaticObject<T>::create(); P.S. I also tried 7.1 (same error) and 6.3 (no error)
This is rejected starting with r242422.
r200450 added - if (DECL_DECLARED_CONSTEXPR_P (decl)) + if (DECL_DECLARED_CONSTEXPR_P (decl) + || DECL_IN_AGGR_P (decl)) I wonder if it shouldn't have been DECL_INITIALIZED_IN_CLASS_P instead, or DECL_IN_AGGR_P (decl) && DECL_INITIALIZED_IN_CLASS_P (decl). If DECL_IN_AGGR_P (decl) check is right here, then the question is why it is set when there is the extern template line (and not otherwise).
--- gcc/cp/typeck2.c.jj 2018-04-19 15:57:36.765482568 +0200 +++ gcc/cp/typeck2.c 2018-04-19 19:32:43.335986274 +0200 @@ -824,7 +824,9 @@ store_init_value (tree decl, tree init, bool const_init; value = fold_non_dependent_expr (value); if (DECL_DECLARED_CONSTEXPR_P (decl) - || (DECL_IN_AGGR_P (decl) && !DECL_VAR_DECLARED_INLINE_P (decl))) + || (DECL_CLASS_SCOPE_P (decl) + && DECL_INITIALIZED_IN_CLASS_P (decl) + && !DECL_VAR_DECLARED_INLINE_P (decl))) { /* Diagnose a non-constant initializer for constexpr. */ if (!require_constant_expression (value)) just changes the error, from pr85470.C:13:75: error: call to non-‘constexpr’ function ‘static T& StaticObject<T>::create() [with T = int]’ to pr85470.C:13:24: error: non-constant in-class initialization invalid for static member ‘StaticObject<int>::instance’ cpp0x/overflow1.C still PASSes.
Author: jason Date: Mon Apr 23 19:11:22 2018 New Revision: 259571 URL: https://gcc.gnu.org/viewcvs?rev=259571&root=gcc&view=rev Log: PR c++/85470 - wrong error with static data member. * decl.c (check_initializer): Check DECL_INITIALIZED_IN_CLASS_P. * typeck2.c (store_init_value): Likewise. Added: trunk/gcc/testsuite/g++.dg/cpp0x/extern_template-4.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/decl.c trunk/gcc/cp/typeck2.c
Author: jason Date: Mon Apr 23 19:58:57 2018 New Revision: 259572 URL: https://gcc.gnu.org/viewcvs?rev=259572&root=gcc&view=rev Log: PR c++/85470 - wrong error with static data member. * decl.c (check_initializer): Check DECL_INITIALIZED_IN_CLASS_P. * typeck2.c (store_init_value): Likewise. Added: branches/gcc-7-branch/gcc/testsuite/g++.dg/cpp0x/extern_template-4.C Modified: branches/gcc-7-branch/gcc/cp/ChangeLog branches/gcc-7-branch/gcc/cp/decl.c branches/gcc-7-branch/gcc/cp/typeck2.c
Fixed.