diff options
author | Douglas Gregor <doug.gregor@gmail.com> | 2008-03-26 04:17:57 +0000 |
---|---|---|
committer | Doug Gregor <dgregor@gcc.gnu.org> | 2008-03-26 04:17:57 +0000 |
commit | a0a5f30f8e6741d55daca7fb3093df6365425661 (patch) | |
tree | f1ef439448a570f47eb3eed0834a900570fcfa64 /gcc | |
parent | 22ec849c3b1088a10c46068f3df6e1e9fbc9efd4 (diff) | |
download | gcc-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/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/pt.c | 182 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C | 79 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic84.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic85.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic88.C | 23 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic89.C | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic90.C | 8 |
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; |