From a26780a30a985778bcd772a6bf7bc217f7cc4b00 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 11 Apr 2013 09:17:54 -0400 Subject: [PATCH] re PR c++/23055 (overload resolution does not find templated function (zero -> pointer)) PR c++/23055 * pt.c (uses_deducible_template_parms): New. (deducible_array_bound, deducible_expression): New. (deducible_template_args): New. (unify_one_argument): Call uses_deducible_template_parms. From-SVN: r197790 --- gcc/cp/ChangeLog | 8 + gcc/cp/pt.c | 142 +++++++++++++++++- .../g++.dg/template/non-deducible1.C | 8 + gcc/testsuite/g++.dg/template/nontype25.C | 2 +- 4 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/non-deducible1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 01fc3efc5be..f1cf2ce40c6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2013-04-11 Jason Merrill + + PR c++/23055 + * pt.c (uses_deducible_template_parms): New. + (deducible_array_bound, deducible_expression): New. + (deducible_template_args): New. + (unify_one_argument): Call uses_deducible_template_parms. + 2013-04-11 Paolo Carlini PR c++/56913 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1d429fe0f1b..5bb0cc03b9f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -15357,6 +15357,135 @@ check_non_deducible_conversion (tree parm, tree arg, int strict, return unify_arg_conversion (explain_p, parm, type, arg); } +static bool uses_deducible_template_parms (tree type); + +/* Returns true iff the expression EXPR is one from which a template + argument can be deduced. In other words, if it's an undecorated + use of a template non-type parameter. */ + +static bool +deducible_expression (tree expr) +{ + return (TREE_CODE (expr) == TEMPLATE_PARM_INDEX); +} + +/* Returns true iff the array domain DOMAIN uses a template parameter in a + deducible way; that is, if it has a max value of - 1. */ + +static bool +deducible_array_bound (tree domain) +{ + if (domain == NULL_TREE) + return false; + + tree max = TYPE_MAX_VALUE (domain); + if (TREE_CODE (max) != MINUS_EXPR) + return false; + + return deducible_expression (TREE_OPERAND (max, 0)); +} + +/* Returns true iff the template arguments ARGS use a template parameter + in a deducible way. */ + +static bool +deducible_template_args (tree args) +{ + for (int i = 0; i < TREE_VEC_LENGTH (args); ++i) + { + bool deducible; + tree elt = TREE_VEC_ELT (args, i); + if (ARGUMENT_PACK_P (elt)) + deducible = deducible_template_args (ARGUMENT_PACK_ARGS (elt)); + else + { + if (PACK_EXPANSION_P (elt)) + elt = PACK_EXPANSION_PATTERN (elt); + if (TREE_CODE (elt) == TEMPLATE_TEMPLATE_PARM) + deducible = true; + else if (TYPE_P (elt)) + deducible = uses_deducible_template_parms (elt); + else + deducible = deducible_expression (elt); + } + if (deducible) + return true; + } + return false; +} + +/* Returns true iff TYPE contains any deducible references to template + parameters, as per 14.8.2.5. */ + +static bool +uses_deducible_template_parms (tree type) +{ + if (PACK_EXPANSION_P (type)) + type = PACK_EXPANSION_PATTERN (type); + + /* T + cv-list T + TT + TT + TT<> */ + if (TREE_CODE (type) == TEMPLATE_TYPE_PARM + || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM) + return true; + + /* T* + T& + T&& */ + if (POINTER_TYPE_P (type)) + return uses_deducible_template_parms (TREE_TYPE (type)); + + /* T[integer-constant ] + type [i] */ + if (TREE_CODE (type) == ARRAY_TYPE) + return (uses_deducible_template_parms (TREE_TYPE (type)) + || deducible_array_bound (TYPE_DOMAIN (type))); + + /* T type ::* + type T::* + T T::* + T (type ::*)() + type (T::*)() + type (type ::*)(T) + type (T::*)(T) + T (type ::*)(T) + T (T::*)() + T (T::*)(T) */ + if (TYPE_PTRMEM_P (type)) + return (uses_deducible_template_parms (TYPE_PTRMEM_CLASS_TYPE (type)) + || (uses_deducible_template_parms + (TYPE_PTRMEM_POINTED_TO_TYPE (type)))); + + /* template-name (where template-name refers to a class template) + template-name (where template-name refers to a class template) */ + if (CLASS_TYPE_P (type) + && CLASSTYPE_TEMPLATE_INFO (type) + && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))) + return deducible_template_args (INNERMOST_TEMPLATE_ARGS + (CLASSTYPE_TI_ARGS (type))); + + /* type (T) + T() + T(T) */ + if (TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE) + { + if (uses_deducible_template_parms (TREE_TYPE (type))) + return true; + tree parm = TYPE_ARG_TYPES (type); + if (TREE_CODE (type) == METHOD_TYPE) + parm = TREE_CHAIN (parm); + for (; parm; parm = TREE_CHAIN (parm)) + if (uses_deducible_template_parms (TREE_VALUE (parm))) + return true; + } + + return false; +} + /* Subroutine of type_unification_real and unify_pack_expansion to handle unification of a single P/A pair. Parameters are as for those functions. */ @@ -15376,10 +15505,21 @@ unify_one_argument (tree tparms, tree targs, tree parm, tree arg, template args from other function args. */ return unify_success (explain_p); - /* FIXME uses_deducible_template_parms */ + /* Implicit conversions (Clause 4) will be performed on a function + argument to convert it to the type of the corresponding function + parameter if the parameter type contains no template-parameters that + participate in template argument deduction. */ if (TYPE_P (parm) && !uses_template_parms (parm)) + /* For function parameters that contain no template-parameters at all, + we have historically checked for convertibility in order to shortcut + consideration of this candidate. */ return check_non_deducible_conversion (parm, arg, strict, flags, explain_p); + else if (strict == DEDUCE_CALL + && TYPE_P (parm) && !uses_deducible_template_parms (parm)) + /* For function parameters with only non-deducible template parameters, + just return. */ + return unify_success (explain_p); switch (strict) { diff --git a/gcc/testsuite/g++.dg/template/non-deducible1.C b/gcc/testsuite/g++.dg/template/non-deducible1.C new file mode 100644 index 00000000000..42135248904 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/non-deducible1.C @@ -0,0 +1,8 @@ +// PR c++/23055 + +template struct S { typedef int type; }; + +template +int foo(T, typename S::type * ret); + +int j = foo(1, 0); diff --git a/gcc/testsuite/g++.dg/template/nontype25.C b/gcc/testsuite/g++.dg/template/nontype25.C index bcdcce5ea9b..f3994083ebe 100644 --- a/gcc/testsuite/g++.dg/template/nontype25.C +++ b/gcc/testsuite/g++.dg/template/nontype25.C @@ -7,7 +7,7 @@ template class C {}; template class D {}; template class E {}; -template void f(D &, C(b)> &) {} // { dg-error "" "" { target c++98 } } +template void f(D &, C(b)> &) {} // { dg-error "" "" } template void g(D &, E(b)> &) {} // { dg-error "" "" { target c++98 } } B b; -- 2.30.2