DR 1391
authorJason Merrill <jason@redhat.com>
Mon, 18 May 2015 17:14:11 +0000 (13:14 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 18 May 2015 17:14:11 +0000 (13:14 -0400)
DR 1391
* pt.c (type_unification_real): Check convertibility here.
(unify_one_argument): Not here.

From-SVN: r223301

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/variadic118.C
gcc/testsuite/g++.dg/template/dr1391-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/dr1391-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/dr1391-3.C [new file with mode: 0644]

index f5a31fde12e3177cbffc0e1b6d3ea5fea5d9c913..957dc1deed50392f39598ae92b8839c6e6415320 100644 (file)
@@ -1,5 +1,9 @@
 2015-05-18  Jason Merrill  <jason@redhat.com>
 
+       DR 1391
+       * pt.c (type_unification_real): Check convertibility here.
+       (unify_one_argument): Not here.
+
        * tree.c (strip_typedefs_expr) [TRAIT_EXPR]: Fix typo.
        (strip_typedefs) [DECLTYPE_TYPE]: Fix typedef of decltype.
        [TREE_LIST]: Fix no-change case.
index 78714745452c079f46db03e11e6dbad382aabd60..2cd36c9c9fff6e96f0a917b25d43e12ea3cb3a4b 100644 (file)
@@ -16678,7 +16678,7 @@ uses_deducible_template_parms (tree type)
 
 static int
 unify_one_argument (tree tparms, tree targs, tree parm, tree arg,
-                   int subr, unification_kind_t strict, int flags,
+                   int subr, unification_kind_t strict,
                    bool explain_p)
 {
   tree arg_expr = NULL_TREE;
@@ -16695,16 +16695,10 @@ unify_one_argument (tree tparms, tree targs, tree parm, tree arg,
      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.  */
+  if (strict != DEDUCE_EXACT
+      && TYPE_P (parm) && !uses_deducible_template_parms (parm))
+    /* For function parameters with no deducible template parameters,
+       just return.  We'll check non-dependent conversions later.  */
     return unify_success (explain_p);
 
   switch (strict)
@@ -16843,7 +16837,7 @@ type_unification_real (tree tparms,
       ++ia;
 
       if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
-                             flags, explain_p))
+                             explain_p))
        return 1;
     }
 
@@ -16925,8 +16919,11 @@ type_unification_real (tree tparms,
             this parameter can be deduced.  */
          if (TREE_CODE (tparm) == PARM_DECL
              && uses_template_parms (TREE_TYPE (tparm))
-             && !saw_undeduced++)
-           goto again;
+             && saw_undeduced < 2)
+           {
+             saw_undeduced = 1;
+             continue;
+           }
 
          /* Core issue #226 (C++0x) [temp.deduct]:
 
@@ -16937,32 +16934,9 @@ type_unification_real (tree tparms,
             be NULL_TREE or ERROR_MARK_NODE, so we do not need
             to explicitly check cxx_dialect here.  */
          if (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)))
-           {
-             tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
-             tree arg = TREE_PURPOSE (TREE_VEC_ELT (tparms, i));
-             reopen_deferring_access_checks (*checks);
-             location_t save_loc = input_location;
-             if (DECL_P (parm))
-               input_location = DECL_SOURCE_LOCATION (parm);
-             arg = tsubst_template_arg (arg, targs, complain, NULL_TREE);
-             arg = convert_template_argument (parm, arg, targs, complain,
-                                              i, NULL_TREE);
-             input_location = save_loc;
-             *checks = get_deferred_access_checks ();
-             pop_deferring_access_checks ();
-             if (arg == error_mark_node)
-               return 1;
-             else
-               {
-                 TREE_VEC_ELT (targs, i) = arg;
-                 /* The position of the first default template argument,
-                    is also the number of non-defaulted arguments in TARGS.
-                    Record that.  */
-                 if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
-                   SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, i);
-                 continue;
-               }
-           }
+           /* OK, there is a default argument.  Wait until after the
+              conversion check to do substitution.  */
+           continue;
 
          /* If the type parameter is a parameter pack, then it will
             be deduced to an empty parameter pack.  */
@@ -16987,6 +16961,84 @@ type_unification_real (tree tparms,
 
          return unify_parameter_deduction_failure (explain_p, tparm);
        }
