From: Jakub Jelinek Date: Thu, 26 Dec 2019 10:16:01 +0000 (+0100) Subject: re PR c++/92438 (Function declaration parsed incorrectly with `-std=c++1z`) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7cd268ad6a6f71877744539d17ed53e752774bfa;p=gcc.git re PR c++/92438 (Function declaration parsed incorrectly with `-std=c++1z`) 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. * g++.dg/ext/attrib61.C: New test. From-SVN: r279736 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 14c6d324580..334438c7c6d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2019-12-26 Jakub Jelinek + + 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 PR c++/92789 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c3c968d9ce4..c66ef34a948 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 1a659dba269..0db2e22e369 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-12-26 Jakub Jelinek + + PR c++/92438 + * g++.dg/ext/attrib61.C: New test. + 2019-12-23 Thomas Schwinge * 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 00000000000..231830616ea --- /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); +}