From 7c2a127e4db1d18116052f15a08641fde6887dc6 Mon Sep 17 00:00:00 2001
From: Iain Sandoe <iain@sandoe.co.uk>
Date: Wed, 9 Oct 2024 09:49:59 +0100
Subject: [PATCH 4/6] c-family: Allow placement of attributes on function
 definitions.

This is to address Issue #12.

It is very unlikely to be acceptable upstream, because the situation
with how GNU attributes appertain is already very complex.  This is
strictly an extension to allow us to consume them in the same position
as clang does.

gcc/c-family/ChangeLog:

	* c.opt:

gcc/c/ChangeLog:

	* c-parser.cc (c_parser_declaration_or_fndef):

gcc/ChangeLog:

	* config/darwin.cc (darwin_override_options):

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_init_declarator):

Signed-off-by: Iain Sandoe <iains@gcc.gnu.org>
(cherry picked from commit f48894008d37635da6f2eae63c072563ca54c3b0)
---
 gcc/c-family/c.opt   |  4 ++++
 gcc/c/c-parser.cc    | 18 ++++++++++++++++--
 gcc/config/darwin.cc |  5 +++++
 gcc/cp/parser.cc     | 13 ++++++++++---
 4 files changed, 35 insertions(+), 5 deletions(-)

diff --git gcc/c-family/c.opt gcc/c-family/c.opt
index c7e662018d5e..61865ff09cb5 100644
--- gcc/c-family/c.opt
+++ gcc/c-family/c.opt
@@ -1643,6 +1643,10 @@ static-libmpxwrappers
 Driver WarnRemoved
 Removed in GCC 9.  This switch has no effect.
 
+fallow-extended-attribute-placement
+C ObjC C++ ObjC++ LTO Var(flag_allow_ext_attr_placement) Init(0)
+Allow placement of attributes on function definitions.
+
 fcilkplus
 C ObjC C++ ObjC++ LTO Undocumented Ignore
 Removed in GCC 8.  This switch has no effect.
diff --git gcc/c/c-parser.cc gcc/c/c-parser.cc
index 5abc6e846977..b158bb2eed0b 100644
--- gcc/c/c-parser.cc
+++ gcc/c/c-parser.cc
@@ -2426,15 +2426,28 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	    d = d->declarator;
 	  underspec_name = d->u.id.id;
 	}
+      tree postfix_attrs = NULL_TREE;
+      if (flag_allow_ext_attr_placement
+	  && c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+	{
+	  postfix_attrs = c_parser_gnu_attributes (parser);
+	  /* IF we have a function definition, and we're allowing it then
+	     treat these attributes as if they had been prepended.  */
+	  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+	    {
+	      all_prefix_attrs = chainon (all_prefix_attrs, postfix_attrs);
+	      postfix_attrs = NULL_TREE;
+	    }
+	}
       if (c_parser_next_token_is (parser, CPP_EQ)
 	  || c_parser_next_token_is (parser, CPP_COMMA)
 	  || c_parser_next_token_is (parser, CPP_SEMICOLON)
 	  || c_parser_next_token_is_keyword (parser, RID_ASM)
 	  || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)
+	  || postfix_attrs
 	  || c_parser_next_token_is_keyword (parser, RID_IN))
 	{
 	  tree asm_name = NULL_TREE;
-	  tree postfix_attrs = NULL_TREE;
 	  if (!diagnosed_no_specs && !specs->declspecs_seen_p)
 	    {
 	      diagnosed_no_specs = true;
@@ -2446,8 +2459,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	  if (c_parser_next_token_is_keyword (parser, RID_ASM))
 	    asm_name = c_parser_simple_asm_expr (parser);
 	  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+	    postfix_attrs = c_parser_gnu_attributes (parser);
+	  if (postfix_attrs)
 	    {
-	      postfix_attrs = c_parser_gnu_attributes (parser);
 	      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
 		{
 		  /* This means there is an attribute specifier after
diff --git gcc/config/darwin.cc gcc/config/darwin.cc
index e95520f2a157..ade374b75316 100644
--- gcc/config/darwin.cc
+++ gcc/config/darwin.cc
@@ -3921,6 +3921,11 @@ darwin_override_options (void)
 
   /* The c_dialect...() macros are not available to us here.  */
   darwin_running_cxx = (strstr (lang_hooks.name, "C++") != 0);
+
+  /* We need to consume attributes on function definitions from the the SDK
+     headers.  */
+  if (!OPTION_SET_P (flag_allow_ext_attr_placement))
+    flag_allow_ext_attr_placement = true;
 }
 
 #if DARWIN_PPC
diff --git gcc/cp/parser.cc gcc/cp/parser.cc
index 1f1b76234b4b..7630fc068ec7 100644
--- gcc/cp/parser.cc
+++ gcc/cp/parser.cc
@@ -22870,9 +22870,16 @@ cp_parser_init_declarator (cp_parser* parser,
 		      "an %<asm%> specification is not allowed "
 		      "on a function-definition");
 	  if (attributes)
-	    error_at (attributes_start_token->location,
-		      "attributes are not allowed "
-		      "on a function-definition");
+	    {
+	      /* When we are allowing attributes in this position, then add
+		 them to the prefix ones.  */
+	      if (flag_allow_ext_attr_placement)
+		prefix_attributes = chainon (prefix_attributes, attributes);
+	      else
+		error_at (attributes_start_token->location,
+			  "attributes are not allowed "
+			  "on a function-definition");
+	    }
 	  /* This is a function-definition.  */
 	  *function_definition_p = true;
 
-- 
2.47.0

