> > 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.
Makes sense, like so? Bootstrapped and regtested on x86_64-pc-linux-gnu. PR c++/101463 gcc/cp/ChangeLog: * pt.cc (type_unification_real): Directly look for undeduced parameters in the default argument instead of substituting and asking if it's dependent. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/nontype6.C: New test. * g++.dg/cpp1z/nontype6a.C: New test. --- 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(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/nontype6.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/nontype6a.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 8725a5eeb3f..ad0f73c2f43 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -23607,28 +23607,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 used 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); +} -- 2.46.0.164.g477ce5ccd6