diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 14c6d324580727665a4b6cf1119a45b23906cdf9..334438c7c6db312e9b53c9dbba9418c40f4d5748 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2019-12-26 Jakub Jelinek <jakub@redhat.com> + + PR c++/92438 + * parser.c (cp_parser_constructor_declarator_p): If open paren + is followed by RID_ATTRIBUTE, skip over the attribute tokens and + try to parse type specifier. + 2019-12-23 Richard Sandiford <richard.sandiford@arm.com> PR c++/92789 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c3c968d9ce413e638f3c22635a1dbc8a45c12aa3..c66ef34a948593ea7fc70b12c9ca8de013064a1d 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -28493,7 +28493,15 @@ cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags, /* A parameter declaration begins with a decl-specifier, which is either the "attribute" keyword, a storage class specifier, or (usually) a type-specifier. */ - && !cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer) + && (!cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer) + /* GNU attributes can actually appear both at the start of + a parameter and parenthesized declarator. + S (__attribute__((unused)) int); + is a constructor, but + S (__attribute__((unused)) foo) (int); + is a function declaration. */ + || (cp_parser_allow_gnu_extensions_p (parser) + && cp_next_tokens_can_be_gnu_attribute_p (parser))) /* A parameter declaration can also begin with [[attribute]]. */ && !cp_next_tokens_can_be_std_attribute_p (parser)) { @@ -28501,6 +28509,13 @@ cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags, tree pushed_scope = NULL_TREE; unsigned saved_num_template_parameter_lists; + if (cp_next_tokens_can_be_gnu_attribute_p (parser)) + { + unsigned int n = cp_parser_skip_gnu_attributes_opt (parser, 1); + while (--n) + cp_lexer_consume_token (parser->lexer); + } + /* Names appearing in the type-specifier should be looked up in the scope of the class. */ if (current_class_type) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1a659dba269111c41431b5a5c4a90e164481c0a9..0db2e22e369efeb8347db5791e73a804036b545e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-12-26 Jakub Jelinek <jakub@redhat.com> + + PR c++/92438 + * g++.dg/ext/attrib61.C: New test. + 2019-12-23 Thomas Schwinge <thomas@codesourcery.com> * c-c++-common/goacc/mdc-1.c: Restrict to LP64, LLP64. diff --git a/gcc/testsuite/g++.dg/ext/attrib61.C b/gcc/testsuite/g++.dg/ext/attrib61.C new file mode 100644 index 0000000000000000000000000000000000000000..231830616ea34f07779756587349eabe130983e8 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attrib61.C @@ -0,0 +1,26 @@ +// PR c++/92438 +// { dg-do compile } + +typedef struct S { int x; } T; +T (foo) (T x); +T __attribute__((unused)) bar (T x); +struct S (__attribute__((unused)) baz) (T x); +T (__attribute__((unused)) qux) (T x); + +struct U +{ + U (__attribute__((unused)) int); + U (__attribute__((unused)) corge) (int); +}; + +void +test () +{ + T a, b; + a = foo (b); + b = bar (a); + a = baz (b); + b = qux (a); + U u (5); + U v = u.corge (3); +}