When we apply function attribute to array of function pointer, we
need to rebuild array with the updated function pointer type.

gcc/

        PR c/68637
        * attribs.c (decl_attributes): Rebuid array with the updated
        * function pointer type.

gcc/testsuite/

        PR c/68637
        * gcc.target/i386/pr68637.c: New test.
---
 gcc/attribs.c                           | 18 +++++++++++++++++-
 gcc/testsuite/gcc.target/i386/pr68637.c | 10 ++++++++++
 2 files changed, 27 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr68637.c

diff --git a/gcc/attribs.c b/gcc/attribs.c
index affb21d..0be5ebf 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -494,9 +494,18 @@ decl_attributes (tree *node, tree attributes, int flags)
          flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
        }
 
+      tree array_type = (TREE_CODE (*anode) == ARRAY_TYPE
+                        ? *anode
+                        : NULL_TREE);
+
       if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
          && TREE_CODE (*anode) != METHOD_TYPE)
        {
+         /* We need to rebuid array with the updated function pointer
+            type later. */
+         if (array_type)
+           *anode = TREE_TYPE (*anode);
+
          if (TREE_CODE (*anode) == POINTER_TYPE
              && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
                  || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
@@ -617,7 +626,14 @@ decl_attributes (tree *node, tree attributes, int flags)
          if (fn_ptr_quals)
            fn_ptr_tmp = build_qualified_type (fn_ptr_tmp, fn_ptr_quals);
          if (DECL_P (*node))
-           TREE_TYPE (*node) = fn_ptr_tmp;
+           {
+             if (array_type)
+               TREE_TYPE (*node)
+                 = build_array_type (fn_ptr_tmp,
+                                     TYPE_DOMAIN (array_type));
+             else
+               TREE_TYPE (*node) = fn_ptr_tmp;
+           }
          else
            {
              gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
diff --git a/gcc/testsuite/gcc.target/i386/pr68637.c 
b/gcc/testsuite/gcc.target/i386/pr68637.c
new file mode 100644
index 0000000..c6fc6ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr68637.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -Werror " } */
+
+extern void (*bar[10]) (int, int) __attribute__ ((regparm (2)));
+
+void
+xxx (int i)
+{
+  bar[i] (1, 2);
+}
-- 
2.5.0

Reply via email to