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
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:
: In instantiation of 'constexpr Outer<
>::Inner::Inner() [with = {}]':
:9:24: recursively required from 'constexpr const Outer<>::Inner
Outer<>::inner'
:9:24: required from 'struct Outer<>'
:16:18: required from here
: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<
>::Inner::Inner() [with = {}]’:
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* (*)(tree_node**, int*, tree_node* (*)(tree_node**, int*, void*),
void*, hash_set >*))
../../src/gcc/tree.c:12108
0xf49c51 walk_tree_1(tree_node**, tree_node* (*)(tree_node**, int*, void*),
void*, hash_set >*,
tree_node* (*)(tree_node**, int*, tree_node* (*)(tree_node**, int*, void*),
void*, hash_set >*))
../../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 >*))
../../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**, 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)