diff options
author | Jason Merrill <jason@redhat.com> | 2016-12-21 14:38:50 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-12-21 14:38:50 -0500 |
commit | 3c75aaa3d884ef2cb1dfed57bb3c2a392ece89d5 (patch) | |
tree | 5bb7df18e3bd88d163ae4b054766c14df9428cea /gcc/cp | |
parent | 57a6add274e98def9fe937eea126c56a71e65c28 (diff) | |
download | gcc-3c75aaa3d884ef2cb1dfed57bb3c2a392ece89d5.zip gcc-3c75aaa3d884ef2cb1dfed57bb3c2a392ece89d5.tar.gz gcc-3c75aaa3d884ef2cb1dfed57bb3c2a392ece89d5.tar.bz2 |
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
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/pt.c | 171 |
2 files changed, 85 insertions, 92 deletions
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 <jason@redhat.com> + 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 <template <typename> class View, - typename Block> - void operator+(float, View<Block> const&); - - template <typename Block, - unsigned int Dim = Block::dim> - struct Lvalue_proxy { operator float() const; }; - - void - test_1d (void) { - Lvalue_proxy<Dense> p; - float b; - b + p; - } - Here, if Lvalue_proxy is permitted to bind to View, then - the global operator+ will be used; if they are not, the - Lvalue_proxy will be converted to float. */ - if (coerce_template_parms (parm_parms, - full_argvec, - TYPE_TI_TEMPLATE (parm), - complain, - /*require_all_args=*/true, - /*use_default_args=*/false) - == error_mark_node) - return 1; - - /* Deduce arguments T, i from TT<T> or TT<i>. - We check each element of PARMVEC and ARGVEC individually - rather than the whole TREE_VEC since they can have - different number of elements. */ - - parmvec = expand_template_argument_pack (parmvec); - argvec = expand_template_argument_pack (argvec); - - len = TREE_VEC_LENGTH (parmvec); - - /* Check if the parameters end in a pack, making them - variadic. */ - if (len > 0 - && PACK_EXPANSION_P (TREE_VEC_ELT (parmvec, len - 1))) - parm_variadic_p = 1; - - for (i = 0; i < len - parm_variadic_p; ++i) - /* If the template argument list of P contains a pack - expansion that is not the last template argument, the - entire template argument list is a non-deduced - context. */ - if (PACK_EXPANSION_P (TREE_VEC_ELT (parmvec, i))) - return unify_success (explain_p); - - if (TREE_VEC_LENGTH (argvec) < len - parm_variadic_p) - return unify_too_few_arguments (explain_p, - TREE_VEC_LENGTH (argvec), len); - - for (i = 0; i < len - parm_variadic_p; ++i) - { - RECUR_AND_CHECK_FAILURE (tparms, targs, - TREE_VEC_ELT (parmvec, i), - TREE_VEC_ELT (argvec, i), - UNIFY_ALLOW_NONE, explain_p); - } + /* Deduce arguments T, i from TT<T> or TT<i>. */ + if (unify_bound_ttp_args (tparms, targs, parm, arg, explain_p)) + return 1; - if (parm_variadic_p - && unify_pack_expansion (tparms, targs, - parmvec, argvec, - DEDUCE_EXACT, - /*subr=*/true, explain_p)) - return 1; - } arg = TYPE_TI_TEMPLATE (arg); /* Fall through to deduce template name. */ |