aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
authorDouglas Gregor <doug.gregor@gmail.com>2008-01-15 18:49:47 +0000
committerDoug Gregor <dgregor@gcc.gnu.org>2008-01-15 18:49:47 +0000
commitcdcae7450ee750f6e41d2d47fa6c52841db5fba1 (patch)
tree9b68e1a6f40c5f5f93069912e1b4c9c184633aef /gcc/cp/parser.c
parent4439d02f0f5881b186b7d3430a9504310e227e30 (diff)
downloadgcc-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.c133
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: