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.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f0e314f..13601ce 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,6 +1,16 @@
 2020-01-22  Jakub Jelinek  <jakub@redhat.com>
 
 	Backported from mainline
+	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.
+
+2020-01-22  Jakub Jelinek  <jakub@redhat.com>
+
+	Backported from mainline
 	2019-12-20  Jakub Jelinek  <jakub@redhat.com>
 
 	PR c++/92992
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4df5d57..54b3522 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -27619,7 +27619,15 @@
 	  /* 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))
 	{
@@ -27627,6 +27635,13 @@
 	  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 2e507fd..c306cf6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,6 +1,14 @@
 2020-01-22  Jakub Jelinek  <jakub@redhat.com>
 
 	Backported from mainline
+	2019-12-26  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c++/92438
+	* g++.dg/ext/attrib61.C: New test.
+
+2020-01-22  Jakub Jelinek  <jakub@redhat.com>
+
+	Backported from mainline
 	2019-12-20  Jakub Jelinek  <jakub@redhat.com>
 
 	PR c++/92992
diff --git a/gcc/testsuite/g++.dg/ext/attrib61.C b/gcc/testsuite/g++.dg/ext/attrib61.C
new file mode 100644
index 0000000..2318306
--- /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);
+}