Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk?
-- >8 -- Here more_specialized_partial_spec considers the two partial specializations to be unordered ultimately because unify for identical parm=arg=A<T>::C returns failure due to C being dependent. This patch fixes this by relaxing unify's early-exit identity test to also accept dependent decls; we can't deduce anything further from them anyway. In passing this patch removes the CONST_DECL case of unify: we should never see the CONST_DECL version of a template parameter here, and for other CONST_DECLs (such as enumerators) it seems we can rely on them already having been folded to their DECL_INITIAL. PR c++/108347 gcc/cp/ChangeLog: * pt.cc (unify): Return unify_success for identical dependent DECL_P 'arg' and 'parm'. <case CONST_DECL>: Remove handling. gcc/testsuite/ChangeLog: * g++.dg/template/ttp41.C: New test. --- gcc/cp/pt.cc | 10 ++-------- gcc/testsuite/g++.dg/template/ttp41.C | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/ttp41.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 838179d5fe3..c311a6b88f5 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -24568,7 +24568,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, even if ARG == PARM, since we won't record unifications for the template parameters. We might need them if we're trying to figure out which of two things is more specialized. */ - if (arg == parm && !uses_template_parms (parm)) + if (arg == parm + && (DECL_P (parm) || !uses_template_parms (parm))) return unify_success (explain_p); /* Handle init lists early, so the rest of the function can assume @@ -25286,13 +25287,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg), strict, explain_p); - case CONST_DECL: - if (DECL_TEMPLATE_PARM_P (parm)) - return unify (tparms, targs, DECL_INITIAL (parm), arg, strict, explain_p); - if (arg != scalar_constant_value (parm)) - return unify_template_argument_mismatch (explain_p, parm, arg); - return unify_success (explain_p); - case FIELD_DECL: case TEMPLATE_DECL: /* Matched cases are handled by the ARG == PARM test above. */ diff --git a/gcc/testsuite/g++.dg/template/ttp41.C b/gcc/testsuite/g++.dg/template/ttp41.C new file mode 100644 index 00000000000..c81e5dd2405 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/ttp41.C @@ -0,0 +1,17 @@ +// PR c++/108347 + +template<class T> +struct A { + template<class U> struct C { }; + + template<template<class> class TT, class U> + struct B; + + template<class U> + struct B<C, U*>; + + template<class U> + struct B<C, const U*> { }; +}; + +A<int>::B<A<int>::C, const int*> b; -- 2.42.0.158.g94e83dcf5b