re PR c++/23055 (overload resolution does not find templated function (zero -> pointer))
authorJason Merrill <jason@redhat.com>
Thu, 11 Apr 2013 13:17:54 +0000 (09:17 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 11 Apr 2013 13:17:54 +0000 (09:17 -0400)
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
gcc/cp/pt.c
gcc/testsuite/g++.dg/template/non-deducible1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/nontype25.C

index 01fc3ef..f1cf2ce 100644 (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
index 1d429fe..5bb0cc0 100644 (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)
     {
diff --git a/gcc/testsuite/g++.dg/template/non-deducible1.C b/gcc/testsuite/g++.dg/template/non-deducible1.C
new file mode 100644 (file)
index 0000000..4213524
--- /dev/null
@@ -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);
index bcdcce5..f399408 100644 (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;