The first patch is a cleanup hoisted from the c++-concepts branch: on
the branch we want to be able to parse type/template in multiple places,
so Andrew factored that out, but it's a good code cleanup on the trunk
as well.
While looking at this and related code on the branch, I noticed that
there was a lot of redundant code in cp_parser_template_parameter for
dealing with parameter packs that we should have handled already in
cp_parser_parameter_declaration. I've dealt with that by taking over an
unused flag in cp_parameter_declarator for passing back that the
parameter is a pack. And while I was there I tweaked a permerror that
wasn't using the permerror function.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit bfb4b766089dedf5a51371cfcb64d2caffe41bb2
Author: Jason Merrill <ja...@redhat.com>
Date: Thu Jul 9 12:11:58 2015 -0400
* parser.c (cp_parser_default_type_template_argument)
(cp_parser_default_template_template_argument): Factor out from
cp_parser_type_parameter.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d64b227..686654c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -13330,6 +13330,69 @@ cp_parser_template_parameter_list (cp_parser* parser)
return end_template_parm_list (parameter_list);
}
+/* Parse a default argument for a type template-parameter.
+ Note that diagnostics are handled in cp_parser_template_parameter. */
+
+static tree
+cp_parser_default_type_template_argument (cp_parser *parser)
+{
+ gcc_assert (cp_lexer_next_token_is (parser->lexer, CPP_EQ));
+
+ /* Consume the `=' token. */
+ cp_lexer_consume_token (parser->lexer);
+
+ /* Parse the default-argument. */
+ push_deferring_access_checks (dk_no_deferred);
+ tree default_argument = cp_parser_type_id (parser);
+ pop_deferring_access_checks ();
+
+ return default_argument;
+}
+
+/* Parse a default argument for a template template-parameter. */
+
+static tree
+cp_parser_default_template_template_argument (cp_parser *parser)
+{
+ gcc_assert (cp_lexer_next_token_is (parser->lexer, CPP_EQ));
+
+ bool is_template;
+
+ /* Consume the `='. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Parse the id-expression. */
+ push_deferring_access_checks (dk_no_deferred);
+ /* save token before parsing the id-expression, for error
+ reporting */
+ const cp_token* token = cp_lexer_peek_token (parser->lexer);
+ tree default_argument
+ = cp_parser_id_expression (parser,
+ /*template_keyword_p=*/false,
+ /*check_dependency_p=*/true,
+ /*template_p=*/&is_template,
+ /*declarator_p=*/false,
+ /*optional_p=*/false);
+ if (TREE_CODE (default_argument) == TYPE_DECL)
+ /* If the id-expression was a template-id that refers to
+ a template-class, we already have the declaration here,
+ so no further lookup is needed. */
+ ;
+ else
+ /* Look up the name. */
+ default_argument
+ = cp_parser_lookup_name (parser, default_argument,
+ none_type,
+ /*is_template=*/is_template,
+ /*is_namespace=*/false,
+ /*check_dependency=*/true,
+ /*ambiguous_decls=*/NULL,
+ token->location);
+ /* See if the default argument is valid. */
+ default_argument = check_template_template_default_arg (default_argument);
+ pop_deferring_access_checks ();
+ return default_argument;
+}
+
/* Parse a template-parameter.
template-parameter:
@@ -13552,11 +13615,8 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
/* If the next token is an `=', we have a default argument. */
if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
{
- /* Consume the `=' token. */
- cp_lexer_consume_token (parser->lexer);
- /* Parse the default-argument. */
- push_deferring_access_checks (dk_no_deferred);
- default_argument = cp_parser_type_id (parser);
+ default_argument
+ = cp_parser_default_type_template_argument (parser);
/* Template parameter packs cannot have default
arguments. */
@@ -13574,7 +13634,6 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
}
else if (check_for_bare_parameter_packs (default_argument))
default_argument = error_mark_node;
- pop_deferring_access_checks ();
}
else
default_argument = NULL_TREE;
@@ -13632,40 +13691,8 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
default-argument. */
if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
{
- bool is_template;
-
- /* Consume the `='. */
- cp_lexer_consume_token (parser->lexer);
- /* Parse the id-expression. */
- push_deferring_access_checks (dk_no_deferred);
- /* save token before parsing the id-expression, for error
- reporting */
- token = cp_lexer_peek_token (parser->lexer);
default_argument
- = cp_parser_id_expression (parser,
- /*template_keyword_p=*/false,
- /*check_dependency_p=*/true,
- /*template_p=*/&is_template,
- /*declarator_p=*/false,
- /*optional_p=*/false);
- if (TREE_CODE (default_argument) == TYPE_DECL)
- /* If the id-expression was a template-id that refers to
- a template-class, we already have the declaration here,
- so no further lookup is needed. */
- ;
- else
- /* Look up the name. */
- default_argument
- = cp_parser_lookup_name (parser, default_argument,
- none_type,
- /*is_template=*/is_template,
- /*is_namespace=*/false,
- /*check_dependency=*/true,
- /*ambiguous_decls=*/NULL,
- token->location);
- /* See if the default argument is valid. */
- default_argument
- = check_template_template_default_arg (default_argument);
+ = cp_parser_default_template_template_argument (parser);
/* Template parameter packs cannot have default
arguments. */
@@ -13681,7 +13708,6 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
"have default arguments");
default_argument = NULL_TREE;
}
- pop_deferring_access_checks ();
}
else
default_argument = NULL_TREE;
commit 6e1c13bb890aa1f19ffc051b2bc3f5f8f956257b
Author: Jason Merrill <ja...@redhat.com>
Date: Thu Jul 9 13:40:02 2015 -0400
* cp-tree.h (struct cp_parameter_declarator): Rename ellipsis_p to
template_parameter_pack_p.
* parser.c (declarator_can_be_parameter_pack): False if
parameter_pack_p is set.
(make_parameter_declarator): Add template_parameter_pack_p parm.
(cp_parser_template_parameter): Remove parameter pack parsing.
(cp_parser_parameter_declaration): Handle all parameter packs.
Tweak default argument permerror.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 18cf87e..d383612 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5042,9 +5042,8 @@ struct cp_parameter_declarator {
cp_declarator *declarator;
/* The default-argument expression, or NULL_TREE, if none. */
tree default_argument;
- /* True iff this is the first parameter in the list and the
- parameter sequence ends with an ellipsis. */
- bool ellipsis_p;
+ /* True iff this is is a template parameter pack. */
+ bool template_parameter_pack_p;
};
/* A declarator. */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 686654c..4911096 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1349,8 +1349,6 @@ static cp_declarator *make_pointer_declarator
(cp_cv_quals, cp_declarator *, tree);
static cp_declarator *make_reference_declarator
(cp_cv_quals, cp_declarator *, bool, tree);
-static cp_parameter_declarator *make_parameter_declarator
- (cp_decl_specifier_seq *, cp_declarator *, tree);
static cp_declarator *make_ptrmem_declarator
(cp_cv_quals, tree, cp_declarator *, tree);
@@ -1575,6 +1573,10 @@ make_array_declarator (cp_declarator *element, tree bounds)
static bool
declarator_can_be_parameter_pack (cp_declarator *declarator)
{
+ if (declarator && declarator->parameter_pack_p)
+ /* We already saw an ellipsis. */
+ return false;
+
/* 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
@@ -1609,7 +1611,8 @@ cp_parameter_declarator *no_parameters;
cp_parameter_declarator *
make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers,
cp_declarator *declarator,
- tree default_argument)
+ tree default_argument,
+ bool template_parameter_pack_p = false)
{
cp_parameter_declarator *parameter;
@@ -1622,7 +1625,7 @@ make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers,
clear_decl_specs (¶meter->decl_specifiers);
parameter->declarator = declarator;
parameter->default_argument = default_argument;
- parameter->ellipsis_p = false;
+ parameter->template_parameter_pack_p = template_parameter_pack_p;
return parameter;
}
@@ -13411,7 +13414,6 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
{
cp_token *token;
cp_parameter_declarator *parameter_declarator;
- cp_declarator *id_declarator;
tree parm;
/* Assume it is a type parameter or a template parameter. */
@@ -13472,15 +13474,9 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
return error_mark_node;
/* If the parameter declaration is marked as a parameter pack, set
- *IS_PARAMETER_PACK to notify the caller. Also, unmark the
- declarator's PACK_EXPANSION_P, otherwise we'll get errors from
- grokdeclarator. */
- if (parameter_declarator->declarator
- && parameter_declarator->declarator->parameter_pack_p)
- {
- *is_parameter_pack = true;
- parameter_declarator->declarator->parameter_pack_p = false;
- }
+ *IS_PARAMETER_PACK to notify the caller. */
+ if (parameter_declarator->template_parameter_pack_p)
+ *is_parameter_pack = true;
if (parameter_declarator->default_argument)
{
@@ -13489,55 +13485,6 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
/* Consume the `...' for better error recovery. */
cp_lexer_consume_token (parser->lexer);
}
- /* 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). */
- else if (!*is_parameter_pack
- && 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 ();
-
- *is_parameter_pack = true;
- }
- /* We might end up with a pack expansion as the type of the non-type
- template parameter, in which case this is a non-type template
- parameter pack. */
- else if (parameter_declarator->decl_specifiers.type
- && PACK_EXPANSION_P (parameter_declarator->decl_specifiers.type))
- {
- *is_parameter_pack = true;
- parameter_declarator->decl_specifiers.type =
- PACK_EXPANSION_PATTERN (parameter_declarator->decl_specifiers.type);
- }
-
- if (*is_parameter_pack && cp_lexer_next_token_is (parser->lexer, CPP_EQ))
- {
- /* 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. */
-
- cp_token *start_token = cp_lexer_peek_token (parser->lexer);
-
- /* Find the name of the parameter pack. */
- 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_at (start_token->location,
- "template parameter pack %qD cannot have a default argument",
- id_declarator->u.id.unqualified_name);
- else
- error_at (start_token->location,
- "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,
¶meter_declarator->decl_specifiers,
@@ -19039,6 +18986,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
tree default_argument;
cp_token *token = NULL, *declarator_token_start = NULL;
const char *saved_message;
+ bool template_parameter_pack_p = false;
/* In a template parameter, `>' is not an operator.
@@ -19124,6 +19072,15 @@ cp_parser_parameter_declaration (cp_parser *parser,
decl_specifiers.attributes
= chainon (decl_specifiers.attributes,
cp_parser_attributes_opt (parser));
+
+ /* If the declarator is a template parameter pack, remember that and
+ clear the flag in the declarator itself so we don't get errors
+ from grokdeclarator. */
+ if (template_parm_p && declarator && declarator->parameter_pack_p)
+ {
+ declarator->parameter_pack_p = false;
+ template_parameter_pack_p = true;
+ }
}
/* If the next token is an ellipsis, and we have not seen a
@@ -19142,15 +19099,16 @@ cp_parser_parameter_declaration (cp_parser *parser,
if (type
&& TREE_CODE (type) != TYPE_PACK_EXPANSION
&& declarator_can_be_parameter_pack (declarator)
- && (!declarator || !declarator->parameter_pack_p)
- && uses_parameter_packs (type))
+ && (template_parm_p || uses_parameter_packs (type)))
{
/* Consume the `...'. */
cp_lexer_consume_token (parser->lexer);
maybe_warn_variadic_templates ();
/* Build a pack expansion type */
- if (declarator)
+ if (template_parm_p)
+ template_parameter_pack_p = true;
+ else if (declarator)
declarator->parameter_pack_p = true;
else
decl_specifiers.type = make_pack_expansion (type);
@@ -19179,17 +19137,12 @@ cp_parser_parameter_declaration (cp_parser *parser,
if (!parser->default_arg_ok_p)
{
- if (flag_permissive)
- warning (0, "deprecated use of default argument for parameter of non-function");
- else
- {
- error_at (token->location,
- "default arguments are only "
- "permitted for function parameters");
- default_argument = NULL_TREE;
- }
+ permerror (token->location,
+ "default arguments are only "
+ "permitted for function parameters");
}
else if ((declarator && declarator->parameter_pack_p)
+ || template_parameter_pack_p
|| (decl_specifiers.type
&& PACK_EXPANSION_P (decl_specifiers.type)))
{
@@ -19222,7 +19175,8 @@ cp_parser_parameter_declaration (cp_parser *parser,
return make_parameter_declarator (&decl_specifiers,
declarator,
- default_argument);
+ default_argument,
+ template_parameter_pack_p);
}
/* Parse a default argument and return it.