aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <doug.gregor@gmail.com>2007-05-25 13:15:04 +0000
committerDoug Gregor <dgregor@gcc.gnu.org>2007-05-25 13:15:04 +0000
commitb1d7b1c00e10e3550b2b1bfc91168679463e457f (patch)
tree626e35a9a9d851c0a1a037eb6349540dc9831f0e
parent77315816df628ed27788142071b54e0f31752313 (diff)
downloadgcc-b1d7b1c00e10e3550b2b1bfc91168679463e457f.zip
gcc-b1d7b1c00e10e3550b2b1bfc91168679463e457f.tar.gz
gcc-b1d7b1c00e10e3550b2b1bfc91168679463e457f.tar.bz2
re PR c++/31431 (ICE with invalid parameter pack)
2007-05-25 Douglas Gregor <doug.gregor@gmail.com> PR c++/31431 PR c++/31432 PR c++/31434 PR c++/31435 PR c++/31437 PR c++/31438 PR c++/31442 PR c++/31443 PR c++/31444 PR c++/31445 * error.c (dump_type): Dump TYPE_ARGUMENT_PACK nodes. * cp-tree.h (check_for_bare_parameter_packs): Returns bool. * pt.c (check_for_bare_parameter_packs): Return bool indicated whether everything was okay. Fix indentation. (push_template_decl_real): Check for bare parameter packs in function parameters; where errors occur, mark the parameter types with ERROR_MARK_NODEs to avert ICEs. (coerce_template_parameter_pack): New. (coerce_template_parms): Moved parameter pack coercion into coerce_template_parameter_pack, and permit it anywhere in the template parameter list (not just at the end). Parameter and argument indices can vary (somewhat) separately now, so add PARM_IDX and ARG_IDX. (fn_type_unification): Don't set an argument pack as incomplete if no argument pack was deduced. (type_unification_real): If a type parameter is a parameter pack and has not otherwise been deduced, it will be deduced to an empty parameter pack. (more_specialized_fn): Use the actual lengths of the argument lists when comparing against expansions. * semantics.c (finish_member_declaration): If a field's type has bare parameter packs, error and set its type to ERROR_MARK_NODE. 2007-05-25 Douglas Gregor <doug.gregor@gmail.com> PR c++/31431 PR c++/31432 PR c++/31434 PR c++/31435 PR c++/31437 PR c++/31438 PR c++/31442 PR c++/31443 PR c++/31444 PR c++/31445 * g++.dg/cpp0x/pr31431.C: New. * g++.dg/cpp0x/pr31437.C: New. * g++.dg/cpp0x/pr31442.C: New. * g++.dg/cpp0x/pr31444.C: New. * g++.dg/cpp0x/pr31431-2.C: New. * g++.dg/cpp0x/pr31432.C: New. * g++.dg/cpp0x/pr31434.C: New. * g++.dg/cpp0x/pr31438.C: New. * g++.dg/cpp0x/pr31443.C: New. * g++.dg/cpp0x/pr31445.C: New. * g++.dg/cpp0x/variadic-crash1.C: New. From-SVN: r125062
-rw-r--r--gcc/cp/ChangeLog35
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/error.c13
-rw-r--r--gcc/cp/pt.c428
-rw-r--r--gcc/cp/semantics.c5
-rw-r--r--gcc/testsuite/ChangeLog24
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31431-2.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31431.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31432.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31434.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31437.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31438.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31442.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31443.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31444.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31445.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-crash1.C72
17 files changed, 510 insertions, 158 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7738d1f..f2c6b6a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,38 @@
+2007-05-25 Douglas Gregor <doug.gregor@gmail.com>
+
+ PR c++/31431
+ PR c++/31432
+ PR c++/31434
+ PR c++/31435
+ PR c++/31437
+ PR c++/31438
+ PR c++/31442
+ PR c++/31443
+ PR c++/31444
+ PR c++/31445
+ * error.c (dump_type): Dump TYPE_ARGUMENT_PACK nodes.
+ * cp-tree.h (check_for_bare_parameter_packs): Returns bool.
+ * pt.c (check_for_bare_parameter_packs): Return bool indicated
+ whether everything was okay. Fix indentation.
+ (push_template_decl_real): Check for bare parameter packs in
+ function parameters; where errors occur, mark the parameter types
+ with ERROR_MARK_NODEs to avert ICEs.
+ (coerce_template_parameter_pack): New.
+ (coerce_template_parms): Moved parameter pack coercion into
+ coerce_template_parameter_pack, and permit it anywhere in the
+ template parameter list (not just at the end). Parameter and
+ argument indices can vary (somewhat) separately now, so add
+ PARM_IDX and ARG_IDX.
+ (fn_type_unification): Don't set an argument pack as incomplete if
+ no argument pack was deduced.
+ (type_unification_real): If a type parameter is a parameter pack
+ and has not otherwise been deduced, it will be deduced to an empty
+ parameter pack.
+ (more_specialized_fn): Use the actual lengths of the argument
+ lists when comparing against expansions.
+ * semantics.c (finish_member_declaration): If a field's type has
+ bare parameter packs, error and set its type to ERROR_MARK_NODE.
+
2007-05-24 Danny Smith <dannysmith@users.sourceforge.net>
PR target/27067
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index df067c9..413b224 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4393,7 +4393,7 @@ extern bool uses_parameter_packs (tree);
extern bool template_parameter_pack_p (tree);
extern bool template_parms_variadic_p (tree);
extern tree make_pack_expansion (tree);
-extern void check_for_bare_parameter_packs (tree);
+extern bool check_for_bare_parameter_packs (tree);
extern int template_class_depth (tree);
extern int is_specialization_of (tree, tree);
extern bool is_specialization_of_friend (tree, tree);
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 7329109..fcc7b08 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -395,6 +395,19 @@ dump_type (tree t, int flags)
pp_cxx_identifier (cxx_pp, "...");
break;
+ case TYPE_ARGUMENT_PACK:
+ {
+ tree args = ARGUMENT_PACK_ARGS (t);
+ int i;
+ for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
+ {
+ if (i)
+ pp_separate_with_comma (cxx_pp);
+ dump_type (TREE_VEC_ELT (args, i), flags);
+ }
+ }
+ break;
+
default:
pp_unsupported_tree (cxx_pp, t);
/* Fall through to error. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 05d7752..584e6cf 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2599,15 +2599,18 @@ make_pack_expansion (tree arg)
where "args" is a parameter pack. check_for_bare_parameter_packs
should not be called for the subexpressions args, h(args),
g(h(args)), or f(g(h(args))), because we would produce erroneous
- error messages. */
-void
+ error messages.
+
+ Returns TRUE if there were no bare parameter packs, returns FALSE
+ (and emits an error) if there were bare parameter packs.*/
+bool
check_for_bare_parameter_packs (tree t)
{
tree parameter_packs = NULL_TREE;
struct find_parameter_pack_data ppd;
if (!processing_template_decl || !t || t == error_mark_node)
- return;
+ return true;
if (TREE_CODE (t) == TYPE_DECL)
t = TREE_TYPE (t);
@@ -2617,25 +2620,30 @@ check_for_bare_parameter_packs (tree t)
walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
pointer_set_destroy (ppd.visited);
- if (parameter_packs) {
- error ("parameter packs not expanded with `...':");
- while (parameter_packs)
- {
- tree pack = TREE_VALUE (parameter_packs);
- tree name = NULL_TREE;
-
- if (TREE_CODE (pack) == TEMPLATE_TYPE_PARM
- || TREE_CODE (pack) == TEMPLATE_TEMPLATE_PARM)
- name = TYPE_NAME (pack);
- else if (TREE_CODE (pack) == TEMPLATE_PARM_INDEX)
- name = DECL_NAME (TEMPLATE_PARM_DECL (pack));
- else
- name = DECL_NAME (pack);
- inform (" %qD", name);
-
- parameter_packs = TREE_CHAIN (parameter_packs);
- }
- }
+ if (parameter_packs)
+ {
+ error ("parameter packs not expanded with `...':");
+ while (parameter_packs)
+ {
+ tree pack = TREE_VALUE (parameter_packs);
+ tree name = NULL_TREE;
+
+ if (TREE_CODE (pack) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (pack) == TEMPLATE_TEMPLATE_PARM)
+ name = TYPE_NAME (pack);
+ else if (TREE_CODE (pack) == TEMPLATE_PARM_INDEX)
+ name = DECL_NAME (TEMPLATE_PARM_DECL (pack));
+ else
+ name = DECL_NAME (pack);
+ inform (" %qD", name);
+
+ parameter_packs = TREE_CHAIN (parameter_packs);
+ }
+
+ return false;
+ }
+
+ return true;
}
/* Expand any parameter packs that occur in the template arguments in
@@ -3376,7 +3384,7 @@ process_partial_specialization (tree decl)
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)
= tree_cons (specargs, inner_parms,
- DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
+ DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
return decl;
}
@@ -3692,7 +3700,38 @@ push_template_decl_real (tree decl, bool is_friend)
/* Ensure that there are no parameter packs in the type of this
declaration that have not been expanded. */
- check_for_bare_parameter_packs (TREE_TYPE (decl));
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ /* Check each of the arguments individually to see if there are
+ any bare parameter packs. */
+ tree type = TREE_TYPE (decl);
+ tree arg = DECL_ARGUMENTS (decl);
+ tree argtype = TYPE_ARG_TYPES (type);
+
+ while (arg && argtype)
+ {
+ if (!FUNCTION_PARAMETER_PACK_P (arg)
+ && !check_for_bare_parameter_packs (TREE_TYPE (arg)))
+ {
+ /* This is a PARM_DECL that contains unexpanded parameter
+ packs. We have already complained about this in the
+ check_for_bare_parameter_packs call, so just replace
+ these types with ERROR_MARK_NODE. */
+ TREE_TYPE (arg) = error_mark_node;
+ TREE_VALUE (argtype) = error_mark_node;
+ }
+
+ arg = TREE_CHAIN (arg);
+ argtype = TREE_CHAIN (argtype);
+ }
+
+ /* Check for bare parameter packs in the return type and the
+ exception specifiers. */
+ check_for_bare_parameter_packs (TREE_TYPE (type));
+ check_for_bare_parameter_packs (TYPE_RAISES_EXCEPTIONS (type));
+ }
+ else
+ check_for_bare_parameter_packs (TREE_TYPE (decl));
if (is_partial)
return process_partial_specialization (decl);
@@ -4740,6 +4779,121 @@ convert_template_argument (tree parm,
return val;
}
+/* Coerces the remaining template arguments in INNER_ARGS (from
+ ARG_IDX to the end) into the parameter pack at PARM_IDX in PARMS.
+ Returns the coerced argument pack. PARM_IDX is the position of this
+ parameter in the template parameter list. ARGS is the original
+ template argument list. */
+static tree
+coerce_template_parameter_pack (tree parms,
+ int parm_idx,
+ tree args,
+ tree inner_args,
+ int arg_idx,
+ tree new_args,
+ int* lost,
+ tree in_decl,
+ tsubst_flags_t complain)
+{
+ tree parm = TREE_VEC_ELT (parms, parm_idx);
+ int nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
+ tree packed_args;
+ tree argument_pack;
+ tree packed_types = NULL_TREE;
+
+ if (arg_idx > nargs)
+ arg_idx = nargs;
+
+ packed_args = make_tree_vec (nargs - arg_idx);
+
+ if (TREE_CODE (TREE_VALUE (parm)) == PARM_DECL
+ && uses_parameter_packs (TREE_TYPE (TREE_VALUE (parm))))
+ {
+ /* When the template parameter is a non-type template
+ parameter pack whose type uses parameter packs, we need
+ to look at each of the template arguments
+ separately. Build a vector of the types for these
+ non-type template parameters in PACKED_TYPES. */
+ tree expansion
+ = make_pack_expansion (TREE_TYPE (TREE_VALUE (parm)));
+ packed_types = tsubst_pack_expansion (expansion, args,
+ complain, in_decl);
+
+ if (packed_types == error_mark_node)
+ return error_mark_node;
+
+ /* Check that we have the right number of arguments. */
+ if (arg_idx < nargs
+ && !PACK_EXPANSION_P (TREE_VEC_ELT (inner_args, arg_idx))
+ && nargs - arg_idx != TREE_VEC_LENGTH (packed_types))
+ {
+ int needed_parms
+ = TREE_VEC_LENGTH (parms) - 1 + TREE_VEC_LENGTH (packed_types);
+ error ("wrong number of template arguments (%d, should be %d)",
+ nargs, needed_parms);
+ return error_mark_node;
+ }
+
+ /* If we aren't able to check the actual arguments now
+ (because they haven't been expanded yet), we can at least
+ verify that all of the types used for the non-type
+ template parameter pack are, in fact, valid for non-type
+ template parameters. */
+ if (arg_idx < nargs
+ && PACK_EXPANSION_P (TREE_VEC_ELT (inner_args, arg_idx)))
+ {
+ int j, len = TREE_VEC_LENGTH (packed_types);
+ for (j = 0; j < len; ++j)
+ {
+ tree t = TREE_VEC_ELT (packed_types, j);
+ if (invalid_nontype_parm_type_p (t, complain))
+ return error_mark_node;
+ }
+ }
+ }
+
+ /* Convert the remaining arguments, which will be a part of the
+ parameter pack "parm". */
+ for (; arg_idx < nargs; ++arg_idx)
+ {
+ tree arg = TREE_VEC_ELT (inner_args, arg_idx);
+ tree actual_parm = TREE_VALUE (parm);
+
+ if (packed_types && !PACK_EXPANSION_P (arg))
+ {
+ /* When we have a vector of types (corresponding to the
+ non-type template parameter pack that uses parameter
+ packs in its type, as mention above), and the
+ argument is not an expansion (which expands to a
+ currently unknown number of arguments), clone the
+ parm and give it the next type in PACKED_TYPES. */
+ actual_parm = copy_node (actual_parm);
+ TREE_TYPE (actual_parm) =
+ TREE_VEC_ELT (packed_types, arg_idx - parm_idx);
+ }
+
+ arg = convert_template_argument (actual_parm,
+ arg, new_args, complain, parm_idx,
+ in_decl);
+ if (arg == error_mark_node)
+ (*lost)++;
+ TREE_VEC_ELT (packed_args, arg_idx - parm_idx) = arg;
+ }
+
+ if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
+ || TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
+ argument_pack = make_node (TYPE_ARGUMENT_PACK);
+ else
+ {
+ argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
+ TREE_TYPE (argument_pack) = TREE_TYPE (TREE_VALUE (parm));
+ TREE_CONSTANT (argument_pack) = 1;
+ }
+
+ SET_ARGUMENT_PACK_ARGS (argument_pack, packed_args);
+ return argument_pack;
+}
+
/* Convert all template arguments to their appropriate types, and
return a vector containing the innermost resulting template
arguments. If any error occurs, return error_mark_node. Error and
@@ -4760,7 +4914,7 @@ coerce_template_parms (tree parms,
bool require_all_args,
bool use_default_args)
{
- int nparms, nargs, i, lost = 0;
+ int nparms, nargs, parm_idx, arg_idx, lost = 0;
tree inner_args;
tree new_args;
tree new_inner_args;
@@ -4770,7 +4924,7 @@ coerce_template_parms (tree parms,
variadic template parameter list. Since it's an int, we can also
subtract it from nparms to get the number of non-variadic
parameters. */
- int variadic_p = template_parms_variadic_p (parms) ? 1 : 0;
+ int variadic_p = 0;
inner_args
= expand_template_argument_pack (INNERMOST_TEMPLATE_ARGS (args));
@@ -4778,6 +4932,17 @@ coerce_template_parms (tree parms,
nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
nparms = TREE_VEC_LENGTH (parms);
+ /* Determine if there are any parameter packs. */
+ for (parm_idx = 0; parm_idx < nparms; ++parm_idx)
+ {
+ tree tparm = TREE_VALUE (TREE_VEC_ELT (parms, parm_idx));
+ if (template_parameter_pack_p (tparm))
+ {
+ variadic_p = 1;
+ break;
+ }
+ }
+
if ((nargs > nparms - variadic_p && !variadic_p)
|| (nargs < nparms - variadic_p
&& require_all_args
@@ -4810,164 +4975,88 @@ coerce_template_parms (tree parms,
skip_evaluation = false;
new_inner_args = make_tree_vec (nparms);
new_args = add_outermost_template_args (args, new_inner_args);
- for (i = 0; i < nparms - variadic_p; i++)
+ for (parm_idx = 0, arg_idx = 0; parm_idx < nparms; parm_idx++, arg_idx++)
{
tree arg;
tree parm;
/* Get the Ith template parameter. */
- parm = TREE_VEC_ELT (parms, i);
+ parm = TREE_VEC_ELT (parms, parm_idx);
if (parm == error_mark_node)
{
- TREE_VEC_ELT (new_inner_args, i) = error_mark_node;
+ TREE_VEC_ELT (new_inner_args, arg_idx) = error_mark_node;
continue;
}
- /* Calculate the Ith argument. */
- if (i < nargs)
+ /* Calculate the next argument. */
+ if (template_parameter_pack_p (TREE_VALUE (parm)))
{
- arg = TREE_VEC_ELT (inner_args, i);
-
- if (PACK_EXPANSION_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);
+
+ /* 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;
+
+ continue;
+ }
+ else if (arg_idx < nargs)
+ {
+ arg = TREE_VEC_ELT (inner_args, arg_idx);
+
+ if (arg && PACK_EXPANSION_P (arg))
{
- /* If ARG is a pack expansion, then PARM must be
- a template parameter pack. We can't expand into a
+ /* 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. */
- tree actual_parm = TREE_VALUE (parm);
- bool parm_is_parameter_pack
- = template_parameter_pack_p (actual_parm);
-
- if (!parm_is_parameter_pack)
- {
- if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
- error ("cannot expand %<%E%> into a fixed-length "
- "argument list", arg);
- else
- error ("cannot expand %<%T%> into a fixed-length "
- "argument list", arg);
- }
+ if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
+ error ("cannot expand %<%E%> into a fixed-length "
+ "argument list", arg);
+ else
+ error ("cannot expand %<%T%> into a fixed-length "
+ "argument list", arg);
}
}
else if (require_all_args)
- /* There must be a default arg in this case. */
- arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
- complain, in_decl);
+ /* There must be a default arg in this case. */
+ arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
+ complain, in_decl);
else
break;
- gcc_assert (arg);
if (arg == error_mark_node)
{
if (complain & tf_error)
- error ("template argument %d is invalid", i + 1);
- }
+ error ("template argument %d is invalid", arg_idx + 1);
+ }
+ else if (!arg)
+ /* This only occurs if there was an error in the template
+ parameter list itself (which we would already have
+ reported) that we are trying to recover from, e.g., a class
+ template with a parameter list such as
+ template<typename..., typename>. */
+ return error_mark_node;
else
arg = convert_template_argument (TREE_VALUE (parm),
- arg, new_args, complain, i,
- in_decl);
+ arg, new_args, complain,
+ parm_idx, in_decl);
if (arg == error_mark_node)
lost++;
- TREE_VEC_ELT (new_inner_args, i) = arg;
+ TREE_VEC_ELT (new_inner_args, arg_idx) = arg;
}
skip_evaluation = saved_skip_evaluation;
- if (variadic_p)
- {
- int expected_len = nargs - nparms + 1;
- tree parm = TREE_VEC_ELT (parms, nparms - 1);
- tree packed_args;
- tree argument_pack;
- tree packed_types = NULL_TREE;
-
- packed_args = make_tree_vec (expected_len >= 0 ? expected_len : 0);
-
- if (TREE_CODE (TREE_VALUE (parm)) == PARM_DECL
- && uses_parameter_packs (TREE_TYPE (TREE_VALUE (parm))))
- {
- /* When the template parameter is a non-type template
- parameter pack whose type uses parameter packs, we need
- to look at each of the template arguments
- separately. Build a vector of the types for these
- non-type template parameters in PACKED_TYPES. */
- tree expansion
- = make_pack_expansion (TREE_TYPE (TREE_VALUE (parm)));
- packed_types = tsubst_pack_expansion (expansion, args,
- complain, in_decl);
-
- if (packed_types == error_mark_node)
- return error_mark_node;
-
- /* Check that we have the right number of arguments. */
- if (i < nargs
- && !PACK_EXPANSION_P (TREE_VEC_ELT (inner_args, i))
- && nargs - i != TREE_VEC_LENGTH (packed_types))
- {
- error ("wrong number of template arguments (%d, should be %d)",
- nargs, nparms - 1 + TREE_VEC_LENGTH (packed_types));
- return error_mark_node;
- }
-
- /* If we aren't able to check the actual arguments now
- (because they haven't been expanded yet), we can at least
- verify that all of the types used for the non-type
- template parameter pack are, in fact, valid for non-type
- template parameters. */
- if (i < nargs && PACK_EXPANSION_P (TREE_VEC_ELT (inner_args, i)))
- {
- int j, len = TREE_VEC_LENGTH (packed_types);
- for (j = 0; j < len; ++j)
- {
- tree t = TREE_VEC_ELT (packed_types, j);
- if (invalid_nontype_parm_type_p (t, complain))
- return error_mark_node;
- }
- }
- }
-
- /* Convert the remaining arguments, which will be a part of the
- parameter pack "parm". */
- for (; i < nargs; ++i)
- {
- tree arg = TREE_VEC_ELT (inner_args, i);
- tree actual_parm = TREE_VALUE (parm);
-
- if (packed_types && !PACK_EXPANSION_P (arg))
- {
- /* When we have a vector of types (corresponding to the
- non-type template parameter pack that uses parameter
- packs in its type, as mention above), and the
- argument is not an expansion (which expands to a
- currently unknown number of arguments), clone the
- parm and give it the next type in PACKED_TYPES. */
- actual_parm = copy_node (actual_parm);
- TREE_TYPE (actual_parm) =
- TREE_VEC_ELT (packed_types, i - nparms + 1);
- }
-
- arg = convert_template_argument (actual_parm,
- arg, new_args, complain, i,
- in_decl);
- if (arg == error_mark_node)
- lost++;
- TREE_VEC_ELT (packed_args, i - nparms + 1) = arg;
- }
-
- if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
- || TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
- argument_pack = make_node (TYPE_ARGUMENT_PACK);
- else
- {
- argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
- TREE_TYPE (argument_pack) = TREE_TYPE (TREE_VALUE (parm));
- TREE_CONSTANT (argument_pack) = 1;
- }
-
- SET_ARGUMENT_PACK_ARGS (argument_pack, packed_args);
- TREE_VEC_ELT (new_inner_args, nparms - 1) = argument_pack;
- }
-
if (lost)
return error_mark_node;
@@ -11055,8 +11144,12 @@ fn_type_unification (tree fn,
/* Mark the argument pack as "incomplete". We could
still deduce more arguments during unification. */
targ = TMPL_ARG (converted_args, level, idx);
- ARGUMENT_PACK_INCOMPLETE_P(targ) = 1;
- ARGUMENT_PACK_EXPLICIT_ARGS (targ) = ARGUMENT_PACK_ARGS (targ);
+ if (targ)
+ {
+ ARGUMENT_PACK_INCOMPLETE_P(targ) = 1;
+ ARGUMENT_PACK_EXPLICIT_ARGS (targ)
+ = ARGUMENT_PACK_ARGS (targ);
+ }
/* We have some incomplete argument packs. */
incomplete_argument_packs_p = true;
@@ -11425,6 +11518,27 @@ type_unification_real (tree tparms,
}
}
+ /* If the type parameter is a parameter pack, then it will
+ be deduced to an empty parameter pack. */
+ if (template_parameter_pack_p (tparm))
+ {
+ tree arg;
+
+ if (TREE_CODE (tparm) == TEMPLATE_PARM_INDEX)
+ {
+ arg = make_node (NONTYPE_ARGUMENT_PACK);
+ TREE_TYPE (arg) = TREE_TYPE (TEMPLATE_PARM_DECL (tparm));
+ TREE_CONSTANT (arg) = 1;
+ }
+ else
+ arg = make_node (TYPE_ARGUMENT_PACK);
+
+ SET_ARGUMENT_PACK_ARGS (arg, make_tree_vec (0));
+
+ TREE_VEC_ELT (targs, i) = arg;
+ continue;
+ }
+
return 2;
}
@@ -12889,7 +13003,7 @@ more_specialized_fn (tree pat1, tree pat2, int len)
if (TREE_CODE (arg1) == TYPE_PACK_EXPANSION)
{
- int i, len2 = len + 1;
+ int i, len2 = list_length (args2);
tree parmvec = make_tree_vec (1);
tree argvec = make_tree_vec (len2);
tree ta = args2;
@@ -12913,7 +13027,7 @@ more_specialized_fn (tree pat1, tree pat2, int len)
}
else if (TREE_CODE (arg2) == TYPE_PACK_EXPANSION)
{
- int i, len1 = len + 1;
+ int i, len1 = list_length (args1);
tree parmvec = make_tree_vec (1);
tree argvec = make_tree_vec (len1);
tree ta = args1;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index a484c05..827f532 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2283,6 +2283,11 @@ finish_member_declaration (tree decl)
/* Mark the DECL as a member of the current class. */
DECL_CONTEXT (decl) = current_class_type;
+ /* Check for bare parameter packs in the member variable declaration. */
+ if (TREE_CODE (decl) == FIELD_DECL
+ && !check_for_bare_parameter_packs (TREE_TYPE (decl)))
+ TREE_TYPE (decl) == error_mark_node;
+
/* [dcl.link]
A C language linkage is ignored for the names of class members
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 499acb2..474be38 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,27 @@
+2007-05-25 Douglas Gregor <doug.gregor@gmail.com>
+
+ PR c++/31431
+ PR c++/31432
+ PR c++/31434
+ PR c++/31435
+ PR c++/31437
+ PR c++/31438
+ PR c++/31442
+ PR c++/31443
+ PR c++/31444
+ PR c++/31445
+ * g++.dg/cpp0x/pr31431.C: New.
+ * g++.dg/cpp0x/pr31437.C: New.
+ * g++.dg/cpp0x/pr31442.C: New.
+ * g++.dg/cpp0x/pr31444.C: New.
+ * g++.dg/cpp0x/pr31431-2.C: New.
+ * g++.dg/cpp0x/pr31432.C: New.
+ * g++.dg/cpp0x/pr31434.C: New.
+ * g++.dg/cpp0x/pr31438.C: New.
+ * g++.dg/cpp0x/pr31443.C: New.
+ * g++.dg/cpp0x/pr31445.C: New.
+ * g++.dg/cpp0x/variadic-crash1.C: New.
+
2007-05-25 Richard Sandiford <richard@codesourcery.com>
* gcc.target/arm/long-calls-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C b/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C
new file mode 100644
index 0000000..2f74e38
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C
@@ -0,0 +1,7 @@
+// { dg-options "-std=gnu++0x" }
+template<typename, typename..., typename> void foo();
+
+void bar()
+{
+ foo<int>(); // { dg-error "no matching function" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31431.C b/gcc/testsuite/g++.dg/cpp0x/pr31431.C
new file mode 100644
index 0000000..061dab0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31431.C
@@ -0,0 +1,7 @@
+// { dg-options "-std=gnu++0x" }
+template<typename..., typename> void foo();
+
+void bar()
+{
+ foo<int>(); // { dg-error "no matching function" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31432.C b/gcc/testsuite/g++.dg/cpp0x/pr31432.C
new file mode 100644
index 0000000..cb8826e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31432.C
@@ -0,0 +1,8 @@
+// { dg-options "-std=gnu++0x" }
+template<typename..., typename> struct A // { dg-error "parameter pack" }
+{
+ static int i;
+};
+
+A<int, int> a; // { dg-error "invalid type" }
+A<char,int> b; // { dg-error "invalid type" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31434.C b/gcc/testsuite/g++.dg/cpp0x/pr31434.C
new file mode 100644
index 0000000..a785ae9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31434.C
@@ -0,0 +1,11 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... T> int foo(const T&) // { dg-error "not expanded with|T" }
+{
+ union { T t; }; // { dg-error "not expanded with|T" }
+ return t;
+}
+
+void bar()
+{
+ foo(0); // { dg-error "no matching" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31437.C b/gcc/testsuite/g++.dg/cpp0x/pr31437.C
new file mode 100644
index 0000000..0e1a888
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31437.C
@@ -0,0 +1,9 @@
+// { dg-options "-std=gnu++0x" }
+template <typename... T> struct A
+{ // { dg-error "candidates|A" }
+ A(T* p) { // { dg-error "parameter packs|T" }
+ (A<T...>*)(p);
+ }
+};
+
+A<int> a(0); // { dg-error "no matching" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31438.C b/gcc/testsuite/g++.dg/cpp0x/pr31438.C
new file mode 100644
index 0000000..3a12563
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31438.C
@@ -0,0 +1,9 @@
+// { dg-options "-std=gnu++0x" }
+
+template<typename> struct A; // { dg-error "candidates" }
+template<typename T, typename... U> struct A<T(U)> // { dg-error "parameter packs|U" }
+{ // { dg-error "parameter packs|U" }
+ template<typename X> A(X); // { dg-error "parameter packs|U" }
+};
+
+A<void(int)> a(0); // { dg-error "no matching" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31442.C b/gcc/testsuite/g++.dg/cpp0x/pr31442.C
new file mode 100644
index 0000000..050e299
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31442.C
@@ -0,0 +1,9 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... T, T = 0> struct A {}; // { dg-error "parameter packs|T|the end" }
+
+struct B
+{
+ template <template <typename...> class C> B(C<int>);
+};
+
+B b = A<int>();
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31443.C b/gcc/testsuite/g++.dg/cpp0x/pr31443.C
new file mode 100644
index 0000000..1eb9d31
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31443.C
@@ -0,0 +1,11 @@
+// { dg-options "-std=gnu++0x" }
+
+template<int, typename... T> struct A
+{
+ template<int N> void foo(A<N,T>); // { dg-error "parameter packs|T" }
+};
+
+void bar()
+{
+ A<0,int>().foo(A<0,int>()); // { dg-error "no member named" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31444.C b/gcc/testsuite/g++.dg/cpp0x/pr31444.C
new file mode 100644
index 0000000..b1f86fe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31444.C
@@ -0,0 +1,10 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... T> struct A
+{
+ template<int> void foo(A<T>); // { dg-error "not expanded|T" }
+};
+
+void bar()
+{
+ A<int>().foo<0>(A<int>()); // { dg-error "no member named" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31445.C b/gcc/testsuite/g++.dg/cpp0x/pr31445.C
new file mode 100644
index 0000000..025cb96
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31445.C
@@ -0,0 +1,8 @@
+// { dg-options "-std=gnu++0x" }
+template <typename... T> struct A
+{
+ void foo(T...); // { dg-error "candidates" }
+ A(T... t) { foo(t); } // { dg-error "parameter packs|t|no matching" }
+};
+
+A<int> a(0);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-crash1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-crash1.C
new file mode 100644
index 0000000..f26aee2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-crash1.C
@@ -0,0 +1,72 @@
+// { dg-options "-std=gnu++0x" }
+
+#define ONE
+#define TWO
+#define THREE
+
+struct Something {};
+Something ___;
+
+template <class F>
+struct Trial
+{
+ F f;
+public:
+ Trial() : f() {}
+ Trial( const F& ff ) : f(ff) { }
+ template <typename... Args>
+ struct Sig { typedef int ResultType; };
+
+ template <typename... Args>
+ struct Sig<Something,Args...> { typedef int ResultType; };
+
+#ifdef ONE
+
+template <typename... Args>
+typename Sig<Something,Args...>::ResultType operator()(const Something& s, const Args&... args) const
+{
+ return f(args...);
+}
+#endif
+#ifdef TWO
+template <typename... Args>
+typename Sig<Args...>::ResultType operator()(const Args&... args) const
+{
+ return f(args...);
+}
+#endif
+};
+
+struct Internal
+{
+
+template <typename... Args>
+struct Sig { typedef int ResultType; };
+
+template <typename... Args>
+struct Sig<Something,Args...> { typedef int ResultType; };
+
+template <typename... Args>
+int operator()(const Args&... args) const
+{
+ int n = sizeof...(Args);
+ return n;
+}
+
+ static Trial<Internal>& full() { static Trial<Internal> f; return f; }
+};
+
+static Trial<Internal>& internal = Internal::full();
+
+int main()
+{
+ int n = 0;
+#ifdef ONE
+ n = internal(___,1,2);
+#endif
+#ifdef THREE
+ n = internal(___,1,2,3);
+ n = internal(___,1,2,3,4);
+#endif
+ return 0;
+}