re PR c++/92438 (Function declaration parsed incorrectly with `-std=c++1z`)
authorJakub Jelinek <jakub@redhat.com>
Thu, 26 Dec 2019 10:16:01 +0000 (11:16 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 26 Dec 2019 10:16:01 +0000 (11:16 +0100)
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

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/attrib61.C [new file with mode: 0644]

index 14c6d32..334438c 100644 (file)
@@ -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
index c3c968d..c66ef34 100644 (file)
@@ -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)
index 1a659db..0db2e22 100644 (file)
@@ -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 (file)
index 0000000..2318306
--- /dev/null
@@ -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);
+}