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.
This commit is contained in:
parent
165255c7a5
commit
245e40af4f
3 changed files with 40 additions and 1 deletions
|
@ -1,3 +1,13 @@
|
|||
2020-01-29 Jason Merrill <jason@redhat.com>
|
||||
|
||||
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 <polacek@redhat.com>
|
||||
|
||||
PR c++/91754 - Fix template arguments comparison with class NTTP.
|
||||
|
|
|
@ -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));
|
||||
|
|
14
gcc/testsuite/g++.dg/ext/attr-trailing1.C
Normal file
14
gcc/testsuite/g++.dg/ext/attr-trailing1.C
Normal file
|
@ -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" }
|
||||
}
|
Loading…
Add table
Reference in a new issue