diff options
author | Douglas Gregor <doug.gregor@gmail.com> | 2008-01-15 18:49:47 +0000 |
---|---|---|
committer | Doug Gregor <dgregor@gcc.gnu.org> | 2008-01-15 18:49:47 +0000 |
commit | cdcae7450ee750f6e41d2d47fa6c52841db5fba1 (patch) | |
tree | 9b68e1a6f40c5f5f93069912e1b4c9c184633aef /gcc/cp/parser.c | |
parent | 4439d02f0f5881b186b7d3430a9504310e227e30 (diff) | |
download | gcc-cdcae7450ee750f6e41d2d47fa6c52841db5fba1.zip gcc-cdcae7450ee750f6e41d2d47fa6c52841db5fba1.tar.gz gcc-cdcae7450ee750f6e41d2d47fa6c52841db5fba1.tar.bz2 |
re PR c++/34751 (ICE with pointer to member and variadic templates)
2008-01-15 Douglas Gregor <doug.gregor@gmail.com>
PR c++/34751
* pt.c (coerce_template_parameter_pack): When substituting into
the type of a non-type template parameter pack. use the
deduced/substituted arguments.
* parser.c (declarator_can_be_parameter_pack): A pointer-to-member
can be a parameter pack with the ellipsis following it. When we
have an erroneous declaration, allow it to be a parameter pack.
(cp_parser_template_parameter): Complain about default
arguments on non-type template parameter packs, and parse them
using the new cp_parser_default_argument.
(cp_parser_parameter_declaration): Complain about parameter packs
with default arguments. Move parsing of default arguments into a
new function, cp_parser_default_argument.
(cp_parser_default_argument): New; extracted from
cp_parser_parameter_declaration.
2008-01-15 Douglas Gregor <doug.gregor@gmail.com>
PR c++/34751
* g++.dg/cpp0x/vt-34751.C: New.
From-SVN: r131548
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 133 |
1 files changed, 94 insertions, 39 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 1400424..6462f35 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1071,12 +1071,13 @@ declarator_can_be_parameter_pack (cp_declarator *declarator) switch ((int)declarator->kind) { case cdk_id: - case cdk_error: case cdk_array: - case cdk_ptrmem: found = true; break; - + + case cdk_error: + return true; + default: declarator = declarator->declarator; break; @@ -1734,6 +1735,8 @@ static cp_parameter_declarator *cp_parser_parameter_declaration_list (cp_parser *, bool *); static cp_parameter_declarator *cp_parser_parameter_declaration (cp_parser *, bool, bool *); +static tree cp_parser_default_argument + (cp_parser *, bool); static void cp_parser_function_body (cp_parser *); static tree cp_parser_initializer @@ -9385,16 +9388,39 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type, /* If the next token is an ellipsis, and we don't already have it marked as a parameter pack, then we have a parameter pack (that - has no declarator); */ + has no declarator). */ if (!*is_parameter_pack && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS) && declarator_can_be_parameter_pack (parameter_declarator->declarator)) { - /* Consume the `...'. */ + /* Consume the `...'. */ cp_lexer_consume_token (parser->lexer); maybe_warn_variadic_templates (); *is_parameter_pack = true; + + /* Parameter packs cannot have default arguments. However, a + user may try to do so, so we'll parse them and give an + appropriate diagnostic here. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) + { + /* Consume the `='. */ + cp_lexer_consume_token (parser->lexer); + + /* Find the name of the parameter pack. */ + cp_declarator *id_declarator = parameter_declarator->declarator; + while (id_declarator && id_declarator->kind != cdk_id) + id_declarator = id_declarator->declarator; + + if (id_declarator && id_declarator->kind == cdk_id) + error ("template parameter pack %qD cannot have a default argument", + id_declarator->u.id.unqualified_name); + else + error ("template parameter pack cannot have a default argument"); + + /* Parse the default argument, but throw away the result. */ + cp_parser_default_argument (parser, /*template_parm_p=*/true); + } } parm = grokdeclarator (parameter_declarator->declarator, @@ -13540,7 +13566,6 @@ cp_parser_parameter_declaration (cp_parser *parser, /* If the next token is `=', then process a default argument. */ if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) { - bool saved_greater_than_is_operator_p; /* Consume the `='. */ cp_lexer_consume_token (parser->lexer); @@ -13646,39 +13671,9 @@ cp_parser_parameter_declaration (cp_parser *parser, /* Outside of a class definition, we can just parse the assignment-expression. */ else - { - bool saved_local_variables_forbidden_p; - - /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is - set correctly. */ - saved_greater_than_is_operator_p - = parser->greater_than_is_operator_p; - parser->greater_than_is_operator_p = greater_than_is_operator_p; - /* Local variable names (and the `this' keyword) may not - appear in a default argument. */ - saved_local_variables_forbidden_p - = parser->local_variables_forbidden_p; - parser->local_variables_forbidden_p = true; - /* The default argument expression may cause implicitly - defined member functions to be synthesized, which will - result in garbage collection. We must treat this - situation as if we were within the body of function so as - to avoid collecting live data on the stack. */ - ++function_depth; - /* Parse the assignment-expression. */ - if (template_parm_p) - push_deferring_access_checks (dk_no_deferred); - default_argument - = cp_parser_assignment_expression (parser, /*cast_p=*/false); - if (template_parm_p) - pop_deferring_access_checks (); - /* Restore saved state. */ - --function_depth; - parser->greater_than_is_operator_p - = saved_greater_than_is_operator_p; - parser->local_variables_forbidden_p - = saved_local_variables_forbidden_p; - } + default_argument + = cp_parser_default_argument (parser, template_parm_p); + if (!parser->default_arg_ok_p) { if (!flag_pedantic_errors) @@ -13689,6 +13684,26 @@ cp_parser_parameter_declaration (cp_parser *parser, default_argument = NULL_TREE; } } + else if ((declarator && declarator->parameter_pack_p) + || (decl_specifiers.type + && PACK_EXPANSION_P (decl_specifiers.type))) + { + const char* kind = template_parm_p? "template " : ""; + + /* Find the name of the parameter pack. */ + cp_declarator *id_declarator = declarator; + while (id_declarator && id_declarator->kind != cdk_id) + id_declarator = id_declarator->declarator; + + if (id_declarator && id_declarator->kind == cdk_id) + error ("%sparameter pack %qD cannot have a default argument", + kind, id_declarator->u.id.unqualified_name); + else + error ("%sparameter pack cannot have a default argument", + kind); + + default_argument = NULL_TREE; + } } else default_argument = NULL_TREE; @@ -13698,6 +13713,46 @@ cp_parser_parameter_declaration (cp_parser *parser, default_argument); } +/* Parse a default argument and return it. + + TEMPLATE_PARM_P is true if this is a default argument for a + non-type template parameter. */ +static tree +cp_parser_default_argument (cp_parser *parser, bool template_parm_p) +{ + tree default_argument = NULL_TREE; + bool saved_greater_than_is_operator_p; + bool saved_local_variables_forbidden_p; + + /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is + set correctly. */ + saved_greater_than_is_operator_p = parser->greater_than_is_operator_p; + parser->greater_than_is_operator_p = !template_parm_p; + /* Local variable names (and the `this' keyword) may not + appear in a default argument. */ + saved_local_variables_forbidden_p = parser->local_variables_forbidden_p; + parser->local_variables_forbidden_p = true; + /* The default argument expression may cause implicitly + defined member functions to be synthesized, which will + result in garbage collection. We must treat this + situation as if we were within the body of function so as + to avoid collecting live data on the stack. */ + ++function_depth; + /* Parse the assignment-expression. */ + if (template_parm_p) + push_deferring_access_checks (dk_no_deferred); + default_argument + = cp_parser_assignment_expression (parser, /*cast_p=*/false); + if (template_parm_p) + pop_deferring_access_checks (); + /* Restore saved state. */ + --function_depth; + parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; + parser->local_variables_forbidden_p = saved_local_variables_forbidden_p; + + return default_argument; +} + /* Parse a function-body. function-body: |