On Wed, 26 Nov 2025, Patrick Palka wrote:

> On Wed, 26 Nov 2025, Marek Polacek wrote:
> 
> > On Mon, Nov 24, 2025 at 08:20:10PM -0500, Patrick Palka wrote:
> > > On Mon, 24 Nov 2025, Marek Polacek wrote:
> > > 
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/15?
> > > > 
> > > > -- >8 --
> > > > In my r15-6792 patch I added a call to tsubst in tsubst_pack_index
> > > > to fully instantiate args#N in the pack.
> > > > 
> > > > Here we are in an unevaluated context, but since the pack is
> > > > a TREE_VEC, we call tsubst_template_args which has cp_evaluated
> > > > at the beginning.  That causes a crash because we trip on the
> > > > assert in tsubst_expr/PARM_DECL:
> > > > 
> > > >   gcc_assert (cp_unevaluated_operand);
> > > > 
> > > > because retrieve_local_specialization didn't find anything (becase
> > > > there are no local_specializations yet).
> > > > 
> > > > ISTM that we don't need a full instantiation in an unevaluated context
> > > > so we can avoid the crash like this.
> > > 
> > > Hmm, it doesn't seem right to avoid doing a substitution solely because
> > > we're in an unevaluated context..
> > > 
> > > Here the TREE_VEC is just a subexpression of the templated
> > > PACK_INDEX_EXPR, not a template argument list, so we should still
> > > substitute it normally, just without setting cp_evaluated, I think.
> > 
> > I think you're right.  How about I just walk the TREE_VEC and subst
> > each element, like this?
> 
> In-place modification of a templated tree is unusual for tsubst, we
> probably should just return a new TREE_VEC.  I think we could use a
> version of tsubst_template_args that doesn't do cp_evaluated
> (tsubst_tree_vec?), define tsubst_template_args in terms of that, and
> also use it here?

Actually never mind about the idea of defining tsubst_template_args
in terms of tsubst_tree_vec... tsubst_template_args does a lot of
stuff that's specific to template arguments which wouldn't be suitable
for TREE_VEC expression substitution.  I suppose we could just use a
standalone tsubst_tree_vec routine that tsubsts each element and returns
a new TREE_VEC.

(I believe TRAIT_EXPR is another tree that has a TREE_VEC subexpression
and probably has a similiar bug wrt cp_evaluated being set, so we could
use tsubst_tree_vec there as well.)

> 
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > In my r15-6792 patch I added a call to tsubst in tsubst_pack_index
> > to fully instantiate args#N in the pack.
> > 
> > Here we are in an unevaluated context, but since the pack is
> > a TREE_VEC, we call tsubst_template_args which has cp_evaluated
> > at the beginning.  That causes a crash because we trip on the
> > assert in tsubst_expr/PARM_DECL:
> > 
> >   gcc_assert (cp_unevaluated_operand);
> > 
> > because retrieve_local_specialization didn't find anything (becase
> > there are no local_specializations yet).
> > 
> > We can avoid the cp_evaluated by calling tsubst_template_arg on
> > each element of the TREE_VEC.  I'm still using tsubst_template_arg
> > for convenience (tsubst for types, tsubst_expr otherwise).
> > 
> >     PR c++/121325
> > 
> > gcc/cp/ChangeLog:
> > 
> >     * pt.cc (tsubst_pack_index): Instead of tsubst, call
> >     tsubst_template_arg on each element of the TREE_VEC.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> >     * g++.dg/cpp26/pack-indexing18.C: New test.
> > ---
> >  gcc/cp/pt.cc                                 |  3 +-
> >  gcc/testsuite/g++.dg/cpp26/pack-indexing18.C | 32 ++++++++++++++++++++
> >  2 files changed, 34 insertions(+), 1 deletion(-)
> >  create mode 100644 gcc/testsuite/g++.dg/cpp26/pack-indexing18.C
> > 
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index e74e34d8149..6d8eca044b9 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -14220,7 +14220,8 @@ tsubst_pack_index (tree t, tree args, 
> > tsubst_flags_t complain, tree in_decl)
> >      a partially instantiated closure.  Let tsubst find the
> >      fully-instantiated one.  */
> >        gcc_assert (TREE_CODE (pack) == TREE_VEC);
> > -      pack = tsubst (pack, args, complain, in_decl);
> > +      for (tree &arg : tree_vec_range (pack))
> > +   arg = tsubst_template_arg (arg, args, complain, in_decl);
> >      }
> >    if (TREE_CODE (pack) == TREE_VEC && TREE_VEC_LENGTH (pack) == 0)
> >      {
> > diff --git a/gcc/testsuite/g++.dg/cpp26/pack-indexing18.C 
> > b/gcc/testsuite/g++.dg/cpp26/pack-indexing18.C
> > new file mode 100644
> > index 00000000000..d3e3730408c
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp26/pack-indexing18.C
> > @@ -0,0 +1,32 @@
> > +// PR c++/121325
> > +// { dg-do compile { target c++26 } }
> > +
> > +void f(auto... a) requires requires { []<int i = 0> 
> > noexcept(noexcept(a...[i])) { }(); } {}
> > +void g(auto... a) requires requires { []<int i = 0> { 
> > static_assert(noexcept(a...[i])); }(); } {}
> > +
> > +void
> > +h ()
> > +{
> > +  f (0);
> > +  g (0);
> > +}
> > +
> > +void foo () {}
> > +void bar () noexcept {}
> > +template<bool B>
> > +void baz () noexcept(B) {}
> > +
> > +template<typename... Ts>
> > +void
> > +x (Ts... ts) noexcept (noexcept (ts...[0]()))
> > +{
> > +}
> > +
> > +void
> > +y ()
> > +{
> > +  static_assert (!noexcept (x (foo)));
> > +  static_assert (noexcept (x (bar)));
> > +  static_assert (noexcept (x (baz<true>)));
> > +  static_assert (!noexcept (x (baz<false>)));
> > +}
> > 
> > base-commit: e97550a7d0e1a8b31a76b0877c0e90a0163da7ee
> > -- 
> > 2.51.1
> > 
> > 
> 

Reply via email to