+
+      /* DR 1391: All parameters have args, now check non-dependent parms for
+        convertibility.  */
+      if (saw_undeduced < 2)
+       for (ia = 0, parms = xparms, args = xargs, nargs = xnargs;
+            parms && parms != void_list_node && ia < nargs; )
+         {
+           parm = TREE_VALUE (parms);
+
+           if (TREE_CODE (parm) == TYPE_PACK_EXPANSION
+               && (!TREE_CHAIN (parms)
+                   || TREE_CHAIN (parms) == void_list_node))
+             /* For a function parameter pack that occurs at the end of the
+                parameter-declaration-list, the type A of each remaining
+                argument of the call is compared with the type P of the
+                declarator-id of the function parameter pack.  */
+             break;
+
+           parms = TREE_CHAIN (parms);
+
+           if (TREE_CODE (parm) == TYPE_PACK_EXPANSION)
+             /* For a function parameter pack that does not occur at the
+                end of the parameter-declaration-list, the type of the
+                parameter pack is a non-deduced context.  */
+             continue;
+
+           arg = args[ia];
+           ++ia;
+
+           if (uses_template_parms (parm))
+             continue;
+           if (check_non_deducible_conversion (parm, arg, strict, flags,
+                                               explain_p))
+             return 1;
+         }
+
+      /* Now substitute into the default template arguments.  */
+      for (i = 0; i < ntparms; i++)
+       {
+         tree targ = TREE_VEC_ELT (targs, i);
+         tree tparm = TREE_VEC_ELT (tparms, i);
+
+         if (targ || tparm == error_mark_node)
+           continue;
+         tree parm = TREE_VALUE (tparm);
+
+         if (TREE_CODE (parm) == PARM_DECL
+             && uses_template_parms (TREE_TYPE (parm))
+             && saw_undeduced < 2)
+           continue;
+
+         tree arg = TREE_PURPOSE (tparm);
+         reopen_deferring_access_checks (*checks);
+         location_t save_loc = input_location;
+         if (DECL_P (parm))
+           input_location = DECL_SOURCE_LOCATION (parm);
+         arg = tsubst_template_arg (arg, targs, complain, NULL_TREE);
+         arg = convert_template_argument (parm, arg, targs, complain,
+                                          i, NULL_TREE);
+         input_location = save_loc;
+         *checks = get_deferred_access_checks ();
+         pop_deferring_access_checks ();
+         if (arg == error_mark_node)
+           return 1;
+         else
+           {
+             TREE_VEC_ELT (targs, i) = arg;
+             /* The position of the first default template argument,
+                is also the number of non-defaulted arguments in TARGS.
+                Record that.  */
+             if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
+               SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, i);
+             continue;
+           }
+       }
+
+      if (saw_undeduced++ == 1)
+       goto again;
     }
 #ifdef ENABLE_CHECKING
   if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
@@ -17601,7 +17653,7 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
 
       /* Unify the pattern with the current argument.  */
       if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
-                             LOOKUP_IMPLICIT, explain_p))
+                             explain_p))
        return 1;
 
       /* For each parameter pack, collect the deduced value.  */
index ee742ebb9463d3028b9119e3b9e036acbd1446f4..705e4e602dd4caeb15cbb2437298ba8bb40de77c 100644 (file)
@@ -1,8 +1,7 @@
-// This should fail deduction, before it produces a candidate.
 // { dg-do compile { target c++11 } }
 
 template <class... T>
-void f(T... ts);               // { dg-message "deduction" }
+void f(T... ts);
 
 struct B { };
 int main()
diff --git a/gcc/testsuite/g++.dg/template/dr1391-1.C b/gcc/testsuite/g++.dg/template/dr1391-1.C
new file mode 100644 (file)
index 0000000..0b99f5d
--- /dev/null
@@ -0,0 +1,17 @@
+// DR 1391
+
+template<class T> struct A {
+  typename T::N n;
+};
+template<class T> struct B { };
+
+template<class T, class T2>
+void foo(const A<T>& r); // #1
+template<class T>
+void foo(const B<T>& r); // #2
+
+void baz() {
+  B<char> b;
+  foo(b); // OK
+  foo<char>(b); // error
+}
diff --git a/gcc/testsuite/g++.dg/template/dr1391-2.C b/gcc/testsuite/g++.dg/template/dr1391-2.C
new file mode 100644 (file)
index 0000000..1af71f0
--- /dev/null
@@ -0,0 +1,22 @@
+// DR 1391
+// { dg-do compile { target c++11 } }
+
+template<class T>
+struct A {
+  typename T::N n;
+};
+
+template<class T>
+struct B { };
+
+template <class T, class... U>
+typename A<T>::value_t bar(int, T, U...);
+
+template <class T>
+T bar(T, T);
+
+void baz()
+{
+  B<char> b;
+  bar(b, b);
+}
diff --git a/gcc/testsuite/g++.dg/template/dr1391-3.C b/gcc/testsuite/g++.dg/template/dr1391-3.C
new file mode 100644 (file)
index 0000000..0f58797
--- /dev/null
@@ -0,0 +1,13 @@
+// DR 1391
+
+template <class T> struct Z {
+  typedef typename T::x xx;
+};
+template <class T> typename Z<T>::xx f(void *, T);
+template <class T> void f(int, T);
+struct A {} a;
+int main() {
+  f(1, a); // If the implementation rules out the first overload
+  // because of the invalid conversion from int to void*,
+  // the error instantiating Z<A> will be avoided
+}