On 6/2/26 5:59 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/branches?-- >8 -- Here we crash because a TARGET_EXPR gets into tsubst_expr with something like: template<typename> constexpr static A a = (A{}, A{}); Pre r14-4796, when we had tsubst_copy, we didn't crash because we had an early exit when substituting with args=NULL_TREE. tsubst_expr deliberately doesn't have that early exit. Note that template<typename> constexpr static A a = A{}; works because expand_aggr_init_1 sees a COMPOUND_LITERAL_P and does the early exit without calling expand_default_init. But with a COMPOUND_EXPR we don't take that path. The TARGET_EXPR is created via check_initializer -> build_aggr_init_full_exprs -> build_aggr_init -> expand_aggr_init_1 -> expand_default_init -> ocp_convert -> build_cplus_new -> build_target_expr. I tried adjusting the big and ugly check in check_initializer before build_aggr_init_full_exprs but that didn't work out. I also tried avoiding the call to ocp_convert but that broke some reflection tests. But avoiding the call to build_cplus_new seems to work. PR c++/125539 gcc/cp/ChangeLog: * cvt.cc (ocp_convert): Don't call build_cplus_new in a template.
I notice that build_aggr_init_expr already shortcuts processing_template_decl. What if we do that in build_cplus_new as well, if init has the right type?
gcc/testsuite/ChangeLog: * g++.dg/cpp1y/var-templ89.C: New test. --- gcc/cp/cvt.cc | 4 ++- gcc/testsuite/g++.dg/cpp1y/var-templ89.C | 32 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ89.C diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc index b1176317d99..571f2e64d03 100644 --- a/gcc/cp/cvt.cc +++ b/gcc/cp/cvt.cc @@ -985,7 +985,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags, type, flags, complain); } if (ctor) - return build_cplus_new (type, ctor, complain); + return (processing_template_decl + ? ctor + : build_cplus_new (type, ctor, complain)); }if (complain & tf_error)diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ89.C b/gcc/testsuite/g++.dg/cpp1y/var-templ89.C new file mode 100644 index 00000000000..5f98a95580c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ89.C @@ -0,0 +1,32 @@ +// PR c++/125539 +// { dg-do compile { target c++14 } } + +struct A {}; +struct B { int i; }; +constexpr void foo () {} + +template<typename T> +constexpr static A a1 = (foo (), A {}); +template<typename T> +constexpr static A a2 = (A{}, A{}); +template<typename T> +constexpr static A a3 = A{}; +template<typename T> +constexpr static A a4 = {}; +template<typename T> +constexpr static A a5{}; +template<typename T> +constexpr static A a6 = (A{}, A{}, A{}, A{}, A{}, A{}, A{}); +template<int N> +constexpr static B b1 = B{N}; +template<int N> +constexpr static B b2 = (B{N}, B{N}); + +template const A a1<int>; +template const A a2<int>; +template const A a3<int>; +template const A a4<int>; +template const A a5<int>; +template const A a6<int>; +template const B b1<42>; +template const B b2<42>; base-commit: ee7d0c7b4102b8ef0bcaa725c75e141248b774cb
