diff options
author | Douglas Gregor <doug.gregor@gmail.com> | 2007-03-31 12:41:30 +0000 |
---|---|---|
committer | Doug Gregor <dgregor@gcc.gnu.org> | 2007-03-31 12:41:30 +0000 |
commit | d393153e7fb5a4bc1ed79b72c5c6d6c6ccc195b6 (patch) | |
tree | 8fa804b4fffaa8361c5c0a3d4f7d5dd2304adab7 /gcc | |
parent | d54a92b5f680c62ae4a129aece857a934e167809 (diff) | |
download | gcc-d393153e7fb5a4bc1ed79b72c5c6d6c6ccc195b6.zip gcc-d393153e7fb5a4bc1ed79b72c5c6d6c6ccc195b6.tar.gz gcc-d393153e7fb5a4bc1ed79b72c5c6d6c6ccc195b6.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/cp/parser.c | 69 | ||||
-rw-r--r-- | gcc/cp/pt.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 |
4 files changed, 90 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4374e6b..c13dcee 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 4fc1a62..63f7fec 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f1e6b18..906b8d5 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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 = diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a1af0d5..35e22c8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 |