https://gcc.gnu.org/g:5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931
commit r15-3038-g5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931 Author: Patrick Palka <ppa...@redhat.com> Date: Tue Aug 20 08:34:36 2024 -0400 c++: default targ eligibility refinement [PR101463] On Tue, 9 Jan 2024, Jason Merrill wrote: > On 1/5/24 15:01, Patrick Palka wrote[1]: > > Here during default template argument substitution we wrongly consider > > the (substituted) default arguments v and vt<int> as value-dependent[1] > > which ultimately leads to deduction failure for the calls. > > > > The bogus value_dependent_expression_p result aside, I noticed > > type_unification_real during default targ substitution keeps track of > > whether all previous targs are known and non-dependent, as is the case > > for these calls. And in such cases it should be safe to avoid checking > > dependence of the substituted default targ and just assume it's not. > > This patch implements this optimization, which lets us accept both > > testcases by sidestepping the value_dependent_expression_p issue > > altogether. > > Hmm, maybe instead of substituting and asking if it's dependent, we should > specifically look for undeduced parameters. This patch implements this refinement, which incidentally fixes PR101463 just as well. [1]: https://gcc.gnu.org/pipermail/gcc-patches/2024-January/641957.html PR c++/101463 gcc/cp/ChangeLog: * pt.cc (type_unification_real): Directly look for undeduced parameters in the default argument instead of doing a trial substitution. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/nontype6.C: New test. * g++.dg/cpp1z/nontype6a.C: New test. Reviewed-by: Jason Merrill <ja...@redhat.com> Diff: --- gcc/cp/pt.cc | 41 ++++++++++++++++++---------------- gcc/testsuite/g++.dg/cpp1z/nontype6.C | 24 ++++++++++++++++++++ gcc/testsuite/g++.dg/cpp1z/nontype6a.C | 25 +++++++++++++++++++++ 3 files changed, 71 insertions(+), 19 deletions(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index ea660a5a5c6..bc3ad5edcc5 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -23619,28 +23619,31 @@ type_unification_real (tree tparms, is important if the default argument contains something that might be instantiation-dependent like access (87480). */ processing_template_decl_sentinel s (!any_dependent_targs); - tree substed = NULL_TREE; - if (saw_undeduced == 1 && !any_dependent_targs) + + tree used_tparms = NULL_TREE; + if (saw_undeduced == 1) { - /* First instatiate in template context, in case we still - depend on undeduced template parameters. */ - ++processing_template_decl; - substed = tsubst_template_arg (arg, full_targs, complain, - NULL_TREE); - --processing_template_decl; - if (substed != error_mark_node - && !uses_template_parms (substed)) - /* We replaced all the tparms, substitute again out of - template context. */ - substed = NULL_TREE; + tree tparms_list = build_tree_list (size_int (1), tparms); + used_tparms = find_template_parameters (arg, tparms_list); + for (; used_tparms; used_tparms = TREE_CHAIN (used_tparms)) + { + int level, index; + template_parm_level_and_index (TREE_VALUE (used_tparms), + &level, &index); + if (TREE_VEC_ELT (targs, index) == NULL_TREE) + break; + } } - if (!substed) - substed = tsubst_template_arg (arg, full_targs, complain, - NULL_TREE); - if (!uses_template_parms (substed)) - arg = convert_template_argument (parm, substed, full_targs, - complain, i, NULL_TREE); + if (!used_tparms) + { + /* All template parameters within this default argument are + deduced, so we can use it. */ + arg = tsubst_template_arg (arg, full_targs, complain, + NULL_TREE); + arg = convert_template_argument (parm, arg, full_targs, + complain, i, NULL_TREE); + } else if (saw_undeduced == 1) arg = NULL_TREE; else if (!any_dependent_targs) diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype6.C b/gcc/testsuite/g++.dg/cpp1z/nontype6.C new file mode 100644 index 00000000000..06cd234cc61 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/nontype6.C @@ -0,0 +1,24 @@ +// PR c++/101463 +// { dg-do compile { target c++17 } } + +int a; + +int& v = a; + +template<const int& = v> +void f(int) { } + +template<class T, int& = v> +void g(T) { } + +template<class T> +int& vt = a; + +template<class T, int& = vt<T>> +void h(T) { } + +int main() { + f(0); + g(0); + h(0); +} diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype6a.C b/gcc/testsuite/g++.dg/cpp1z/nontype6a.C new file mode 100644 index 00000000000..8bc40a0505c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/nontype6a.C @@ -0,0 +1,25 @@ +// PR c++/101463 +// A version of nontype6.C where v and vt are constexpr. +// { dg-do compile { target c++17 } } + +int a; + +constexpr int& v = a; + +template<const int& = v> +void f(int) { } + +template<class T, const int& = v> +void g(T) { } + +template<class T> +constexpr int& vt = a; + +template<class T, const int& = vt<T>> +void h(T) { } + +int main() { + f(0); + g(0); + h(0); +}