summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2017-06-26 18:49:18 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2017-06-26 18:49:18 +0000
commitf404873464c6d87b7d0cfc433bacd8a1c15b16c6 (patch)
tree01a0fa1caf9c2a4b4451bb0286f009e35ae389a0
parentc8efa6c97e5fcca72caed9e85ffd6cf48755842e (diff)
downloadgcc-f404873464c6d87b7d0cfc433bacd8a1c15b16c6.tar.gz
PR c++/81215 - deduction failure with variadic TTP.
* pt.c (unify_bound_ttp_args): Restore old logic for C++14 and down. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@249664 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/pt.c66
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ttp7.C16
3 files changed, 75 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8bc268c1dcd..c067d23eb8a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2017-06-26 Jason Merrill <jason@redhat.com>
+
+ PR c++/81215 - deduction failure with variadic TTP.
+ * pt.c (unify_bound_ttp_args): Restore old logic for C++14 and down.
+
2017-06-26 Martin Sebor <msebor@redhat.com>
PR c++/81169
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 392fba07714..43f9ca8b39e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7170,26 +7170,68 @@ unify_bound_ttp_args (tree tparms, tree targs, tree parm, tree& arg,
parmvec = expand_template_argument_pack (parmvec);
argvec = expand_template_argument_pack (argvec);
- tree nparmvec = parmvec;
if (flag_new_ttp)
{
/* In keeping with P0522R0, adjust P's template arguments
to apply to A's template; then flatten it again. */
+ tree nparmvec = parmvec;
nparmvec = coerce_ttp_args_for_tta (arg, parmvec, tf_none);
nparmvec = expand_template_argument_pack (nparmvec);
- }
- if (unify (tparms, targs, nparmvec, argvec,
- UNIFY_ALLOW_NONE, explain_p))
- return 1;
+ if (unify (tparms, targs, nparmvec, argvec,
+ UNIFY_ALLOW_NONE, explain_p))
+ return 1;
- /* If the P0522 adjustment eliminated a pack expansion, deduce
- empty packs. */
- if (flag_new_ttp
- && TREE_VEC_LENGTH (nparmvec) < TREE_VEC_LENGTH (parmvec)
- && unify_pack_expansion (tparms, targs, parmvec, argvec,
- DEDUCE_EXACT, /*sub*/true, explain_p))
- return 1;
+ /* If the P0522 adjustment eliminated a pack expansion, deduce
+ empty packs. */
+ if (flag_new_ttp
+ && TREE_VEC_LENGTH (nparmvec) < TREE_VEC_LENGTH (parmvec)
+ && unify_pack_expansion (tparms, targs, parmvec, argvec,
+ DEDUCE_EXACT, /*sub*/true, explain_p))
+ return 1;
+ }
+ else
+ {
+ /* Deduce arguments T, i from TT<T> or TT<i>.
+ We check each element of PARMVEC and ARGVEC individually
+ rather than the whole TREE_VEC since they can have
+ different number of elements, which is allowed under N2555. */
+
+ int len = TREE_VEC_LENGTH (parmvec);
+
+ /* Check if the parameters end in a pack, making them
+ variadic. */
+ int parm_variadic_p = 0;
+ if (len > 0
+ && PACK_EXPANSION_P (TREE_VEC_ELT (parmvec, len - 1)))
+ parm_variadic_p = 1;
+
+ for (int i = 0; i < len - parm_variadic_p; ++i)
+ /* If the template argument list of P contains a pack
+ expansion that is not the last template argument, the
+ entire template argument list is a non-deduced
+ context. */
+ if (PACK_EXPANSION_P (TREE_VEC_ELT (parmvec, i)))
+ return unify_success (explain_p);
+
+ if (TREE_VEC_LENGTH (argvec) < len - parm_variadic_p)
+ return unify_too_few_arguments (explain_p,
+ TREE_VEC_LENGTH (argvec), len);
+
+ for (int i = 0; i < len - parm_variadic_p; ++i)
+ if (unify (tparms, targs,
+ TREE_VEC_ELT (parmvec, i),
+ TREE_VEC_ELT (argvec, i),
+ UNIFY_ALLOW_NONE, explain_p))
+ return 1;
+
+ if (parm_variadic_p
+ && unify_pack_expansion (tparms, targs,
+ parmvec, argvec,
+ DEDUCE_EXACT,
+ /*subr=*/true, explain_p))
+ return 1;
+ }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ttp7.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp7.C
new file mode 100644
index 00000000000..0dbe904601d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp7.C
@@ -0,0 +1,16 @@
+// PR c++/81215
+// { dg-do compile { target c++11 } }
+
+template<typename U> struct X { };
+template<typename T, typename U = void> struct set { };
+
+template <typename V, template <typename...> class C>
+void bar (const X<C<V>>&)
+{
+}
+
+void
+foo (X<set<int>>& x)
+{
+ bar (x);
+}