diff options
author | Patrick Palka <ppalka@redhat.com> | 2024-08-20 08:34:36 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2024-08-20 08:34:36 -0400 |
commit | 5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931 (patch) | |
tree | fb41f19ae76754c19116845f1f770419ee283fdb | |
parent | 20a5b4824993ae1c99f3b965c5e07bbd2c64b2ce (diff) | |
download | gcc-5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931.zip gcc-5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931.tar.gz gcc-5348e3cb9bc99d2ee4d7438b8eca5c92fff5b931.tar.bz2 |
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 <jason@redhat.com>
-rw-r--r-- | gcc/cp/pt.cc | 41 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/nontype6.C | 24 | ||||
-rw-r--r-- | 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 ea660a5..bc3ad5e 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 0000000..06cd234 --- /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 0000000..8bc40a0 --- /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); +} |