On Thu, Jun 04, 2026 at 05:20:30PM -0400, Jason Merrill wrote:
> On 6/4/26 3:39 PM, Marek Polacek wrote:
> > On Wed, Jun 03, 2026 at 03:41:56PM -0400, Jason Merrill wrote:
> > > 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?
> >
> > I think that looks better, and is a more general fix.
> >
> > dg.exp passed; ok for trunk/branches if the rest of the testing passes too?
> >
> > -- >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.
> >
> > We can fix this by returning early in build_cplus_new in a template,
> > like in build_aggr_init_expr.
> >
> > PR c++/125539
> >
> > gcc/cp/ChangeLog:
> >
> > * tree.cc (build_cplus_new): In a template, return before creating
> > a TARGET_EXPR.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/cpp1y/var-templ89.C: New test.
> > ---
> > gcc/cp/tree.cc | 5 ++++
> > gcc/testsuite/g++.dg/cpp1y/var-templ89.C | 32 ++++++++++++++++++++++++
> > 2 files changed, 37 insertions(+)
> > create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ89.C
> >
> > diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
> > index 360eae87698..df9dd562314 100644
> > --- a/gcc/cp/tree.cc
> > +++ b/gcc/cp/tree.cc
> > @@ -838,6 +838,11 @@ build_cplus_new (tree type, tree init, tsubst_flags_t
> > complain)
> > if (abstract_virtuals_error (NULL_TREE, type, complain))
> > return error_mark_node;
> > + /* As in build_aggr_init_expr. We don't want to create a TARGET_EXPR
> > + in a template. */
> > + if (processing_template_decl)
> > + return rval;
>
> I mentioned "if init has the right type"; we need to check that so we don't
> just return a void constructor call.
Oop, now I see what you meant, sorry.
If I check
if (processing_template_decl
&& same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (init)))
return rval;
then we crash on var-templ89.C with -std=c++14 because we don't
elide the copy, so have a ctor call, so the types don't match, so
we create a TARGET_EXPR.
Marek