aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-01-07 15:43:01 -0500
committerJason Merrill <jason@gcc.gnu.org>2009-01-07 15:43:01 -0500
commitffaf1e05dd024cc57a21cea23722e0e37e5d8ebb (patch)
treebae01ef9b1a395e476eaa1c3ade6dd59e43205c9 /gcc
parent30af0edbf4637051e029063027052b843dbe8aac (diff)
downloadgcc-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/ChangeLog19
-rw-r--r--gcc/cp/pt.c205
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic65.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic82.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic83.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic92.C70
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic93.C11
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;
+}