From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 115092 invoked by alias); 9 Jul 2015 17:48:22 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 115079 invoked by uid 89); 9 Jul 2015 17:48:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=AWL,BAYES_50,KAM_LAZY_DOMAIN_SECURITY,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 09 Jul 2015 17:48:20 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (Postfix) with ESMTPS id 2EB83BC6A1 for ; Thu, 9 Jul 2015 17:48:19 +0000 (UTC) Received: from [10.10.116.20] ([10.10.116.20]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t69HmIAG027425 for ; Thu, 9 Jul 2015 13:48:18 -0400 To: gcc-patches List From: Jason Merrill Subject: C++ PATCHes to template parameter parsing Message-ID: <559EB3DE.8000502@redhat.com> Date: Thu, 09 Jul 2015 17:48:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.0.1 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------030707060709000104000006" X-SW-Source: 2015-07/txt/msg00799.txt.bz2 This is a multi-part message in MIME format. --------------030707060709000104000006 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-length: 734 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. --------------030707060709000104000006 Content-Type: text/x-patch; name="defarg.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="defarg.patch" Content-length: 5721 commit bfb4b766089dedf5a51371cfcb64d2caffe41bb2 Author: Jason Merrill 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; --------------030707060709000104000006 Content-Type: text/x-patch; name="pack2.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="pack2.patch" Content-length: 8854 commit 6e1c13bb890aa1f19ffc051b2bc3f5f8f956257b Author: Jason Merrill 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. --------------030707060709000104000006--