summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/pt.c134
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic118.C3
-rw-r--r--gcc/testsuite/g++.dg/template/dr1391-1.C17
-rw-r--r--gcc/testsuite/g++.dg/template/dr1391-2.C22
-rw-r--r--gcc/testsuite/g++.dg/template/dr1391-3.C13
6 files changed, 150 insertions, 43 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f5a31fde12e..957dc1deed5 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 78714745452..2cd36c9c9ff 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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. */
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic118.C b/gcc/testsuite/g++.dg/cpp0x/variadic118.C
index ee742ebb946..705e4e602dd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic118.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic118.C
@@ -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
index 00000000000..0b99f5d4a91
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dr1391-1.C
@@ -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
index 00000000000..1af71f0d333
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dr1391-2.C
@@ -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
index 00000000000..0f5879704c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dr1391-3.C
@@ -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
+}