Commit b1d7b1c0 by Douglas Gregor Committed by Doug Gregor

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
parent 77315816
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> 2007-05-24 Danny Smith <dannysmith@users.sourceforge.net>
PR target/27067 PR target/27067
......
...@@ -4393,7 +4393,7 @@ extern bool uses_parameter_packs (tree); ...@@ -4393,7 +4393,7 @@ extern bool uses_parameter_packs (tree);
extern bool template_parameter_pack_p (tree); extern bool template_parameter_pack_p (tree);
extern bool template_parms_variadic_p (tree); extern bool template_parms_variadic_p (tree);
extern tree make_pack_expansion (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 template_class_depth (tree);
extern int is_specialization_of (tree, tree); extern int is_specialization_of (tree, tree);
extern bool is_specialization_of_friend (tree, tree); extern bool is_specialization_of_friend (tree, tree);
......
...@@ -395,6 +395,19 @@ dump_type (tree t, int flags) ...@@ -395,6 +395,19 @@ dump_type (tree t, int flags)
pp_cxx_identifier (cxx_pp, "..."); pp_cxx_identifier (cxx_pp, "...");
break; 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: default:
pp_unsupported_tree (cxx_pp, t); pp_unsupported_tree (cxx_pp, t);
/* Fall through to error. */ /* Fall through to error. */
......
...@@ -2599,15 +2599,18 @@ make_pack_expansion (tree arg) ...@@ -2599,15 +2599,18 @@ make_pack_expansion (tree arg)
where "args" is a parameter pack. check_for_bare_parameter_packs where "args" is a parameter pack. check_for_bare_parameter_packs
should not be called for the subexpressions args, h(args), should not be called for the subexpressions args, h(args),
g(h(args)), or f(g(h(args))), because we would produce erroneous g(h(args)), or f(g(h(args))), because we would produce erroneous
error messages. */ error messages.
void
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) check_for_bare_parameter_packs (tree t)
{ {
tree parameter_packs = NULL_TREE; tree parameter_packs = NULL_TREE;
struct find_parameter_pack_data ppd; struct find_parameter_pack_data ppd;
if (!processing_template_decl || !t || t == error_mark_node) if (!processing_template_decl || !t || t == error_mark_node)
return; return true;
if (TREE_CODE (t) == TYPE_DECL) if (TREE_CODE (t) == TYPE_DECL)
t = TREE_TYPE (t); t = TREE_TYPE (t);
...@@ -2617,25 +2620,30 @@ check_for_bare_parameter_packs (tree t) ...@@ -2617,25 +2620,30 @@ check_for_bare_parameter_packs (tree t)
walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited); walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
pointer_set_destroy (ppd.visited); pointer_set_destroy (ppd.visited);
if (parameter_packs) { if (parameter_packs)
error ("parameter packs not expanded with `...':"); {
while (parameter_packs) error ("parameter packs not expanded with `...':");
{ while (parameter_packs)
tree pack = TREE_VALUE (parameter_packs); {
tree name = NULL_TREE; tree pack = TREE_VALUE (parameter_packs);
tree name = NULL_TREE;
if (TREE_CODE (pack) == TEMPLATE_TYPE_PARM
|| TREE_CODE (pack) == TEMPLATE_TEMPLATE_PARM) if (TREE_CODE (pack) == TEMPLATE_TYPE_PARM
name = TYPE_NAME (pack); || TREE_CODE (pack) == TEMPLATE_TEMPLATE_PARM)
else if (TREE_CODE (pack) == TEMPLATE_PARM_INDEX) name = TYPE_NAME (pack);
name = DECL_NAME (TEMPLATE_PARM_DECL (pack)); else if (TREE_CODE (pack) == TEMPLATE_PARM_INDEX)
else name = DECL_NAME (TEMPLATE_PARM_DECL (pack));
name = DECL_NAME (pack); else
inform (" %qD", name); name = DECL_NAME (pack);
inform (" %qD", name);
parameter_packs = TREE_CHAIN (parameter_packs);
} parameter_packs = TREE_CHAIN (parameter_packs);
} }
return false;
}
return true;
} }
/* Expand any parameter packs that occur in the template arguments in /* Expand any parameter packs that occur in the template arguments in
...@@ -3376,7 +3384,7 @@ process_partial_specialization (tree decl) ...@@ -3376,7 +3384,7 @@ process_partial_specialization (tree decl)
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)
= tree_cons (specargs, inner_parms, = tree_cons (specargs, inner_parms,
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)); DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type; TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
return decl; return decl;
} }
...@@ -3692,7 +3700,38 @@ push_template_decl_real (tree decl, bool is_friend) ...@@ -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 /* Ensure that there are no parameter packs in the type of this
declaration that have not been expanded. */ 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) if (is_partial)
return process_partial_specialization (decl); return process_partial_specialization (decl);
...@@ -4740,6 +4779,121 @@ convert_template_argument (tree parm, ...@@ -4740,6 +4779,121 @@ convert_template_argument (tree parm,
return val; 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 /* Convert all template arguments to their appropriate types, and
return a vector containing the innermost resulting template return a vector containing the innermost resulting template
arguments. If any error occurs, return error_mark_node. Error and arguments. If any error occurs, return error_mark_node. Error and
...@@ -4760,7 +4914,7 @@ coerce_template_parms (tree parms, ...@@ -4760,7 +4914,7 @@ coerce_template_parms (tree parms,
bool require_all_args, bool require_all_args,
bool use_default_args) bool use_default_args)
{ {
int nparms, nargs, i, lost = 0; int nparms, nargs, parm_idx, arg_idx, lost = 0;
tree inner_args; tree inner_args;
tree new_args; tree new_args;
tree new_inner_args; tree new_inner_args;
...@@ -4770,7 +4924,7 @@ coerce_template_parms (tree parms, ...@@ -4770,7 +4924,7 @@ coerce_template_parms (tree parms,
variadic template parameter list. Since it's an int, we can also variadic template parameter list. Since it's an int, we can also
subtract it from nparms to get the number of non-variadic subtract it from nparms to get the number of non-variadic
parameters. */ parameters. */
int variadic_p = template_parms_variadic_p (parms) ? 1 : 0; int variadic_p = 0;
inner_args inner_args
= expand_template_argument_pack (INNERMOST_TEMPLATE_ARGS (args)); = expand_template_argument_pack (INNERMOST_TEMPLATE_ARGS (args));
...@@ -4778,6 +4932,17 @@ coerce_template_parms (tree parms, ...@@ -4778,6 +4932,17 @@ coerce_template_parms (tree parms,
nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0; nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
nparms = TREE_VEC_LENGTH (parms); 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) if ((nargs > nparms - variadic_p && !variadic_p)
|| (nargs < nparms - variadic_p || (nargs < nparms - variadic_p
&& require_all_args && require_all_args
...@@ -4810,164 +4975,88 @@ coerce_template_parms (tree parms, ...@@ -4810,164 +4975,88 @@ coerce_template_parms (tree parms,
skip_evaluation = false; skip_evaluation = false;
new_inner_args = make_tree_vec (nparms); new_inner_args = make_tree_vec (nparms);
new_args = add_outermost_template_args (args, new_inner_args); 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 arg;
tree parm; tree parm;
/* Get the Ith template parameter. */ /* Get the Ith template parameter. */
parm = TREE_VEC_ELT (parms, i); parm = TREE_VEC_ELT (parms, parm_idx);
if (parm == error_mark_node) 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; continue;
} }
/* Calculate the Ith argument. */ /* Calculate the next argument. */
if (i < nargs) if (template_parameter_pack_p (TREE_VALUE (parm)))
{ {
arg = TREE_VEC_ELT (inner_args, i); /* All remaining arguments will be placed in the
template parameter pack PARM. */
if (PACK_EXPANSION_P (arg)) 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 /* If ARG is a pack expansion, but PARM is not a
a template parameter pack. We can't expand into a template parameter pack (if it were, we would have
handled it above), we're trying to expand into a
fixed-length argument list. */ fixed-length argument list. */
tree actual_parm = TREE_VALUE (parm); if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
bool parm_is_parameter_pack error ("cannot expand %<%E%> into a fixed-length "
= template_parameter_pack_p (actual_parm); "argument list", arg);
else
if (!parm_is_parameter_pack) 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) else if (require_all_args)
/* There must be a default arg in this case. */ /* There must be a default arg in this case. */
arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args, arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
complain, in_decl); complain, in_decl);
else else
break; break;
gcc_assert (arg);
if (arg == error_mark_node) if (arg == error_mark_node)
{ {
if (complain & tf_error) 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 else
arg = convert_template_argument (TREE_VALUE (parm), arg = convert_template_argument (TREE_VALUE (parm),
arg, new_args, complain, i, arg, new_args, complain,
in_decl); parm_idx, in_decl);
if (arg == error_mark_node) if (arg == error_mark_node)
lost++; lost++;
TREE_VEC_ELT (new_inner_args, i) = arg; TREE_VEC_ELT (new_inner_args, arg_idx) = arg;
} }
skip_evaluation = saved_skip_evaluation; 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) if (lost)
return error_mark_node; return error_mark_node;
...@@ -11055,8 +11144,12 @@ fn_type_unification (tree fn, ...@@ -11055,8 +11144,12 @@ fn_type_unification (tree fn,
/* Mark the argument pack as "incomplete". We could /* Mark the argument pack as "incomplete". We could
still deduce more arguments during unification. */ still deduce more arguments during unification. */
targ = TMPL_ARG (converted_args, level, idx); targ = TMPL_ARG (converted_args, level, idx);
ARGUMENT_PACK_INCOMPLETE_P(targ) = 1; if (targ)
ARGUMENT_PACK_EXPLICIT_ARGS (targ) = ARGUMENT_PACK_ARGS (targ); {
ARGUMENT_PACK_INCOMPLETE_P(targ) = 1;
ARGUMENT_PACK_EXPLICIT_ARGS (targ)
= ARGUMENT_PACK_ARGS (targ);
}
/* We have some incomplete argument packs. */ /* We have some incomplete argument packs. */
incomplete_argument_packs_p = true; incomplete_argument_packs_p = true;
...@@ -11425,6 +11518,27 @@ type_unification_real (tree tparms, ...@@ -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; return 2;
} }
...@@ -12889,7 +13003,7 @@ more_specialized_fn (tree pat1, tree pat2, int len) ...@@ -12889,7 +13003,7 @@ more_specialized_fn (tree pat1, tree pat2, int len)
if (TREE_CODE (arg1) == TYPE_PACK_EXPANSION) 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 parmvec = make_tree_vec (1);
tree argvec = make_tree_vec (len2); tree argvec = make_tree_vec (len2);
tree ta = args2; tree ta = args2;
...@@ -12913,7 +13027,7 @@ more_specialized_fn (tree pat1, tree pat2, int len) ...@@ -12913,7 +13027,7 @@ more_specialized_fn (tree pat1, tree pat2, int len)
} }
else if (TREE_CODE (arg2) == TYPE_PACK_EXPANSION) 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 parmvec = make_tree_vec (1);
tree argvec = make_tree_vec (len1); tree argvec = make_tree_vec (len1);
tree ta = args1; tree ta = args1;
......
...@@ -2283,6 +2283,11 @@ finish_member_declaration (tree decl) ...@@ -2283,6 +2283,11 @@ finish_member_declaration (tree decl)
/* Mark the DECL as a member of the current class. */ /* Mark the DECL as a member of the current class. */
DECL_CONTEXT (decl) = current_class_type; 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] /* [dcl.link]
A C language linkage is ignored for the names of class members A C language linkage is ignored for the names of class members
......
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> 2007-05-25 Richard Sandiford <richard@codesourcery.com>
* gcc.target/arm/long-calls-1.c: New test. * gcc.target/arm/long-calls-1.c: New test.
// { dg-options "-std=gnu++0x" }
template<typename, typename..., typename> void foo();
void bar()
{
foo<int>(); // { dg-error "no matching function" }
}
// { dg-options "-std=gnu++0x" }
template<typename..., typename> void foo();
void bar()
{
foo<int>(); // { dg-error "no matching function" }
}
// { 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" }
// { 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" }
}
// { 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" }
// { 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" }
// { 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>();
// { 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" }
}
// { 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" }
};
// { 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);
// { 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment