aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDouglas Gregor <doug.gregor@gmail.com>2008-03-26 04:17:57 +0000
committerDoug Gregor <dgregor@gcc.gnu.org>2008-03-26 04:17:57 +0000
commita0a5f30f8e6741d55daca7fb3093df6365425661 (patch)
treef1ef439448a570f47eb3eed0834a900570fcfa64 /gcc
parent22ec849c3b1088a10c46068f3df6e1e9fbc9efd4 (diff)
downloadgcc-a0a5f30f8e6741d55daca7fb3093df6365425661.zip
gcc-a0a5f30f8e6741d55daca7fb3093df6365425661.tar.gz
gcc-a0a5f30f8e6741d55daca7fb3093df6365425661.tar.bz2
pt.c (coerce_template_template_parm): Moved the body of the loop of coerce_template_template_parms here...
2008-03-26 Douglas Gregor <doug.gregor@gmail.com> * pt.c (coerce_template_template_parm): Moved the body of the loop of coerce_template_template_parms here, to make iteration over a template argument pack simpler. Also, allow matching of a template parameter pack in the template template parameter to a template parameter in the template template argument. (coerce_template_template_parms): Deal with variadic template template parameters. Use coerce_template_template_parm. (unify): Make sure we coerce the template template argument's template arguments to the template template parameter's template parameters, not the other way around. 2008-03-26 Douglas Gregor <doug.gregor@gmail.com> * g++.dg/cpp0x/variadic84.C: Update to reflect the change in variadic template template parameter binding semantics. * g++.dg/cpp0x/variadic85.C: Ditto. * g++.dg/cpp0x/variadic88.C: New. * g++.dg/cpp0x/variadic89.C: New. * g++.dg/cpp0x/variadic90.C: New. * g++.dg/cpp0x/variadic-ex14.C: Update to reflect the change in variadic template template parameter binding semantics. * g++.dg/cpp0x/variadic-lambda.C: New. From-SVN: r133543
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/pt.c182
-rw-r--r--gcc/testsuite/ChangeLog12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C79
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic84.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic85.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic88.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic89.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic90.C8
10 files changed, 288 insertions, 66 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5ddc8b5..87e8c05 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+2008-03-26 Douglas Gregor <doug.gregor@gmail.com>
+
+ * pt.c (coerce_template_template_parm): Moved the body of the loop
+ of coerce_template_template_parms here, to make iteration over a
+ template argument pack simpler.
+ Also, allow matching of a template parameter pack in the template
+ template parameter to a template parameter in the template
+ template argument.
+ (coerce_template_template_parms): Deal with variadic template
+ template parameters. Use coerce_template_template_parm.
+ (unify): Make sure we coerce the template template argument's
+ template arguments to the template template parameter's template
+ parameters, not the other way around.
+
2008-03-25 Tom Tromey <tromey@redhat.com>
* Make-lang.in: Remove .o targets.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bc33efc..67d392d 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -4630,6 +4630,77 @@ convert_nontype_argument (tree type, tree expr)
return expr;
}
+/* Subroutine of coerce_template_template_parms, which returns 1 if
+ PARM_PARM and ARG_PARM match using the rule for the template
+ parameters of template template parameters. Both PARM and ARG are
+ template parameters; the rest of the arguments are the same as for
+ coerce_template_template_parms.
+ */
+static int
+coerce_template_template_parm (tree parm,
+ tree arg,
+ tsubst_flags_t complain,
+ tree in_decl,
+ tree outer_args)
+{
+ if (arg == NULL_TREE || arg == error_mark_node
+ || parm == NULL_TREE || parm == error_mark_node)
+ return 0;
+
+ if (TREE_CODE (arg) != TREE_CODE (parm))
+ return 0;
+
+ switch (TREE_CODE (parm))
+ {
+ case TEMPLATE_DECL:
+ /* We encounter instantiations of templates like
+ template <template <template <class> class> class TT>
+ class C; */
+ {
+ tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+ tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+
+ if (!coerce_template_template_parms
+ (parmparm, argparm, complain, in_decl, outer_args))
+ return 0;
+ }
+ /* Fall through. */
+
+ case TYPE_DECL:
+ if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (arg))
+ && !TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
+ /* Argument is a parameter pack but parameter is not. */
+ return 0;
+ break;
+
+ case PARM_DECL:
+ /* The tsubst call is used to handle cases such as
+
+ template <int> class C {};
+ template <class T, template <T> class TT> class D {};
+ D<int, C> d;
+
+ i.e. the parameter list of TT depends on earlier parameters. */
+ if (!dependent_type_p (TREE_TYPE (arg))
+ && !same_type_p
+ (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
+ TREE_TYPE (arg)))
+ return 0;
+
+ if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (arg))
+ && !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
+ /* Argument is a parameter pack but parameter is not. */
+ return 0;
+
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return 1;
+}
+
/* Return 1 if PARM_PARMS and ARG_PARMS matches using rule for
template template parameters. Both PARM_PARMS and ARG_PARMS are
@@ -4652,6 +4723,7 @@ coerce_template_template_parms (tree parm_parms,
{
int nparms, nargs, i;
tree parm, arg;
+ int variadic_p = 0;
gcc_assert (TREE_CODE (parm_parms) == TREE_VEC);
gcc_assert (TREE_CODE (arg_parms) == TREE_VEC);
@@ -4659,10 +4731,37 @@ coerce_template_template_parms (tree parm_parms,
nparms = TREE_VEC_LENGTH (parm_parms);
nargs = TREE_VEC_LENGTH (arg_parms);
- if (nargs != nparms)
+ /* Determine whether we have a parameter pack at the end of the
+ template template parameter's template parameter list. */
+ if (TREE_VEC_ELT (parm_parms, nparms - 1) != error_mark_node)
+ {
+ parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, nparms - 1));
+
+ switch (TREE_CODE (parm))
+ {
+ case TEMPLATE_DECL:
+ case TYPE_DECL:
+ if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
+ variadic_p = 1;
+ break;
+
+ case PARM_DECL:
+ if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
+ variadic_p = 1;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ if (nargs != nparms
+ && !(variadic_p && nargs >= nparms - 1))
return 0;
- for (i = 0; i < nparms; ++i)
+ /* Check all of the template parameters except the parameter pack at
+ the end (if any). */
+ for (i = 0; i < nparms - variadic_p; ++i)
{
if (TREE_VEC_ELT (parm_parms, i) == error_mark_node
|| TREE_VEC_ELT (arg_parms, i) == error_mark_node)
@@ -4671,60 +4770,35 @@ coerce_template_template_parms (tree parm_parms,
parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
- if (arg == NULL_TREE || arg == error_mark_node
- || parm == NULL_TREE || parm == error_mark_node)
+ if (!coerce_template_template_parm (parm, arg, complain, in_decl,
+ outer_args))
return 0;
- if (TREE_CODE (arg) != TREE_CODE (parm))
- return 0;
-
- switch (TREE_CODE (parm))
- {
- case TEMPLATE_DECL:
- /* We encounter instantiations of templates like
- template <template <template <class> class> class TT>
- class C; */
- {
- tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
- tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
-
- if (!coerce_template_template_parms
- (parmparm, argparm, complain, in_decl, outer_args))
- return 0;
- }
- /* Fall through. */
-
- case TYPE_DECL:
- if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm))
- != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (arg)))
- /* One is a parameter pack, the other is not. */
- return 0;
- break;
-
- case PARM_DECL:
- /* The tsubst call is used to handle cases such as
-
- template <int> class C {};
- template <class T, template <T> class TT> class D {};
- D<int, C> d;
+ }
- i.e. the parameter list of TT depends on earlier parameters. */
- if (!dependent_type_p (TREE_TYPE (arg))
- && !same_type_p
- (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
- TREE_TYPE (arg)))
- return 0;
+ if (variadic_p)
+ {
+ /* Check each of the template parameters in the template
+ argument against the template parameter pack at the end of
+ the template template parameter. */
+ if (TREE_VEC_ELT (parm_parms, i) == error_mark_node)
+ return 0;
- if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))
- != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (arg)))
- /* One is a parameter pack, the other is not. */
- return 0;
- break;
+ parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
- default:
- gcc_unreachable ();
- }
+ for (; i < nargs; ++i)
+ {
+ if (TREE_VEC_ELT (arg_parms, i) == error_mark_node)
+ continue;
+
+ arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
+
+ if (!coerce_template_template_parm (parm, arg, complain, in_decl,
+ outer_args))
+ return 0;
+ }
}
+
return 1;
}
@@ -12825,8 +12899,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
{
tree parmvec = TYPE_TI_ARGS (parm);
tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
- tree argtmplvec
- = DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (arg));
+ tree parm_parms
+ = DECL_INNERMOST_TEMPLATE_PARMS
+ (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
int i, len;
int parm_variadic_p = 0;
@@ -12857,7 +12932,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
Here, if Lvalue_proxy is permitted to bind to View, then
the global operator+ will be used; if they are not, the
Lvalue_proxy will be converted to float. */
- if (coerce_template_parms (argtmplvec, parmvec,
+ if (coerce_template_parms (parm_parms,
+ argvec,
TYPE_TI_TEMPLATE (parm),
tf_none,
/*require_all_args=*/true,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b22d21b..e3499ad 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,15 @@
+2008-03-26 Douglas Gregor <doug.gregor@gmail.com>
+
+ * g++.dg/cpp0x/variadic84.C: Update to reflect the change in
+ variadic template template parameter binding semantics.
+ * g++.dg/cpp0x/variadic85.C: Ditto.
+ * g++.dg/cpp0x/variadic88.C: New.
+ * g++.dg/cpp0x/variadic89.C: New.
+ * g++.dg/cpp0x/variadic90.C: New.
+ * g++.dg/cpp0x/variadic-ex14.C: Update to reflect the change in
+ variadic template template parameter binding semantics.
+ * g++.dg/cpp0x/variadic-lambda.C: New.
+
2008-03-25 Andrew Pinski <andrew_pinski@playstation.sony.com>
PR target/31558
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C
index 7050256..f33ca0e8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C
@@ -14,10 +14,6 @@ X<B> xB; // { dg-error "mismatch" }
X<C> xC; // { dg-error "mismatch" }
// { dg-error "expected a template" "" { target *-*-* } 14 }
// { dg-error "invalid type" "" { target *-*-* } 14 }
-Y<A> yA; // { dg-error "mismatch" }
-// { dg-error "expected a template" "" { target *-*-* } 17 }
-// { dg-error "invalid type" "" { target *-*-* } 17 }
-Y<B> yB; // { dg-error "mismatch" }
-// { dg-error "expected a template" "" { target *-*-* } 20 }
-// { dg-error "invalid type" "" { target *-*-* } 20 }
+Y<A> yA;
+Y<B> yB;
Y<C> yC; // okay
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C b/gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C
new file mode 100644
index 0000000..705d441
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C
@@ -0,0 +1,79 @@
+// { dg-options "-std=c++0x" }
+
+struct int_placeholder;
+
+template<typename T>
+struct do_replace
+{
+ typedef T type;
+};
+
+template<>
+struct do_replace<int_placeholder>
+{
+ typedef int type;
+};
+
+template<typename T> struct lambdalike
+{
+ typedef T type;
+};
+
+template<template<typename...> class TT, typename... Args>
+struct lambdalike<TT<Args...> > {
+ typedef TT<typename do_replace<Args>::type...> type;
+};
+
+
+template<typename T, typename U>
+struct is_same
+{
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T>
+{
+ static const bool value = true;
+};
+
+template<typename... Elements> struct tuple;
+template<typename T1, typename T2> struct pair;
+
+static_assert(is_same<lambdalike<tuple<float, int_placeholder, double>>::type,
+ tuple<float, int, double>>::value,
+ "MPL lambda-like replacement on tuple");
+static_assert(is_same<lambdalike<pair<float, int_placeholder>>::type,
+ pair<float, int>>::value,
+ "MPL lambda-like replacement on pair");
+
+
+struct _1 {};
+
+template<typename Arg0, typename Lambda>
+struct eval
+{
+ typedef Lambda type;
+};
+
+template<typename Arg0>
+struct eval<Arg0, _1>
+{
+ typedef Arg0 type;
+};
+
+template<typename Arg0, template<typename...> class T, typename... Pack>
+struct eval<Arg0, T<Pack...> >
+{
+ typedef T< typename eval<Arg0, Pack>::type... > type;
+};
+
+static_assert(is_same<eval<int, tuple<float, _1, double>>::type,
+ tuple<float, int, double>>::value, "eval tuple");
+static_assert(is_same<eval<int, pair<_1, double>>::type,
+ pair<int, double>>::value, "eval pair");
+static_assert(is_same<eval<int,
+ tuple<pair<_1, _1>, pair<float, float>,
+ pair<double, _1>>>::type,
+ tuple<pair<int, int>, pair<float, float>, pair<double, int>>>::value,
+ "recursive eval");
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic84.C b/gcc/testsuite/g++.dg/cpp0x/variadic84.C
index d5be764..ce31267 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic84.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic84.C
@@ -18,9 +18,9 @@ template<int> struct B1 {};
template<int, int> struct B2 {};
template<typename> struct B3 {};
template<typename, typename> struct B4 {};
-A1<B1<0> > a1; // { dg-error "incomplete type" }
-A2<B2<0, 1> > a2; // { dg-error "incomplete type" }
-A3<B2<0, 1> > a3; // { dg-error "incomplete type" }
-A4<B3<int> > a4; // { dg-error "incomplete type" }
-A5<B4<int, long> > a5; // { dg-error "incomplete type" }
-A6<B4<int, long> > a6; // { dg-error "incomplete type" }
+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;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic85.C b/gcc/testsuite/g++.dg/cpp0x/variadic85.C
index 7004d08..facb263 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic85.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic85.C
@@ -5,6 +5,6 @@
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; // { dg-error "incomplete type" }
+A1<B1<0, 1> > a1;
template<int...> struct B2 {};
A1<B2<0, 1> > a2; // { dg-error "incomplete type" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic88.C b/gcc/testsuite/g++.dg/cpp0x/variadic88.C
new file mode 100644
index 0000000..b14cabe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic88.C
@@ -0,0 +1,23 @@
+// { dg-options "-std=c++0x" }
+
+template<template<typename...> class TT>
+TT<int, float, double> foo(TT<int, float>)
+{
+ return TT<int, float, double>();
+}
+
+template<typename T>
+int& foo(T)
+{
+ static int i = 0; return i;
+}
+
+template<typename T, typename U>
+struct pair {};
+
+void bar()
+{
+ pair<int, float> p;
+ int& i = foo(p);
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic89.C b/gcc/testsuite/g++.dg/cpp0x/variadic89.C
new file mode 100644
index 0000000..b943771
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic89.C
@@ -0,0 +1,14 @@
+// { dg-options "-std=c++0x" }
+// Contributed by Eric Niebler
+template<typename T, typename U>
+struct pair
+{};
+
+template<typename T>
+struct test;
+
+template<template<typename...> class T, typename... Args>
+struct test<T<Args...> >
+{};
+
+test<pair<int, double> > t;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic90.C b/gcc/testsuite/g++.dg/cpp0x/variadic90.C
new file mode 100644
index 0000000..632e166
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic90.C
@@ -0,0 +1,8 @@
+// { dg-options "-std=c++0x" }
+
+template<template<typename...> class TT>
+struct X { };
+
+template<typename T, typename U> struct pair { };
+
+X<pair> x;