From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 38079 invoked by alias); 30 Jan 2020 21:06:12 -0000 Mailing-List: contact gcc-cvs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-cvs-owner@gcc.gnu.org Received: (qmail 38059 invoked by uid 9846); 30 Jan 2020 21:06:11 -0000 Date: Thu, 30 Jan 2020 21:06:00 -0000 Message-ID: <20200130210611.38058.qmail@sourceware.org> Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Iain D Sandoe To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/c++-coroutines] c++: Fix attributes with lambda and trailing return type. X-Act-Checkin: gcc X-Git-Author: Jason Merrill X-Git-Refname: refs/heads/devel/c++-coroutines X-Git-Oldrev: 165255c7a562e04e3be89eb1c87b4ac3c5248d77 X-Git-Newrev: 245e40af4fab5b7cf40fb310591a879355775971 X-SW-Source: 2020-01/txt/msg04848.txt.bz2 https://gcc.gnu.org/g:245e40af4fab5b7cf40fb310591a879355775971 commit 245e40af4fab5b7cf40fb310591a879355775971 Author: Jason Merrill Date: Tue Jan 28 17:41:05 2020 -0500 c++: Fix attributes with lambda and trailing return type. My fix for 60503 fixed handling of C++11 attributes following the lambda-declarator. My patch for 89640 re-added support for GNU attributes, but attributes after the trailing return type were parsed as applying to the return type rather than to the function. This patch adjusts parsing of a trailing-return-type to ignore GNU attributes at the end of the declaration so that they will be applied to the declaration as a whole. I also considered parsing the attributes between the closing paren and the trailing-return-type, and tried a variety of approaches to implementing that, but I think it's better to stick with the documented rule that "An attribute specifier list may appear immediately before the comma, '=' or semicolon terminating the declaration of an identifier...." Anyone disagree? Meanwhile, C++ committee discussion about the lack of any way to apply attributes to a lambda op() seems to have concluded that they should go between the introducer and declarator, so I've implemented that as well. PR c++/90333 PR c++/89640 PR c++/60503 * parser.c (cp_parser_type_specifier_seq): Don't parse attributes in a trailing return type. (cp_parser_lambda_declarator_opt): Parse C++11 attributes before parens. Diff: --- gcc/cp/ChangeLog | 10 ++++++++++ gcc/cp/parser.c | 17 ++++++++++++++++- gcc/testsuite/g++.dg/ext/attr-trailing1.C | 14 ++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3029714..b307583 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2020-01-29 Jason Merrill + + PR c++/90333 + PR c++/89640 + PR c++/60503 + * parser.c (cp_parser_type_specifier_seq): Don't parse attributes in + a trailing return type. + (cp_parser_lambda_declarator_opt): Parse C++11 attributes before + parens. + 2020-01-29 Marek Polacek PR c++/91754 - Fix template arguments comparison with class NTTP. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b832782..bd8e524 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -10962,6 +10962,9 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) ++parser->num_template_parameter_lists; } + /* Committee discussion supports allowing attributes here. */ + lambda_specs.attributes = cp_parser_attributes_opt (parser); + /* The parameter-declaration-clause is optional (unless template-parameter-list was given), but must begin with an opening parenthesis if present. */ @@ -11097,7 +11100,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) fco = grokmethod (&return_type_specs, declarator, - gnu_attrs); + chainon (gnu_attrs, lambda_specs.attributes)); if (fco != error_mark_node) { DECL_INITIALIZED_IN_CLASS_P (fco) = 1; @@ -22277,6 +22280,18 @@ cp_parser_type_specifier_seq (cp_parser* parser, /* Check for attributes first. */ if (cp_next_tokens_can_be_attribute_p (parser)) { + /* GNU attributes at the end of a declaration apply to the + declaration as a whole, not to the trailing return type. So look + ahead to see if these attributes are at the end. */ + if (seen_type_specifier && is_trailing_return + && cp_next_tokens_can_be_gnu_attribute_p (parser)) + { + size_t n = cp_parser_skip_attributes_opt (parser, 1); + cp_token *tok = cp_lexer_peek_nth_token (parser->lexer, n); + if (tok->type == CPP_SEMICOLON || tok->type == CPP_COMMA + || tok->type == CPP_EQ || tok->type == CPP_OPEN_BRACE) + break; + } type_specifier_seq->attributes = attr_chainon (type_specifier_seq->attributes, cp_parser_attributes_opt (parser)); diff --git a/gcc/testsuite/g++.dg/ext/attr-trailing1.C b/gcc/testsuite/g++.dg/ext/attr-trailing1.C new file mode 100644 index 0000000..ff3fb90 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attr-trailing1.C @@ -0,0 +1,14 @@ +// PR c++/90333 +// { dg-do compile { target c++11 } } + +auto l = [] [[nodiscard]] () -> int { return 0; }; +auto l2 = []() -> int __attribute ((warn_unused_result)) { return 0; }; +auto f() -> int __attribute ((warn_unused_result)); +auto f() -> int { return 0; } + +int main() +{ + l(); // { dg-warning "nodiscard" } + l2(); // { dg-warning "unused_result" } + f(); // { dg-warning "unused_result" } +}