https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105956

--- Comment #10 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Patrick Palka <ppa...@gcc.gnu.org>:

https://gcc.gnu.org/g:7b90f07f778caa5e09f3dc20a8c3da1f4cf60c20

commit r13-1565-g7b90f07f778caa5e09f3dc20a8c3da1f4cf60c20
Author: Patrick Palka <ppa...@redhat.com>
Date:   Thu Jul 7 16:46:29 2022 -0400

    c++: generic targs and identity substitution [PR105956]

    In r13-1045-gcb7fd1ea85feea I assumed that substitution into generic
    DECL_TI_ARGS corresponds to an identity mapping of the given arguments,
    and hence its safe to always elide such substitution.  But this PR
    demonstrates that such a substitution isn't always the identity mapping,
    in particular when there's an ARGUMENT_PACK_SELECT argument, which gets
    handled specially during substitution:

      * when substituting an APS into a template parameter, we strip the
        APS to its underlying argument;
      * and when substituting an APS into a pack expansion, we strip the
        APS to its underlying argument pack.

    In this testcase, when expanding the pack expansion pattern (idx + Ns)...
    with Ns={0,1}, we specialize idx twice, first with Ns=APS<0,{0,1}> and
    then Ns=APS<1,{0,1}>.  The DECL_TI_ARGS of idx are the generic template
    arguments of the enclosing class template impl, so before r13-1045,
    we'd substitute into its DECL_TI_ARGS which gave Ns={0,1} as desired.
    But after r13-1045, we elide this substitution and end up attempting to
    hash the original Ns argument, an APS, which ICEs.

    So this patch reverts that part of r13-1045.  I considered using
    preserve_args in this case instead, but that'd break the static_assert
    in the testcase because preserve_args always strips APS to its
    underlying argument, but here we want to strip it to its underlying
    argument pack, so we'd incorrectly end up forming the specializations
    impl<0>::idx and impl<1>::idx instead of impl<0,1>::idx.

    Although we can't elide the substitution into DECL_TI_ARGS in light of
    ARGUMENT_PACK_SELECT, it should still be safe to elide template argument
    coercion in the case of a non-template decl, which this patch preserves.

    It's unfortunate that we need to remove this optimization just because
    it doesn't hold for one special tree code.  So this patch implements a
    heuristic in tsubst_template_args to avoid allocating a new TREE_VEC if
    the substituted elements are identical to those of a level from ARGS, as
    well as a similar heuristic for tsubst_argument_pack.  It turns out that
    about 40% of all calls to tsubst_template_args benefit from this, and it
    reduces memory usage by about 4% for e.g. range-v3's zip.cpp (relative to
    r13-1045) which more than makes up for the reversion.

            PR c++/105956

    gcc/cp/ChangeLog:

            * pt.cc (template_arg_to_parm): Define.
            (tsubst_argument_pack): Try to reuse the corresponding
            ARGUMENT_PACK from 'args' when substituting into a generic
            ARGUMENT_PACK for a variadic template parameter.
            (tsubst_template_args): Move variable declarations closer to
            their first use.  Replace 'orig_t' with 'r'.  Rename 'need_new'
            to 'const_subst_p'.  Heuristically detect if the substituted
            elements are identical to that of a level from 'args' and avoid
            allocating a new TREE_VEC if so.  Add sanity check for the
            length of the new TREE_VEC, and remove dead ARGUMENT_PACK_P test.
            (tsubst_decl) <case TYPE_DECL, case VAR_DECL>: Revert
            r13-1045-gcb7fd1ea85feea change for avoiding substitution into
            DECL_TI_ARGS, but still avoid coercion in this case.

    gcc/testsuite/ChangeLog:

            * g++.dg/cpp0x/variadic183.C: New test.

Reply via email to