From 3c75aaa3d884ef2cb1dfed57bb3c2a392ece89d5 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 21 Dec 2016 14:38:50 -0500 Subject: [PATCH] PR c++/42329 - deducing base template for template template arg * pt.c (unify_bound_ttp_args): Split out from unify. (try_class_unification): Handle BOUND_TEMPLATE_TEMPLATE_PARM. (unify): Check for type/non-type mismatch early. [BOUND_TEMPLATE_TEMPLATE_PARM]: Try get_template_base. From-SVN: r243870 --- gcc/cp/ChangeLog | 6 + gcc/cp/pt.c | 171 +++++++++++++-------------- gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C | 2 +- gcc/testsuite/g++.dg/cpp0x/variadic-ttp6.C | 10 ++ gcc/testsuite/g++.dg/template/ttp-derived1.C | 12 ++ gcc/testsuite/g++.dg/template/ttp-derived2.C | 16 +++ 6 files changed, 124 insertions(+), 93 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-ttp6.C create mode 100644 gcc/testsuite/g++.dg/template/ttp-derived1.C create mode 100644 gcc/testsuite/g++.dg/template/ttp-derived2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 05d6dba..ffda8e1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2016-12-21 Jason Merrill + PR c++/42329 + * pt.c (unify_bound_ttp_args): Split out from unify. + (try_class_unification): Handle BOUND_TEMPLATE_TEMPLATE_PARM. + (unify): Check for type/non-type mismatch early. + [BOUND_TEMPLATE_TEMPLATE_PARM]: Try get_template_base. + * pt.c (coerce_template_parms): Consider variadic_args_p before complaining about too many template arguments. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f839c53..6abb639 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6863,6 +6863,27 @@ coerce_template_template_parm (tree parm, return 1; } +/* Subroutine of unify for the case when PARM is a + BOUND_TEMPLATE_TEMPLATE_PARM. */ + +static int +unify_bound_ttp_args (tree tparms, tree targs, tree parm, tree arg, + bool explain_p) +{ + tree parmvec = TYPE_TI_ARGS (parm); + tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg)); + + /* The template template parm might be variadic and the argument + not, so flatten both argument lists. */ + parmvec = expand_template_argument_pack (parmvec); + argvec = expand_template_argument_pack (argvec); + + if (unify (tparms, targs, parmvec, argvec, + UNIFY_ALLOW_NONE, explain_p)) + return 1; + + return 0; +} /* Return 1 if PARM_PARMS and ARG_PARMS matches using rule for template template parameters. Both PARM_PARMS and ARG_PARMS are @@ -19391,9 +19412,12 @@ try_class_unification (tree tparms, tree targs, tree parm, tree arg, { tree copy_of_targs; - if (!CLASSTYPE_TEMPLATE_INFO (arg) - || (most_general_template (CLASSTYPE_TI_TEMPLATE (arg)) - != most_general_template (CLASSTYPE_TI_TEMPLATE (parm)))) + if (!CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (arg)) + return NULL_TREE; + else if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM) + /* Matches anything. */; + else if (most_general_template (CLASSTYPE_TI_TEMPLATE (arg)) + != most_general_template (CLASSTYPE_TI_TEMPLATE (parm))) return NULL_TREE; /* We need to make a new template argument vector for the call to @@ -19428,6 +19452,13 @@ try_class_unification (tree tparms, tree targs, tree parm, tree arg, would reject the possibility I=1. */ copy_of_targs = make_tree_vec (TREE_VEC_LENGTH (targs)); + if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM) + { + if (unify_bound_ttp_args (tparms, copy_of_targs, parm, arg, explain_p)) + return NULL_TREE; + return arg; + } + /* If unification failed, we're done. */ if (unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm), CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE, explain_p)) @@ -19832,6 +19863,25 @@ unify_array_domain (tree tparms, tree targs, UNIFY_ALLOW_INTEGER, explain_p); } +/* Returns whether T, a P or A in unify, is a type, template or expression. */ + +enum pa_kind_t { pa_type, pa_tmpl, pa_expr }; + +static pa_kind_t +pa_kind (tree t) +{ + if (PACK_EXPANSION_P (t)) + t = PACK_EXPANSION_PATTERN (t); + if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM + || TREE_CODE (t) == UNBOUND_CLASS_TEMPLATE + || DECL_TYPE_TEMPLATE_P (t)) + return pa_tmpl; + else if (TYPE_P (t)) + return pa_type; + else + return pa_expr; +} + /* Deduce the value of template parameters. TPARMS is the (innermost) set of template parameters to a template. TARGS is the bindings for those template parameters, as determined thus far; TARGS may @@ -19985,6 +20035,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, return unify_success (explain_p); } + /* If parm and arg aren't the same kind of thing (template, type, or + expression), fail early. */ + if (pa_kind (parm) != pa_kind (arg)) + return unify_invalid (explain_p); + /* Immediately reject some pairs that won't unify because of cv-qualification mismatches. */ if (TREE_CODE (arg) == TREE_CODE (parm) @@ -20053,100 +20108,32 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM) { + if (strict_in & UNIFY_ALLOW_DERIVED) + { + /* First try to match ARG directly. */ + tree t = try_class_unification (tparms, targs, parm, arg, + explain_p); + if (!t) + { + /* Otherwise, look for a suitable base of ARG, as below. */ + enum template_base_result r; + r = get_template_base (tparms, targs, parm, arg, + explain_p, &t); + if (!t) + return unify_no_common_base (explain_p, r, parm, arg); + arg = t; + } + } /* ARG must be constructed from a template class or a template template parameter. */ - if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM - && !CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (arg)) + else if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM + && !CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (arg)) return unify_template_deduction_failure (explain_p, parm, arg); - { - tree parmvec = TYPE_TI_ARGS (parm); - tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg)); - tree full_argvec = add_to_template_args (targs, argvec); - tree parm_parms - = DECL_INNERMOST_TEMPLATE_PARMS - (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm)); - int i, len; - int parm_variadic_p = 0; - - /* The resolution to DR150 makes clear that default - arguments for an N-argument may not be used to bind T - to a template template parameter with fewer than N - parameters. It is not safe to permit the binding of - default arguments as an extension, as that may change - the meaning of a conforming program. Consider: - - struct Dense { static const unsigned int dim = 1; }; - - template