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;
(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
/* 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,
/* 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);
/* 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)
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;
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: