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
This commit is contained in:
Jason Merrill 2013-04-11 09:17:54 -04:00 committed by Jason Merrill
parent 752b81d9c7
commit a26780a30a
4 changed files with 158 additions and 2 deletions

View File

@ -1,3 +1,11 @@
2013-04-11 Jason Merrill <jason@redhat.com>
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 <paolo.carlini@oracle.com>
PR c++/56913

View File

@ -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 <PARM> - 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<T>
TT<i>
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 <T> (where template-name refers to a class template)
template-name <i> (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)
{

View File

@ -0,0 +1,8 @@
// PR c++/23055
template <class> struct S { typedef int type; };
template <class T>
int foo(T, typename S<T>::type * ret);
int j = foo(1, 0);

View File

@ -7,7 +7,7 @@ template<const A* a> class C {};
template<const B* b> class D {};
template<B* b> class E {};
template<const B* b> void f(D<b> &, C<static_cast<const A*>(b)> &) {} // { dg-error "" "" { target c++98 } }
template<const B* b> void f(D<b> &, C<static_cast<const A*>(b)> &) {} // { dg-error "" "" }
template<const B* b> void g(D<b> &, E<const_cast<B*>(b)> &) {} // { dg-error "" "" { target c++98 } }
B b;