diff options
author | Patrick Palka <ppalka@redhat.com> | 2022-07-07 16:46:29 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2022-07-07 16:46:29 -0400 |
commit | 7b90f07f778caa5e09f3dc20a8c3da1f4cf60c20 (patch) | |
tree | ce5b7e4e6e7f79679efeb04fbe90cda6a3963b69 /gcc/incpath.cc | |
parent | 52f538fa4a13d5d439f6db2c2657791fbddd934c (diff) | |
download | gcc-7b90f07f778caa5e09f3dc20a8c3da1f4cf60c20.zip gcc-7b90f07f778caa5e09f3dc20a8c3da1f4cf60c20.tar.gz gcc-7b90f07f778caa5e09f3dc20a8c3da1f4cf60c20.tar.bz2 |
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.
Diffstat (limited to 'gcc/incpath.cc')
0 files changed, 0 insertions, 0 deletions