c++: default template arg, partial ordering [PR105481]

The default argument code in type_unification_real was assuming that all
targs we've deduced by that point are non-dependent, but that's not the case
for partial ordering.

	PR c++/105481

gcc/cp/ChangeLog:

	* pt.cc (type_unification_real): Adjust for partial ordering.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/fntmpdefarg-partial1.C: New test.
This commit is contained in:
Jason Merrill 2023-03-23 18:20:52 -04:00
parent e8fec6998b
commit 4e2cdb1ddb
2 changed files with 22 additions and 4 deletions

View file

@ -23304,14 +23304,24 @@ type_unification_real (tree tparms,
return unify_parameter_deduction_failure (explain_p, tparm);
}
/* During partial ordering, we deduce dependent template args. */
bool any_dependent_targs = false;
/* Now substitute into the default template arguments. */
for (i = 0; i < ntparms; i++)
{
tree targ = TREE_VEC_ELT (targs, i);
tree tparm = TREE_VEC_ELT (tparms, i);
if (targ || tparm == error_mark_node)
if (targ)
{
if (!any_dependent_targs && dependent_template_arg_p (targ))
any_dependent_targs = true;
continue;
}
if (tparm == error_mark_node)
continue;
tree parm = TREE_VALUE (tparm);
tree arg = TREE_PURPOSE (tparm);
reopen_deferring_access_checks (*checks);
@ -23347,9 +23357,9 @@ type_unification_real (tree tparms,
do this substitution without processing_template_decl. This
is important if the default argument contains something that
might be instantiation-dependent like access (87480). */
processing_template_decl_sentinel s;
processing_template_decl_sentinel s (!any_dependent_targs);
tree substed = NULL_TREE;
if (saw_undeduced == 1)
if (saw_undeduced == 1 && !any_dependent_targs)
{
/* First instatiate in template context, in case we still
depend on undeduced template parameters. */
@ -23372,7 +23382,7 @@ type_unification_real (tree tparms,
complain, i, NULL_TREE);
else if (saw_undeduced == 1)
arg = NULL_TREE;
else
else if (!any_dependent_targs)
arg = error_mark_node;
}

View file

@ -0,0 +1,8 @@
// PR c++/105481
// { dg-do compile { target c++11 } }
template<unsigned> struct uint;
template<unsigned N> uint<N> f(const uint<N> &);
template<unsigned N, typename T, typename = uint<N>> uint<N> f(T);
using X = uint<1>;
X (*fp)(X const &) = f;