re PR c++/31138 (ICE with ellipsis)

2007-03-31  Douglas Gregor  <doug.gregor@gmail.com>

	PR c++/31138
	PR c++/31140
	PR c++/31141
	* parser.c (declarator_can_be_parameter_pack): New.
	(cp_parser_template_parameter): Only parse the `...' if the
	declarator can be a parameter pack.
	(cp_parser_parameter_declaration): Ditto. Also, handle when TYPE
	is NULL.
	* pt.c (find_parameter_packs_r): Look into the bounds on integer
	types (they could be used as array bounds). 
	(check_for_bare_parameter_packs): Deal with TEMPLATE_PARM_INDEX.
	(tsubst_pack_expansion): Handle failure to expand parameter
	packs.

2007-03-31  Douglas Gregor  <doug.gregor@gmail.com>

	* g++.dg/parser/pr31138.C: New.
	* g++.dg/parser/pr31140.C: New.
	* g++.dg/parser/pr31141.C: New.

From-SVN: r123380
This commit is contained in:
Douglas Gregor 2007-03-31 12:41:30 +00:00 committed by Doug Gregor
parent d54a92b5f6
commit d393153e7f
4 changed files with 90 additions and 18 deletions

View file

@ -1,3 +1,19 @@
2007-03-31 Douglas Gregor <doug.gregor@gmail.com>
PR c++/31138
PR c++/31140
PR c++/31141
* parser.c (declarator_can_be_parameter_pack): New.
(cp_parser_template_parameter): Only parse the `...' if the
declarator can be a parameter pack.
(cp_parser_parameter_declaration): Ditto. Also, handle when TYPE
is NULL.
* pt.c (find_parameter_packs_r): Look into the bounds on integer
types (they could be used as array bounds).
(check_for_bare_parameter_packs): Deal with TEMPLATE_PARM_INDEX.
(tsubst_pack_expansion): Handle failure to expand parameter
packs.
2007-03-30 Paolo Carlini <pcarlini@suse.de>
PR c++/26099

View file

@ -1055,6 +1055,36 @@ make_array_declarator (cp_declarator *element, tree bounds)
return declarator;
}
/* Determine whether the declarator we've seen so far can be a
parameter pack, when followed by an ellipsis. */
static bool
declarator_can_be_parameter_pack (cp_declarator *declarator)
{
/* Search for a declarator name, or any other declarator that goes
after the point where the ellipsis could appear in a parameter
pack. If we find any of these, then this declarator can not be
made into a parameter pack. */
bool found = false;
while (declarator && !found)
{
switch ((int)declarator->kind)
{
case cdk_id:
case cdk_error:
case cdk_array:
case cdk_ptrmem:
found = true;
break;
default:
declarator = declarator->declarator;
break;
}
}
return !found;
}
cp_parameter_declarator *no_parameters;
/* Create a parameter declarator with the indicated DECL_SPECIFIERS,
@ -9049,9 +9079,9 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
marked as a parameter pack, then we have a parameter pack (that
has no declarator); */
if (!*is_parameter_pack
&& cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
&& cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)
&& declarator_can_be_parameter_pack (parameter_declarator->declarator))
{
/* Consume the `...'. */
cp_lexer_consume_token (parser->lexer);
maybe_warn_variadic_templates ();
@ -13095,32 +13125,35 @@ cp_parser_parameter_declaration (cp_parser *parser,
cp_parser_attributes_opt (parser));
}
/* If the next token is an ellipsis, and the type of the declarator
contains parameter packs but it is not a TYPE_PACK_EXPANSION, then
we actually have a parameter pack expansion expression. Otherwise,
leave the ellipsis for a C-style variadic function. */
/* If the next token is an ellipsis, and we have not seen a
declarator name, and the type of the declarator contains parameter
packs but it is not a TYPE_PACK_EXPANSION, then we actually have
a parameter pack expansion expression. Otherwise, leave the
ellipsis for a C-style variadic function. */
token = cp_lexer_peek_token (parser->lexer);
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
{
tree type = decl_specifiers.type;
if (DECL_P (type))
if (type && DECL_P (type))
type = TREE_TYPE (type);
if (TREE_CODE (type) != TYPE_PACK_EXPANSION
if (type
&& TREE_CODE (type) != TYPE_PACK_EXPANSION
&& declarator_can_be_parameter_pack (declarator)
&& (!declarator || !declarator->parameter_pack_p)
&& uses_parameter_packs (type))
{
/* Consume the `...'. */
cp_lexer_consume_token (parser->lexer);
maybe_warn_variadic_templates ();
/* Build a pack expansion type */
if (declarator)
declarator->parameter_pack_p = true;
else
decl_specifiers.type = make_pack_expansion (type);
}
/* Consume the `...'. */
cp_lexer_consume_token (parser->lexer);
maybe_warn_variadic_templates ();
/* Build a pack expansion type */
if (declarator)
declarator->parameter_pack_p = true;
else
decl_specifiers.type = make_pack_expansion (type);
}
}
/* The restriction on defining new types applies only to the type

View file

@ -2441,6 +2441,12 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
*walk_subtrees = 0;
return NULL_TREE;
case INTEGER_TYPE:
walk_tree (&TYPE_MAX_VALUE (t), &find_parameter_packs_r,
ppd, ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
default:
return NULL_TREE;
}
@ -2621,6 +2627,8 @@ check_for_bare_parameter_packs (tree t)
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);
@ -6860,6 +6868,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
if (arg_pack && TREE_CODE (arg_pack) == ARGUMENT_PACK_SELECT)
arg_pack = ARGUMENT_PACK_SELECT_FROM_PACK (arg_pack);
if (arg_pack && !ARGUMENT_PACK_P (arg_pack))
/* This can only happen if we forget to expand an argument
pack somewhere else. Just return an error, silently. */
{
result = make_tree_vec (1);
TREE_VEC_ELT (result, 0) = error_mark_node;
return result;
}
if (arg_pack)
{
int my_len =

View file

@ -1,3 +1,9 @@
2007-03-31 Douglas Gregor <doug.gregor@gmail.com>
* g++.dg/parser/pr31138.C: New.
* g++.dg/parser/pr31140.C: New.
* g++.dg/parser/pr31141.C: New.
2007-03-30 Paolo Carlini <pcarlini@suse.de>
PR c++/26099