diff options
author | Jason Merrill <jason@redhat.com> | 2009-01-07 15:43:01 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2009-01-07 15:43:01 -0500 |
commit | ffaf1e05dd024cc57a21cea23722e0e37e5d8ebb (patch) | |
tree | bae01ef9b1a395e476eaa1c3ade6dd59e43205c9 /gcc | |
parent | 30af0edbf4637051e029063027052b843dbe8aac (diff) | |
download | gcc-ffaf1e05dd024cc57a21cea23722e0e37e5d8ebb.zip gcc-ffaf1e05dd024cc57a21cea23722e0e37e5d8ebb.tar.gz gcc-ffaf1e05dd024cc57a21cea23722e0e37e5d8ebb.tar.bz2 |
re PR c++/35297 (Compiling error with variadic template with fixed parameter with default type.)
PR c++/35297
PR c++/35477
PR c++/35784
PR c++/36846
PR c++/38276
* pt.c (check_default_tmpl_args): Don't complain about
out-of-order parameter packs in the enclosing class
or parameter packs after default args.
(coerce_template_parms): If we have more than one
parameter pack, don't flatten argument packs.
(template_args_equal): Handle argument packs.
(comp_template_args): Don't flatten argument packs.
(check_instantiated_arg): Split out from...
(check_instantiated_args): Here. Handle arg packs.
(convert_template_argument): Just check that nontype argument
packs have the right type.
From-SVN: r143166
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/cp/pt.c | 205 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic65.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic82.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic83.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic92.C | 70 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic93.C | 11 |
8 files changed, 243 insertions, 77 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1e85539..e1539c5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,22 @@ +2009-01-06 Jason Merrill <jason@redhat.com> + + PR c++/35297 + PR c++/35477 + PR c++/35784 + PR c++/36846 + PR c++/38276 + * pt.c (check_default_tmpl_args): Don't complain about + out-of-order parameter packs in the enclosing class + or parameter packs after default args. + (coerce_template_parms): If we have more than one + parameter pack, don't flatten argument packs. + (template_args_equal): Handle argument packs. + (comp_template_args): Don't flatten argument packs. + (check_instantiated_arg): Split out from... + (check_instantiated_args): Here. Handle arg packs. + (convert_template_argument): Just check that nontype argument + packs have the right type. + 2009-01-05 Dodji Seketeli <dodji@redhat.com> PR c++/38472 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 786e845..410641d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3590,7 +3590,8 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary, if (TREE_PURPOSE (parm)) seen_def_arg_p = 1; - else if (seen_def_arg_p) + else if (seen_def_arg_p + && !template_parameter_pack_p (TREE_VALUE (parm))) { error ("no default argument for %qD", TREE_VALUE (parm)); /* For better subsequent error-recovery, we indicate that @@ -3601,6 +3602,9 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary, else if (is_primary && !is_partial && !is_friend_decl + /* Don't complain about an enclosing partial + specialization. */ + && parm_level == parms && TREE_CODE (decl) == TYPE_DECL && i < ntparms - 1 && template_parameter_pack_p (TREE_VALUE (parm))) @@ -5060,7 +5064,19 @@ convert_template_argument (tree parm, if (invalid_nontype_parm_type_p (t, complain)) return error_mark_node; - if (!uses_template_parms (orig_arg) && !uses_template_parms (t)) + if (template_parameter_pack_p (parm) && ARGUMENT_PACK_P (orig_arg)) + { + if (same_type_p (t, TREE_TYPE (orig_arg))) + val = orig_arg; + else + { + /* Not sure if this is reachable, but it doesn't hurt + to be robust. */ + error ("type mismatch in nontype parameter pack"); + val = error_mark_node; + } + } + else if (!uses_template_parms (orig_arg) && !uses_template_parms (t)) /* We used to call digest_init here. However, digest_init will report errors, which we don't want when complain is zero. More importantly, digest_init will try too @@ -5233,10 +5249,6 @@ coerce_template_parms (tree parms, parameters. */ int variadic_p = 0; - inner_args - = expand_template_argument_pack (INNERMOST_TEMPLATE_ARGS (args)); - - nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0; nparms = TREE_VEC_LENGTH (parms); /* Determine if there are any parameter packs. */ @@ -5244,13 +5256,22 @@ coerce_template_parms (tree parms, { tree tparm = TREE_VALUE (TREE_VEC_ELT (parms, parm_idx)); if (template_parameter_pack_p (tparm)) - { - variadic_p = 1; - break; - } + ++variadic_p; } - if ((nargs > nparms - variadic_p && !variadic_p) + inner_args = INNERMOST_TEMPLATE_ARGS (args); + /* If there are 0 or 1 parameter packs, we need to expand any argument + packs so that we can deduce a parameter pack from some non-packed args + followed by an argument pack, as in variadic85.C. If there are more + than that, we need to leave argument packs intact so the arguments are + assigned to the right parameter packs. This should only happen when + dealing with a nested class inside a partial specialization of a class + template, as in variadic92.C. */ + if (variadic_p <= 1) + inner_args = expand_template_argument_pack (inner_args); + + nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0; + if ((nargs > nparms && !variadic_p) || (nargs < nparms - variadic_p && require_all_args && (!use_default_args @@ -5297,42 +5318,48 @@ coerce_template_parms (tree parms, } /* Calculate the next argument. */ - if (template_parameter_pack_p (TREE_VALUE (parm))) + if (arg_idx < nargs) + arg = TREE_VEC_ELT (inner_args, arg_idx); + else + arg = NULL_TREE; + + if (template_parameter_pack_p (TREE_VALUE (parm)) + && !(arg && ARGUMENT_PACK_P (arg))) { - /* All remaining arguments will be placed in the - template parameter pack PARM. */ - arg = coerce_template_parameter_pack (parms, parm_idx, args, - inner_args, arg_idx, - new_args, &lost, - in_decl, complain); - + /* All remaining arguments will be placed in the + template parameter pack PARM. */ + arg = coerce_template_parameter_pack (parms, parm_idx, args, + inner_args, arg_idx, + new_args, &lost, + in_decl, complain); + /* Store this argument. */ if (arg == error_mark_node) lost++; TREE_VEC_ELT (new_inner_args, parm_idx) = arg; - /* We are done with all of the arguments. */ - arg_idx = nargs; - + /* We are done with all of the arguments. */ + arg_idx = nargs; + continue; } - else if (arg_idx < nargs) - { - arg = TREE_VEC_ELT (inner_args, arg_idx); - - if (arg && PACK_EXPANSION_P (arg)) + else if (arg) + { + if (PACK_EXPANSION_P (arg)) { if (complain & tf_error) { + /* FIXME this restriction was removed by N2555; see + bug 35722. */ /* If ARG is a pack expansion, but PARM is not a template parameter pack (if it were, we would have handled it above), we're trying to expand into a fixed-length argument list. */ if (TREE_CODE (arg) == EXPR_PACK_EXPANSION) - error ("cannot expand %<%E%> into a fixed-length " + sorry ("cannot expand %<%E%> into a fixed-length " "argument list", arg); else - error ("cannot expand %<%T%> into a fixed-length " + sorry ("cannot expand %<%T%> into a fixed-length " "argument list", arg); } return error_mark_node; @@ -5389,6 +5416,25 @@ template_args_equal (tree ot, tree nt) return PACK_EXPANSION_P (nt) && template_args_equal (PACK_EXPANSION_PATTERN (ot), PACK_EXPANSION_PATTERN (nt)); + else if (ARGUMENT_PACK_P (ot)) + { + int i, len; + tree opack, npack; + + if (!ARGUMENT_PACK_P (nt)) + return 0; + + opack = ARGUMENT_PACK_ARGS (ot); + npack = ARGUMENT_PACK_ARGS (nt); + len = TREE_VEC_LENGTH (opack); + if (TREE_VEC_LENGTH (npack) != len) + return 0; + for (i = 0; i < len; ++i) + if (!template_args_equal (TREE_VEC_ELT (opack, i), + TREE_VEC_ELT (npack, i))) + return 0; + return 1; + } else if (TYPE_P (nt)) return TYPE_P (ot) && same_type_p (ot, nt); else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot)) @@ -5405,9 +5451,6 @@ comp_template_args (tree oldargs, tree newargs) { int i; - oldargs = expand_template_argument_pack (oldargs); - newargs = expand_template_argument_pack (newargs); - if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs)) return 0; @@ -11707,58 +11750,76 @@ tsubst_copy_and_build (tree t, Emit an error under control of COMPLAIN, and return TRUE on error. */ static bool -check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain) +check_instantiated_arg (tree tmpl, tree t, tsubst_flags_t complain) { - int ix, len = DECL_NTPARMS (tmpl); - bool result = false; + if (ARGUMENT_PACK_P (t)) + { + tree vec = ARGUMENT_PACK_ARGS (t); + int len = TREE_VEC_LENGTH (vec); + bool result = false; + int i; - for (ix = 0; ix != len; ix++) + for (i = 0; i < len; ++i) + if (check_instantiated_arg (tmpl, TREE_VEC_ELT (vec, i), complain)) + result = true; + return result; + } + else if (TYPE_P (t)) { - tree t = TREE_VEC_ELT (args, ix); + /* [basic.link]: A name with no linkage (notably, the name + of a class or enumeration declared in a local scope) + shall not be used to declare an entity with linkage. + This implies that names with no linkage cannot be used as + template arguments. */ + tree nt = no_linkage_check (t, /*relaxed_p=*/false); - if (TYPE_P (t)) + if (nt) { - /* [basic.link]: A name with no linkage (notably, the name - of a class or enumeration declared in a local scope) - shall not be used to declare an entity with linkage. - This implies that names with no linkage cannot be used as - template arguments. */ - tree nt = no_linkage_check (t, /*relaxed_p=*/false); - - if (nt) - { - /* DR 488 makes use of a type with no linkage cause - type deduction to fail. */ - if (complain & tf_error) - { - if (TYPE_ANONYMOUS_P (nt)) - error ("%qT is/uses anonymous type", t); - else - error ("template argument for %qD uses local type %qT", - tmpl, t); - } - result = true; - } - /* In order to avoid all sorts of complications, we do not - allow variably-modified types as template arguments. */ - else if (variably_modified_type_p (t, NULL_TREE)) + /* DR 488 makes use of a type with no linkage cause + type deduction to fail. */ + if (complain & tf_error) { - if (complain & tf_error) - error ("%qT is a variably modified type", t); - result = true; + if (TYPE_ANONYMOUS_P (nt)) + error ("%qT is/uses anonymous type", t); + else + error ("template argument for %qD uses local type %qT", + tmpl, t); } + return true; } - /* A non-type argument of integral or enumerated type must be a - constant. */ - else if (TREE_TYPE (t) - && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t)) - && !TREE_CONSTANT (t)) + /* In order to avoid all sorts of complications, we do not + allow variably-modified types as template arguments. */ + else if (variably_modified_type_p (t, NULL_TREE)) { if (complain & tf_error) - error ("integral expression %qE is not constant", t); - result = true; + error ("%qT is a variably modified type", t); + return true; } } + /* A non-type argument of integral or enumerated type must be a + constant. */ + else if (TREE_TYPE (t) + && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t)) + && !TREE_CONSTANT (t)) + { + if (complain & tf_error) + error ("integral expression %qE is not constant", t); + return true; + } + return false; +} + +static bool +check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain) +{ + int ix, len = DECL_NTPARMS (tmpl); + bool result = false; + + for (ix = 0; ix != len; ix++) + { + if (check_instantiated_arg (tmpl, TREE_VEC_ELT (args, ix), complain)) + result = true; + } if (result && (complain & tf_error)) error (" trying to instantiate %qD", tmpl); return result; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c3e22fc..0e605d0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-01-07 Jason Merrill <jason@redhat.com> + + * g++.dg/cpp0x/variadic92.C: New test. + * g++.dg/cpp0x/variadic93.C: New test. + 2009-01-07 Janis Johnson <janis187@us.ibm.com> * lib/target-supports-dg.exp (current_compiler_flags): New. diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic65.C b/gcc/testsuite/g++.dg/cpp0x/variadic65.C index 6379da8..1c815d1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic65.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic65.C @@ -5,4 +5,4 @@ template<typename T1 = unused, typename T2 = unused, typename T3 = unused, struct tuple {}; template<typename... Args> -void foo(tuple<Args...>) { } // { dg-error "cannot expand" } +void foo(tuple<Args...>) { } // { dg-bogus "cannot expand" "" { xfail *-*-* } } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic82.C b/gcc/testsuite/g++.dg/cpp0x/variadic82.C index 5acbc83..fb3ddb3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic82.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic82.C @@ -3,9 +3,9 @@ template<typename> struct A; -template<typename... T> struct A<T*...> // { dg-error "cannot expand" } +template<typename... T> struct A<T*...> // { dg-bogus "cannot expand" "" { xfail *-*-* } } { struct B; }; -A<void*> a; // { dg-error "incomplete type" } +A<void*> a; // { dg-bogus "incomplete type" "" { xfail *-*-* } } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic83.C b/gcc/testsuite/g++.dg/cpp0x/variadic83.C index ec6cabd..2613d62 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic83.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic83.C @@ -3,6 +3,6 @@ template<typename> struct A; -template<typename... T> struct A<T...> { }; // { dg-error "cannot expand" } +template<typename... T> struct A<T...> { }; // { dg-bogus "cannot expand" "" { xfail *-*-* } } -A<int> a; // { dg-error "incomplete type" } +A<int> a; // { dg-bogus "incomplete type" "" { xfail *-*-* } } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic92.C b/gcc/testsuite/g++.dg/cpp0x/variadic92.C new file mode 100644 index 0000000..d382912 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic92.C @@ -0,0 +1,70 @@ +// Various tests for variadic templates and partial specialization. +// { dg-options "-std=c++0x" } + +// PR c++/36846 +template<typename A, typename B> +struct pair; + +template<typename... T> +struct pairs; + +template<typename... AS, typename... BS> +struct pairs<pair<AS, BS>...> { + struct mismatched_packs {}; +}; + +template class pairs< + pair<int, int>, + pair<int, int> +>; + +template<int A, int B> +struct point; + +template<typename... T> +struct points; + +template<int... AS, int... BS> +struct points<point<AS, BS>...> { + struct mismatched_packs {}; +}; + +template class points< + point<0, 1>, + point<0, 1> +>; + +// PR c++/35477 +template <class...ARGS> struct tuple {}; +template <class A, class B> struct test {}; +template <class... ARGS, class B> struct test<B, tuple<ARGS...>> +{ + template <class T> struct inside {}; +}; + +// PR c++/38276 +template<typename...> struct A; + +template<typename, typename> struct B; + +template<typename... T, typename... U> struct B<A<T...>, A<U...> > +{ + static int i; +}; + +B<A<>, A<int> > b1; + +B<A<int>, A<> > b2; + +// PR c++/35784 +template <typename...> struct p; + +template <typename, typename> struct d; + +template <typename... A, typename... B> +struct d<p<A...>, p<B...> > { typedef int t; }; + +typedef d<p<>, p<int, float> >::t q; +typedef d<q, d<p<int>, p<float> >::t> r; // * + +typedef d<d<p<>, p<int, float> >::t, d<p<>, p<> >::t> s; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic93.C b/gcc/testsuite/g++.dg/cpp0x/variadic93.C new file mode 100644 index 0000000..7d8c329 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic93.C @@ -0,0 +1,11 @@ +// PR c++/35297 +// { dg-options "-std=c++0x" } + +template <class T=int, class... ARGS> +struct test2 {}; + +int main() +{ + test2<> a; + return 0; +} |