This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix ICE in unify with variadic templates (PRs c++/32565, c++/33943)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>, Mark Mitchell <mark at codesourcery dot com>
- Cc: Doug Gregor <doug dot gregor at gmail dot com>, gcc-patches at gcc dot gnu dot org
- Date: Mon, 19 Nov 2007 04:10:37 -0500
- Subject: [C++ PATCH] Fix ICE in unify with variadic templates (PRs c++/32565, c++/33943)
- References: <20071115124041.GR5451@devserv.devel.redhat.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Thu, Nov 15, 2007 at 07:40:42AM -0500, Jakub Jelinek wrote:
> As shown on these I believe valid testcases, when unifying
> BOUND_TEMPLATE_TEMPLATE_PARMs, we really can't assume if one {parm,arg}vec
> argument is a parameter pack, the other will be as well. Fixed by using
> expand_template_argument_pack on both vectors so that we unify corresponding
> parameters.
This updated patch also handles PACK_EXPANSION_P if present at the end of
this way expanded parmvec. With this PR33943 no longer ICEs, the errors are
now:
/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/variadic86.C:18: error: cannot expand 'U ...' into a fixed-length argument list
/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/variadic86.C:18: error: ambiguous class template instantiation for 'struct baz<foo<int, short int> >'
/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/variadic86.C:12: error: candidates are: struct baz<T<U ...> >
/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/variadic86.C:16: error: struct baz<T<U, V ...> >
/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/variadic86.C:18: error: aggregate 'baz<foo<int, short int> > b1' has incomplete type and cannot be defined
/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/variadic86.C:19: error: cannot expand 'U ...' into a fixed-length argument list
(though they aren't issued by the unify with BOUND_TEMPLATE_TEMPLATE_PARM
that has been changed, but later on). Now whether the errors are
correct or not I don't know.
2007-11-19 Jakub Jelinek <jakub@redhat.com>
PR c++/32565
PR c++/33943
* pt.c (unify) <case BOUND_TEMPLATE_TEMPLATE_PARM>: Expand both
parmvec and argvec with expand_template_argument_pack. Handle
PACK_EXPANSION_P at the end of parmvec.
* g++.dg/cpp0x/variadic84.C: New test.
* g++.dg/cpp0x/variadic85.C: New test.
* g++.dg/cpp0x/variadic86.C: New test.
--- gcc/cp/pt.c.jj 2007-11-18 20:14:58.000000000 +0100
+++ gcc/cp/pt.c 2007-11-19 09:48:36.000000000 +0100
@@ -12684,7 +12684,8 @@ unify (tree tparms, tree targs, tree par
tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
tree argtmplvec
= DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (arg));
- int i;
+ int i, len;
+ int parm_variadic_p = 0;
/* The resolution to DR150 makes clear that default
arguments for an N-argument may not be used to bind T
@@ -12726,7 +12727,19 @@ unify (tree tparms, tree targs, tree par
rather than the whole TREE_VEC since they can have
different number of elements. */
- for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
+ parmvec = expand_template_argument_pack (parmvec);
+ argvec = expand_template_argument_pack (argvec);
+
+ len = TREE_VEC_LENGTH (parmvec);
+ /* Check if the parameters end in a pack, making them variadic. */
+ if (len > 0
+ && PACK_EXPANSION_P (TREE_VEC_ELT (parmvec, len - 1)))
+ parm_variadic_p = 1;
+
+ if (TREE_VEC_LENGTH (argvec) < len - parm_variadic_p)
+ return 1;
+
+ for (i = 0; i < len - parm_variadic_p; ++i)
{
if (unify (tparms, targs,
TREE_VEC_ELT (parmvec, i),
@@ -12734,6 +12747,14 @@ unify (tree tparms, tree targs, tree par
UNIFY_ALLOW_NONE))
return 1;
}
+
+ if (parm_variadic_p
+ && unify_pack_expansion (tparms, targs,
+ parmvec, argvec,
+ UNIFY_ALLOW_NONE,
+ /*call_args_p=*/false,
+ /*subr=*/false))
+ return 1;
}
arg = TYPE_TI_TEMPLATE (arg);
--- gcc/testsuite/g++.dg/cpp0x/variadic84.C.jj 2007-11-19 08:27:59.000000000 +0100
+++ gcc/testsuite/g++.dg/cpp0x/variadic84.C 2007-11-19 08:27:59.000000000 +0100
@@ -0,0 +1,26 @@
+// PR c++/32565
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+template<typename...> struct A1;
+template<template<int...> class T> struct A1<T<0> > {};
+template<typename...> struct A2;
+template<template<int...> class T> struct A2<T<0, 1> > {};
+template<typename...> struct A3;
+template<template<int, int...> class T> struct A3<T<0, 1> > {};
+template<typename...> struct A4;
+template<template<typename...> class T> struct A4<T<int> > {};
+template<typename...> struct A5;
+template<template<typename...> class T> struct A5<T<int, long> > {};
+template<typename...> struct A6;
+template<template<typename, typename...> class T> struct A6<T<int, long> > {};
+template<int> struct B1 {};
+template<int, int> struct B2 {};
+template<typename> struct B3 {};
+template<typename, typename> struct B4 {};
+A1<B1<0> > a1;
+A2<B2<0, 1> > a2;
+A3<B2<0, 1> > a3;
+A4<B3<int> > a4;
+A5<B4<int, long> > a5;
+A6<B4<int, long> > a6;
--- gcc/testsuite/g++.dg/cpp0x/variadic85.C.jj 2007-11-19 08:27:59.000000000 +0100
+++ gcc/testsuite/g++.dg/cpp0x/variadic85.C 2007-11-19 08:27:59.000000000 +0100
@@ -0,0 +1,10 @@
+// PR c++/32565
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+template<typename...> struct A1;
+template<template<int, int...> class T> struct A1<T<0, 1> > {};
+template<int, int, int...> struct B1 {};
+A1<B1<0, 1> > a1;
+template<int...> struct B2 {};
+A1<B2<0, 1> > a2;
--- gcc/testsuite/g++.dg/cpp0x/variadic86.C.jj 2007-11-19 10:02:14.000000000 +0100
+++ gcc/testsuite/g++.dg/cpp0x/variadic86.C 2007-11-19 10:03:01.000000000 +0100
@@ -0,0 +1,19 @@
+// PR c++/33943
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+template<typename... A> struct foo {};
+
+template<typename A0, typename... A1> struct bar {};
+
+template<typename U> struct baz;
+
+template<template<typename...> class T, typename... U> struct baz< T<U...> >
+{}; // { dg-error "struct baz" }
+
+template<template<typename, typename...> class T, typename U, typename... V>
+struct baz< T<U, V...> >
+{}; // { dg-error "struct baz" }
+
+baz< foo<int, short> > b1; // { dg-error "cannot expand|ambiguous class template instantiation|has incomplete type" }
+baz< bar<int, short> > b2; // { dg-error "cannot expand" }
Jakub