On Thu, 20 Apr 2023, Patrick Palka wrote: > 1. Now that we no longer substitute the constraints of an auto, we can > get rid of the infinite recursion loop breaker during level lowering > of a constrained auto and we can also use the TEMPLATE_PARM_DESCENDANTS > cache in this case. > 2. Don't bother recursing when level lowering a cv-qualified type template > parameter. > 3. Use TEMPLATE_PARM_DESCENDANTS when level lowering a non-type template > parameter too. > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > trunk? > > gcc/cp/ChangeLog: > > * pt.cc (tsubst) <case TEMPLATE_TYPE_PARM>: Remove infinite > recursion loop breaker in the level lowering case for > constrained autos. Use the TEMPLATE_PARM_DESCENDANTS cache in > this case as well. > <case TEMPLATE_PARM_INDEX>: Use the TEMPLATE_PARM_INDEX cache > when level lowering a non-type template parameter. > --- > gcc/cp/pt.cc | 42 ++++++++++++++++++++---------------------- > 1 file changed, 20 insertions(+), 22 deletions(-) > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > index f65f2d58b28..07e9736cdce 100644 > --- a/gcc/cp/pt.cc > +++ b/gcc/cp/pt.cc > @@ -16228,33 +16228,23 @@ tsubst (tree t, tree args, tsubst_flags_t complain, > tree in_decl) > /* If we get here, we must have been looking at a parm for a > more deeply nested template. Make a new version of this > template parameter, but with a lower level. */ > + int quals; > switch (code) > { > case TEMPLATE_TYPE_PARM: > case TEMPLATE_TEMPLATE_PARM: > - if (cp_type_quals (t)) > + quals = cp_type_quals (t); > + if (quals) > { > - r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl); > - r = cp_build_qualified_type > - (r, cp_type_quals (t), > - complain | (code == TEMPLATE_TYPE_PARM > - ? tf_ignore_bad_quals : 0)); > + gcc_checking_assert (code == TEMPLATE_TYPE_PARM); > + t = TYPE_MAIN_VARIANT (t); > } > - else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM > - && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t) > - && (r = (TEMPLATE_PARM_DESCENDANTS > - (TEMPLATE_TYPE_PARM_INDEX (t)))) > - && (r = TREE_TYPE (r)) > - && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r)) > - /* Break infinite recursion when substituting the constraints > - of a constrained placeholder. */; > - else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM > - && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t) > - && (arg = TEMPLATE_TYPE_PARM_INDEX (t), > - r = TEMPLATE_PARM_DESCENDANTS (arg)) > - && (TEMPLATE_PARM_LEVEL (r) > - == TEMPLATE_PARM_LEVEL (arg) - levels)) > - /* Cache the simple case of lowering a type parameter. */ > + if (TREE_CODE (t) == TEMPLATE_TYPE_PARM > + && (arg = TEMPLATE_TYPE_PARM_INDEX (t), > + r = TEMPLATE_PARM_DESCENDANTS (arg)) > + && (TEMPLATE_PARM_LEVEL (r) > + == TEMPLATE_PARM_LEVEL (arg) - levels)) > + /* Cache the simple case of lowering a type parameter. */ > r = TREE_TYPE (r); > else > { > @@ -16278,6 +16268,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, > tree in_decl) > else > TYPE_CANONICAL (r) = canonical_type_parameter (r); > } > + if (quals) > + r = cp_build_qualified_type (r, quals, > + complain | tf_ignore_bad_quals); > break; > > case BOUND_TEMPLATE_TEMPLATE_PARM: > @@ -16307,7 +16300,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain, > tree in_decl) > type = tsubst (type, args, complain, in_decl); > if (type == error_mark_node) > return error_mark_node; > - r = reduce_template_parm_level (t, type, levels, args, complain); > + if ((r = TEMPLATE_PARM_DESCENDANTS (t)) > + && (TEMPLATE_PARM_LEVEL (r) == TEMPLATE_PARM_LEVEL (t) - levels) > + && TREE_TYPE (r) == type) > + /* Cache the simple case of lowering a non-type parameter. */; > + else > + r = reduce_template_parm_level (t, type, levels, args, complain);
D'oh, this hunk is totally redundant since reduce_template_parm_level already checks TEMPLATE_PARM_DESCENDANTS, and so we've been caching level-lowering of non-type template parameters this whole time. Please consider this patch instead, which removes this hunk and therefore only changes TEMPLATE_TYPE_PARM level lowering: -- >8 -- Subject: [PATCH] c++: improve TEMPLATE_TYPE_PARM level lowering 1. Don't bother recursing when level lowering a cv-qualified type template parameter. 2. Get rid of the infinite recursion loop breaker during level lowering of a constrained auto and use the TEMPLATE_PARM_DESCENDANTS cache in this case too, now that we no longer substitute its constraints. gcc/cp/ChangeLog: * pt.cc (tsubst) <case TEMPLATE_TYPE_PARM>: Don't recurse when level lowering a cv-qualified type template parameter. Remove infinite recursion loop breaker in the level lowering case for constrained autos. Use the TEMPLATE_PARM_DESCENDANTS cache in this case as well. --- gcc/cp/pt.cc | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index f65f2d58b28..ed038b9ca24 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -16228,33 +16228,23 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) /* If we get here, we must have been looking at a parm for a more deeply nested template. Make a new version of this template parameter, but with a lower level. */ + int quals; switch (code) { case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: - if (cp_type_quals (t)) + quals = cp_type_quals (t); + if (quals) { - r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl); - r = cp_build_qualified_type - (r, cp_type_quals (t), - complain | (code == TEMPLATE_TYPE_PARM - ? tf_ignore_bad_quals : 0)); + gcc_checking_assert (code == TEMPLATE_TYPE_PARM); + t = TYPE_MAIN_VARIANT (t); } - else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM - && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t) - && (r = (TEMPLATE_PARM_DESCENDANTS - (TEMPLATE_TYPE_PARM_INDEX (t)))) - && (r = TREE_TYPE (r)) - && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r)) - /* Break infinite recursion when substituting the constraints - of a constrained placeholder. */; - else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM - && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t) - && (arg = TEMPLATE_TYPE_PARM_INDEX (t), - r = TEMPLATE_PARM_DESCENDANTS (arg)) - && (TEMPLATE_PARM_LEVEL (r) - == TEMPLATE_PARM_LEVEL (arg) - levels)) - /* Cache the simple case of lowering a type parameter. */ + if (TREE_CODE (t) == TEMPLATE_TYPE_PARM + && (arg = TEMPLATE_TYPE_PARM_INDEX (t), + r = TEMPLATE_PARM_DESCENDANTS (arg)) + && (TEMPLATE_PARM_LEVEL (r) + == TEMPLATE_PARM_LEVEL (arg) - levels)) + /* Cache the simple case of lowering a type parameter. */ r = TREE_TYPE (r); else { @@ -16278,6 +16268,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) else TYPE_CANONICAL (r) = canonical_type_parameter (r); } + if (quals) + r = cp_build_qualified_type (r, quals, + complain | tf_ignore_bad_quals); break; case BOUND_TEMPLATE_TEMPLATE_PARM: -- 2.40.0.352.g667fcf4e15