https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104629
Bug ID: 104629 Summary: Constexpr static functions and variables in templates, in the wrong order and under specific circumstances produces ICEs under some versions, compiles (but shouldn't) on others Product: gcc Version: 11.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: ahajha at gmail dot com Target Milestone: --- The following code, as far as I can tell, is invalid C++. Recent versions of other compilers reject this, citing that foo() has is not found at its use in Inner(). template<class...> struct Outer { struct Inner { constexpr Inner() { foo(); } }; constexpr static auto inner = Inner{}; constexpr void foo(); }; int main() { auto x = Outer<>::inner; } This code produces ICEs under versions 7.x, 8.x, and 11.x. Under 7.x and 8.x, the error is as follows: <source>: In instantiation of 'constexpr Outer< <template-parameter-1-1> >::Inner::Inner() [with <template-parameter-1-1> = {}]': <source>:9:24: recursively required from 'constexpr const Outer<>::Inner Outer<>::inner' <source>:9:24: required from 'struct Outer<>' <source>:16:18: required from here <source>:6:23: internal compiler error: in finish_expr_stmt, at cp/semantics.c:678 constexpr Inner() { foo(); } ^~~ mmap: Invalid argument (The last line "mmap: Invalid argument", seems to randomly appear with some minor versions and not with others) Under 11.2.0, the error is as follows: ice1.cpp: In instantiation of ‘constexpr Outer< <template-parameter-1-1> >::Inner::Inner() [with <template-parameter-1-1> = {}]’: ice1.cpp:9:24: recursively required from ‘constexpr const Outer<>::Inner Outer<>::inner’ ice1.cpp:9:24: required from ‘struct Outer<>’ ice1.cpp:16:18: required from here ice1.cpp:6:37: internal compiler error: in finish_expr_stmt, at cp/semantics.c:860 6 | constexpr Inner() { foo(); } | ^~~ 0x6fc478 finish_expr_stmt(tree_node*) ../../src/gcc/cp/semantics.c:860 0x116c048 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../src/gcc/cp/pt.c:18233 0x116beb5 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../src/gcc/cp/pt.c:18550 0x116bf43 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../src/gcc/cp/pt.c:18199 0x116beb5 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../src/gcc/cp/pt.c:18550 0x1228bd0 instantiate_body ../../src/gcc/cp/pt.c:25876 0x1227ffa instantiate_decl(tree_node*, bool, bool) ../../src/gcc/cp/pt.c:26170 0x10145fd instantiate_cx_fn_r ../../src/gcc/cp/constexpr.c:7085 0xf49a8a walk_tree_1(tree_node**, tree_node* (*)(tree_node**, int*, void*), void*, hash_set<tree_node*, false, default_hash_traits<tree_node*> >*, tree_node* (*)(tree_node**, int*, tree_node* (*)(tree_node**, int*, void*), void*, hash_set<tree_node*, false, default_hash_traits<tree_node*> >*)) ../../src/gcc/tree.c:12108 0xf49c51 walk_tree_1(tree_node**, tree_node* (*)(tree_node**, int*, void*), void*, hash_set<tree_node*, false, default_hash_traits<tree_node*> >*, tree_node* (*)(tree_node**, int*, tree_node* (*)(tree_node**, int*, void*), void*, hash_set<tree_node*, false, default_hash_traits<tree_node*> >*)) ../../src/gcc/tree.c:12456 0xf49692 walk_tree_without_duplicates_1(tree_node**, tree_node* (*)(tree_node**, int*, void*), void*, tree_node* (*)(tree_node**, int*, tree_node* (*)(tree_node**, int*, void*), void*, hash_set<tree_node*, false, default_hash_traits<tree_node*> >*)) ../../src/gcc/tree.c:12482 0x101054c instantiate_constexpr_fns ../../src/gcc/cp/constexpr.c:7105 0x101054c cxx_eval_outermost_constant_expr ../../src/gcc/cp/constexpr.c:7259 0x10202ec maybe_constant_value(tree_node*, tree_node*, bool) ../../src/gcc/cp/constexpr.c:7518 0xffbe4b fold_non_dependent_expr(tree_node*, int, bool, tree_node*) ../../src/gcc/cp/constexpr.c:7644 0xffbe4b store_init_value(tree_node*, tree_node*, vec<tree_node*, va_gc, vl_embed>**, int) ../../src/gcc/cp/typeck2.c:777 0xfeb03b check_initializer ../../src/gcc/cp/decl.c:7130 0xfdce84 cp_finish_decl(tree_node*, tree_node*, bool, tree_node*, int) ../../src/gcc/cp/decl.c:8064 0x1228354 instantiate_decl(tree_node*, bool, bool) ../../src/gcc/cp/pt.c:26130 0x65e75d cp_finish_decl(tree_node*, tree_node*, bool, tree_node*, int) ../../src/gcc/cp/decl.c:7783 This code compiles (which I believe it shouldn't) without warnings (other than x being unused) under version 9.x and 10.x. All versions were tested using https://godbolt.org/, and GCC 11.2.0 was also tested locally, the configuration is attached. Compiler flags used for all tests: -Wall -Wextra -std=c++14 (I believe the same behavior happens under C++17 and 20)