]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Allow target attributes in non-gnu namespaces
authorRichard Sandiford <richard.sandiford@arm.com>
Sat, 2 Dec 2023 13:49:52 +0000 (13:49 +0000)
committerRichard Sandiford <richard.sandiford@arm.com>
Sat, 2 Dec 2023 13:49:52 +0000 (13:49 +0000)
Currently there are four static sources of attributes:

- LANG_HOOKS_ATTRIBUTE_TABLE
- LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
- LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
- TARGET_ATTRIBUTE_TABLE

All of the attributes in these tables go in the "gnu" namespace.
This means that they can use the traditional GNU __attribute__((...))
syntax and the standard [[gnu::...]] syntax.

Standard attributes are registered dynamically with a null namespace.
There are no supported attributes in other namespaces (clang, vendor
namespaces, etc.).

This patch tries to generalise things by making the namespace
part of the attribute specification.

It's usual for multiple attributes to be defined in the same namespace,
so rather than adding the namespace to each individual definition,
it seemed better to group attributes in the same namespace together.
This would also allow us to reuse the same table for clang attributes
that are written with the GNU syntax, or other similar situations
where the attribute can be accessed via multiple "spellings".

The patch therefore adds a scoped_attribute_specs that contains
a namespace and a list of attributes in that namespace.

It's still possible to have multiple scoped_attribute_specs
for the same namespace.  E.g. it makes sense to keep the
C++-specific, C/C++-common, and format-related attributes in
separate tables, even though they're all GNU attributes.

Current lists of attributes are terminated by a null name.
Rather than keep that for the new structure, it seemed neater
to use an array_slice.  This also makes the tables slighly more
compact.

In general, a target might want to support attributes in multiple
namespaces.  Rather than have a separate hook for each possibility
(like the three langhooks above), it seemed better to make
TARGET_ATTRIBUTE_TABLE a table of tables.  Specifically, it's
an array_slice of scoped_attribute_specs.

We can do the same thing for langhooks, which allows the three hooks
above to be merged into a single LANG_HOOKS_ATTRIBUTE_TABLE.
It also allows the standard attributes to be registered statically
and checked by the usual attribs.cc checks.

The patch adds a TARGET_GNU_ATTRIBUTES helper for the common case
in which a target wants a single table of gnu attributes.  It can
only be used if the table is free of preprocessor directives.

There are probably other things we need to do to make vendor namespaces
work smoothly.  E.g. in principle it would be good to make exclusion
sets namespace-aware.  But to some extent we have that with standard
vs. gnu attributes too.  This patch is just supposed to be a first step.

gcc/
* attribs.h (scoped_attribute_specs): New structure.
(register_scoped_attributes): Take a reference to a
scoped_attribute_specs instead of separate namespace and array
parameters.
* plugin.h (register_scoped_attributes): Likewise.
* attribs.cc (register_scoped_attributes): Likewise.
(attribute_tables): Change into an array of scoped_attribute_specs
pointers.  Reduce to 1 element for frontends and 1 element for targets.
(empty_attribute_table): Delete.
(check_attribute_tables): Update for changes to attribute_tables.
Use a hash_set to identify duplicates.
(handle_ignored_attributes_option): Update for above changes.
(init_attributes): Likewise.
(excl_pair): Delete.
(test_attribute_exclusions): Update for above changes.  Don't
enforce symmetry for standard attributes in the top-level namespace.
* langhooks-def.h (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Delete.
(LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Likewise.
(LANG_HOOKS_INITIALIZER): Update accordingly.
(LANG_HOOKS_ATTRIBUTE_TABLE): Define to an empty constructor.
* langhooks.h (lang_hooks::common_attribute_table): Delete.
(lang_hooks::format_attribute_table): Likewise.
(lang_hooks::attribute_table): Redefine to an array of
scoped_attribute_specs pointers.
* target-def.h (TARGET_GNU_ATTRIBUTES): New macro.
* target.def (attribute_spec): Redefine to return an array of
scoped_attribute_specs pointers.
* tree-inline.cc (function_attribute_inlinable_p): Update accordingly.
* doc/tm.texi: Regenerate.
* config/aarch64/aarch64.cc (aarch64_attribute_table): Define using
TARGET_GNU_ATTRIBUTES.
* config/alpha/alpha.cc (vms_attribute_table): Likewise.
* config/avr/avr.cc (avr_attribute_table): Likewise.
* config/bfin/bfin.cc (bfin_attribute_table): Likewise.
* config/bpf/bpf.cc (bpf_attribute_table): Likewise.
* config/csky/csky.cc (csky_attribute_table): Likewise.
* config/epiphany/epiphany.cc (epiphany_attribute_table): Likewise.
* config/gcn/gcn.cc (gcn_attribute_table): Likewise.
* config/h8300/h8300.cc (h8300_attribute_table): Likewise.
* config/loongarch/loongarch.cc (loongarch_attribute_table): Likewise.
* config/m32c/m32c.cc (m32c_attribute_table): Likewise.
* config/m32r/m32r.cc (m32r_attribute_table): Likewise.
* config/m68k/m68k.cc (m68k_attribute_table): Likewise.
* config/mcore/mcore.cc (mcore_attribute_table): Likewise.
* config/microblaze/microblaze.cc (microblaze_attribute_table):
Likewise.
* config/mips/mips.cc (mips_attribute_table): Likewise.
* config/msp430/msp430.cc (msp430_attribute_table): Likewise.
* config/nds32/nds32.cc (nds32_attribute_table): Likewise.
* config/nvptx/nvptx.cc (nvptx_attribute_table): Likewise.
* config/riscv/riscv.cc (riscv_attribute_table): Likewise.
* config/rl78/rl78.cc (rl78_attribute_table): Likewise.
* config/rx/rx.cc (rx_attribute_table): Likewise.
* config/s390/s390.cc (s390_attribute_table): Likewise.
* config/sh/sh.cc (sh_attribute_table): Likewise.
* config/sparc/sparc.cc (sparc_attribute_table): Likewise.
* config/stormy16/stormy16.cc (xstormy16_attribute_table): Likewise.
* config/v850/v850.cc (v850_attribute_table): Likewise.
* config/visium/visium.cc (visium_attribute_table): Likewise.
* config/arc/arc.cc (arc_attribute_table): Likewise.  Move further
down file.
* config/arm/arm.cc (arm_attribute_table): Update for above changes,
using...
(arm_gnu_attributes, arm_gnu_attribute_table): ...these new globals.
* config/i386/i386-options.h (ix86_attribute_table): Delete.
(ix86_gnu_attribute_table): Declare.
* config/i386/i386-options.cc (ix86_attribute_table): Replace with...
(ix86_gnu_attributes, ix86_gnu_attribute_table): ...these two globals.
* config/i386/i386.cc (ix86_attribute_table): Define as an array of
scoped_attribute_specs pointers.
* config/ia64/ia64.cc (ia64_attribute_table): Update for above changes,
using...
(ia64_gnu_attributes, ia64_gnu_attribute_table): ...these new globals.
* config/rs6000/rs6000.cc (rs6000_attribute_table): Update for above
changes, using...
(rs6000_gnu_attributes, rs6000_gnu_attribute_table): ...these new
globals.

gcc/ada/
* gcc-interface/gigi.h (gnat_internal_attribute_table): Change
type to scoped_attribute_specs.
* gcc-interface/utils.cc (gnat_internal_attribute_table): Likewise,
using...
(gnat_internal_attributes): ...this as the underlying array.
* gcc-interface/misc.cc (gnat_attribute_table): New global.
(LANG_HOOKS_ATTRIBUTE_TABLE): Use it.

gcc/c-family/
* c-common.h (c_common_attribute_table): Replace with...
(c_common_gnu_attribute_table): ...this.
(c_common_format_attribute_table): Change type to
scoped_attribute_specs.
* c-attribs.cc (c_common_attribute_table): Replace with...
(c_common_gnu_attributes, c_common_gnu_attribute_table): ...these
new globals.
(c_common_format_attribute_table): Change type to
scoped_attribute_specs, using...
(c_common_format_attributes): ...this as the underlying array.

gcc/c/
* c-tree.h (std_attribute_table): Declare.
* c-decl.cc (std_attribute_table): Change type to
scoped_attribute_specs, using...
(std_attributes): ...this as the underlying array.
(c_init_decl_processing): Remove call to register_scoped_attributes.
* c-objc-common.h (c_objc_attribute_table): New global.
(LANG_HOOKS_ATTRIBUTE_TABLE): Use it.
(LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Delete.
(LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Delete.

gcc/cp/
* cp-tree.h (cxx_attribute_table): Delete.
(cxx_gnu_attribute_table, std_attribute_table): Declare.
* cp-objcp-common.h (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Delete.
(LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Delete.
(cp_objcp_attribute_table): New table.
(LANG_HOOKS_ATTRIBUTE_TABLE): Redefine.
* tree.cc (cxx_attribute_table): Replace with...
(cxx_gnu_attributes, cxx_gnu_attribute_table): ...these globals.
(std_attribute_table): Change type to scoped_attribute_specs, using...
(std_attributes): ...this as the underlying array.
(init_tree): Remove call to register_scoped_attributes.

gcc/d/
* d-tree.h (d_langhook_attribute_table): Replace with...
(d_langhook_gnu_attribute_table): ...this.
(d_langhook_common_attribute_table): Change type to
scoped_attribute_specs.
* d-attribs.cc (d_langhook_common_attribute_table): Change type to
scoped_attribute_specs, using...
(d_langhook_common_attributes): ...this as the underlying array.
(d_langhook_attribute_table): Replace with...
(d_langhook_gnu_attributes, d_langhook_gnu_attribute_table): ...these
new globals.
(uda_attribute_p): Update accordingly, and update for new
targetm.attribute_table type.
* d-lang.cc (d_langhook_attribute_table): New global.
(LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Delete.

gcc/fortran/
* f95-lang.cc: Include attribs.h.
(gfc_attribute_table): Change to an array of scoped_attribute_specs
pointers, using...
(gfc_gnu_attributes, gfc_gnu_attribute_table): ...these new globals.

gcc/jit/
* dummy-frontend.cc (jit_format_attribute_table): Change type to
scoped_attribute_specs, using...
(jit_format_attributes): ...this as the underlying array.
(jit_attribute_table): Change to an array of scoped_attribute_specs
pointers, using...
(jit_gnu_attributes, jit_gnu_attribute_table): ...these new globals
for the original array.  Include the format attributes.
(LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Delete.
(LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Delete.
(LANG_HOOKS_ATTRIBUTE_TABLE): Define.

gcc/lto/
* lto-lang.cc (lto_format_attribute_table): Change type to
scoped_attribute_specs, using...
(lto_format_attributes): ...this as the underlying array.
(lto_attribute_table): Change to an array of scoped_attribute_specs
pointers, using...
(lto_gnu_attributes, lto_gnu_attribute_table): ...these new globals
for the original array.  Include the format attributes.
(LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Delete.
(LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Delete.
(LANG_HOOKS_ATTRIBUTE_TABLE): Define.

61 files changed:
gcc/ada/gcc-interface/gigi.h
gcc/ada/gcc-interface/misc.cc
gcc/ada/gcc-interface/utils.cc
gcc/attribs.cc
gcc/attribs.h
gcc/c-family/c-attribs.cc
gcc/c-family/c-common.h
gcc/c/c-decl.cc
gcc/c/c-objc-common.h
gcc/c/c-tree.h
gcc/config/aarch64/aarch64.cc
gcc/config/alpha/alpha.cc
gcc/config/arc/arc.cc
gcc/config/arm/arm.cc
gcc/config/avr/avr.cc
gcc/config/bfin/bfin.cc
gcc/config/bpf/bpf.cc
gcc/config/csky/csky.cc
gcc/config/epiphany/epiphany.cc
gcc/config/gcn/gcn.cc
gcc/config/h8300/h8300.cc
gcc/config/i386/i386-options.cc
gcc/config/i386/i386-options.h
gcc/config/i386/i386.cc
gcc/config/ia64/ia64.cc
gcc/config/loongarch/loongarch.cc
gcc/config/m32c/m32c.cc
gcc/config/m32r/m32r.cc
gcc/config/m68k/m68k.cc
gcc/config/mcore/mcore.cc
gcc/config/microblaze/microblaze.cc
gcc/config/mips/mips.cc
gcc/config/msp430/msp430.cc
gcc/config/nds32/nds32.cc
gcc/config/nvptx/nvptx.cc
gcc/config/riscv/riscv.cc
gcc/config/rl78/rl78.cc
gcc/config/rs6000/rs6000.cc
gcc/config/rx/rx.cc
gcc/config/s390/s390.cc
gcc/config/sh/sh.cc
gcc/config/sparc/sparc.cc
gcc/config/stormy16/stormy16.cc
gcc/config/v850/v850.cc
gcc/config/visium/visium.cc
gcc/cp/cp-objcp-common.h
gcc/cp/cp-tree.h
gcc/cp/tree.cc
gcc/d/d-attribs.cc
gcc/d/d-lang.cc
gcc/d/d-tree.h
gcc/doc/tm.texi
gcc/fortran/f95-lang.cc
gcc/jit/dummy-frontend.cc
gcc/langhooks-def.h
gcc/langhooks.h
gcc/lto/lto-lang.cc
gcc/plugin.h
gcc/target-def.h
gcc/target.def
gcc/tree-inline.cc

index eb5496f50db80057693467de2e7cb36caf16b1cf..63ccf311c233974db6ad39513cf1989c7597c283 100644 (file)
@@ -350,7 +350,7 @@ struct attrib
 };
 
 /* Table of machine-independent internal attributes.  */
-extern const struct attribute_spec gnat_internal_attribute_table[];
+extern const struct scoped_attribute_specs gnat_internal_attribute_table;
 
 /* Define the entries in the standard data array.  */
 enum standard_datatypes
index 7d6d4466d5646064b12c6783aaaf5c84b099e967..01e8267f88496cbd0274ed5e06f41b2b30a97384 100644 (file)
@@ -1352,6 +1352,11 @@ get_lang_specific (tree node)
   return TYPE_LANG_SPECIFIC (node);
 }
 
+const struct scoped_attribute_specs *const gnat_attribute_table[] =
+{
+  &gnat_internal_attribute_table
+};
+
 /* Definitions for our language-specific hooks.  */
 
 #undef  LANG_HOOKS_NAME
@@ -1417,7 +1422,7 @@ get_lang_specific (tree node)
 #undef  LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO
 #define LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO gnat_get_fixed_point_type_info
 #undef  LANG_HOOKS_ATTRIBUTE_TABLE
-#define LANG_HOOKS_ATTRIBUTE_TABLE     gnat_internal_attribute_table
+#define LANG_HOOKS_ATTRIBUTE_TABLE     gnat_attribute_table
 #undef  LANG_HOOKS_BUILTIN_FUNCTION
 #define LANG_HOOKS_BUILTIN_FUNCTION    gnat_builtin_function
 #undef  LANG_HOOKS_INIT_TS
index e7b5c7783b1f1c702130c8879c79b7e329764b09..f46454d6545a2e8dd7b1ac926d94526e235a0194 100644 (file)
@@ -136,7 +136,7 @@ static tree fake_attribute_handler (tree *, tree, tree, int, bool *);
 
 /* Table of machine-independent internal attributes for Ada.  We support
    this minimal set of attributes to accommodate the needs of builtins.  */
-const struct attribute_spec gnat_internal_attribute_table[] =
+static const attribute_spec gnat_internal_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -217,9 +217,11 @@ const struct attribute_spec gnat_internal_attribute_table[] =
   /* This is handled entirely in the front end.  */
   { "hardbool",     0, 0,  false, true, false, true,
     fake_attribute_handler, NULL },
+};
 
-  { NULL,           0, 0,  false, false, false, false,
-    NULL, NULL }
+const scoped_attribute_specs gnat_internal_attribute_table =
+{
+  "gnu", gnat_internal_attributes
 };
 
 /* Associates a GNAT tree node to a GCC tree node. It is used in
index c7209c26acc9faf699774b0ef669ec6748b9073d..8ad9b3b234903cfd0d0d5b0bdc59d1fcc65fd0eb 100644 (file)
@@ -39,7 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Table of the tables of attributes (common, language, format, machine)
    searched.  */
-static const struct attribute_spec *attribute_tables[4];
+static array_slice<const scoped_attribute_specs *const> attribute_tables[2];
 
 /* Substring representation.  */
 
@@ -102,13 +102,6 @@ static const struct attribute_spec *lookup_scoped_attribute_spec (const_tree,
 
 static bool attributes_initialized = false;
 
-/* Default empty table of attributes.  */
-
-static const struct attribute_spec empty_attribute_table[] =
-{
-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
-};
-
 /* Return base name of the attribute.  Ie '__attr__' is turned into 'attr'.
    To avoid need for copying, we simply return length of the string.  */
 
@@ -118,21 +111,19 @@ extract_attribute_substring (struct substring *str)
   canonicalize_attr_name (str->str, str->length);
 }
 
-/* Insert an array of attributes ATTRIBUTES into a namespace.  This
-   array must be NULL terminated.  NS is the name of attribute
-   namespace.  IGNORED_P is true iff all unknown attributes in this
-   namespace should be ignored for the purposes of -Wattributes.  The
-   function returns the namespace into which the attributes have been
-   registered.  */
+/* Insert SPECS into its namespace.  IGNORED_P is true iff all unknown
+   attributes in this namespace should be ignored for the purposes of
+   -Wattributes.  The function returns the namespace into which the
+   attributes have been registered.  */
 
 scoped_attributes *
-register_scoped_attributes (const struct attribute_spec *attributes,
-                           const char *ns, bool ignored_p /*=false*/)
+register_scoped_attributes (const scoped_attribute_specs &specs,
+                           bool ignored_p /*=false*/)
 {
   scoped_attributes *result = NULL;
 
   /* See if we already have attributes in the namespace NS.  */
-  result = find_attribute_namespace (ns);
+  result = find_attribute_namespace (specs.ns);
 
   if (result == NULL)
     {
@@ -143,7 +134,7 @@ register_scoped_attributes (const struct attribute_spec *attributes,
        attributes_table.create (64);
 
       memset (&sa, 0, sizeof (sa));
-      sa.ns = ns;
+      sa.ns = specs.ns;
       sa.attributes.create (64);
       sa.ignored_p = ignored_p;
       result = attributes_table.safe_push (sa);
@@ -153,10 +144,10 @@ register_scoped_attributes (const struct attribute_spec *attributes,
     result->ignored_p |= ignored_p;
 
   /* Really add the attributes to their namespace now.  */
-  for (unsigned i = 0; attributes[i].name != NULL; ++i)
+  for (const attribute_spec &attribute : specs.attributes)
     {
-      result->attributes.safe_push (attributes[i]);
-      register_scoped_attribute (&attributes[i], result);
+      result->attributes.safe_push (attribute);
+      register_scoped_attribute (&attribute, result);
     }
 
   gcc_assert (result != NULL);
@@ -183,49 +174,40 @@ find_attribute_namespace (const char* ns)
 static void
 check_attribute_tables (void)
 {
-  for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
-    for (size_t j = 0; attribute_tables[i][j].name != NULL; j++)
-      {
-       /* The name must not begin and end with __.  */
-       const char *name = attribute_tables[i][j].name;
-       int len = strlen (name);
+  hash_set<pair_hash<nofree_string_hash, nofree_string_hash>> names;
 
-       gcc_assert (!(name[0] == '_' && name[1] == '_'
-                     && name[len - 1] == '_' && name[len - 2] == '_'));
+  for (auto scoped_array : attribute_tables)
+    for (auto scoped_attributes : scoped_array)
+      for (const attribute_spec &attribute : scoped_attributes->attributes)
+       {
+         /* The name must not begin and end with __.  */
+         const char *name = attribute.name;
+         int len = strlen (name);
+
+         gcc_assert (!(name[0] == '_' && name[1] == '_'
+                       && name[len - 1] == '_' && name[len - 2] == '_'));
 
-       /* The minimum and maximum lengths must be consistent.  */
-       gcc_assert (attribute_tables[i][j].min_length >= 0);
+         /* The minimum and maximum lengths must be consistent.  */
+         gcc_assert (attribute.min_length >= 0);
 
-       gcc_assert (attribute_tables[i][j].max_length == -1
-                   || (attribute_tables[i][j].max_length
-                       >= attribute_tables[i][j].min_length));
+         gcc_assert (attribute.max_length == -1
+                     || attribute.max_length >= attribute.min_length);
 
-       /* An attribute cannot require both a DECL and a TYPE.  */
-       gcc_assert (!attribute_tables[i][j].decl_required
-                   || !attribute_tables[i][j].type_required);
+         /* An attribute cannot require both a DECL and a TYPE.  */
+         gcc_assert (!attribute.decl_required
+                     || !attribute.type_required);
 
          /* If an attribute requires a function type, in particular
             it requires a type.  */
-       gcc_assert (!attribute_tables[i][j].function_type_required
-                   || attribute_tables[i][j].type_required);
-      }
-
-  /* Check that each name occurs just once in each table.  */
-  for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
-    for (size_t j = 0; attribute_tables[i][j].name != NULL; j++)
-      for (size_t k = j + 1; attribute_tables[i][k].name != NULL; k++)
-       gcc_assert (strcmp (attribute_tables[i][j].name,
-                           attribute_tables[i][k].name));
-
-  /* Check that no name occurs in more than one table.  Names that
-     begin with '*' are exempt, and may be overridden.  */
-  for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
-    for (size_t j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
-      for (size_t k = 0; attribute_tables[i][k].name != NULL; k++)
-       for (size_t l = 0; attribute_tables[j][l].name != NULL; l++)
-         gcc_assert (attribute_tables[i][k].name[0] == '*'
-                     || strcmp (attribute_tables[i][k].name,
-                                attribute_tables[j][l].name));
+         gcc_assert (!attribute.function_type_required
+                     || attribute.type_required);
+
+         /* Check that no name occurs more than once.  Names that
+            begin with '*' are exempt, and may be overridden.  */
+         const char *ns = scoped_attributes->ns;
+         if (name[0] != '*' && names.add ({ ns ? ns : "", name }))
+           gcc_unreachable ();
+       }
 }
 
 /* Used to stash pointers to allocated memory so that we can free them at
@@ -281,7 +263,7 @@ handle_ignored_attributes_option (vec<char *> *v)
       canonicalize_attr_name (vendor_start, vendor_len);
       /* We perform all this hijinks so that we don't have to copy OPT.  */
       tree vendor_id = get_identifier_with_length (vendor_start, vendor_len);
-      const char *attr;
+      array_slice<const attribute_spec> attrs;
       /* In the "vendor::" case, we should ignore *any* attribute coming
         from this attribute namespace.  */
       if (attr_len > 0)
@@ -293,22 +275,23 @@ handle_ignored_attributes_option (vec<char *> *v)
            }
          canonicalize_attr_name (attr_start, attr_len);
          tree attr_id = get_identifier_with_length (attr_start, attr_len);
-         attr = IDENTIFIER_POINTER (attr_id);
+         const char *attr = IDENTIFIER_POINTER (attr_id);
          /* If we've already seen this vendor::attr, ignore it.  Attempting to
             register it twice would lead to a crash.  */
          if (lookup_scoped_attribute_spec (vendor_id, attr_id))
            continue;
+         /* Create a table with extra attributes which we will register.
+            We can't free it here, so squirrel away the pointers.  */
+         attribute_spec *table = new attribute_spec {
+           attr, 0, -2, false, false, false, false, nullptr, nullptr
+         };
+         ignored_attributes_table.safe_push (table);
+         attrs = { table, 1 };
        }
-      else
-       attr = nullptr;
-      /* Create a table with extra attributes which we will register.
-        We can't free it here, so squirrel away the pointers.  */
-      attribute_spec *table = new attribute_spec[2];
-      ignored_attributes_table.safe_push (table);
-      table[0] = { attr, 0, -2, false, false, false, false, nullptr, nullptr };
-      table[1] = { nullptr, 0, 0, false, false, false, false, nullptr,
-                  nullptr };
-      register_scoped_attributes (table, IDENTIFIER_POINTER (vendor_id), !attr);
+      const scoped_attribute_specs scoped_specs = {
+       IDENTIFIER_POINTER (vendor_id), attrs
+      };
+      register_scoped_attributes (scoped_specs, attrs.empty ());
     }
 }
 
@@ -328,27 +311,18 @@ free_attr_data ()
 void
 init_attributes (void)
 {
-  size_t i;
-
   if (attributes_initialized)
     return;
 
-  attribute_tables[0] = lang_hooks.common_attribute_table;
-  attribute_tables[1] = lang_hooks.attribute_table;
-  attribute_tables[2] = lang_hooks.format_attribute_table;
-  attribute_tables[3] = targetm.attribute_table;
-
-  /* Translate NULL pointers to pointers to the empty table.  */
-  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
-    if (attribute_tables[i] == NULL)
-      attribute_tables[i] = empty_attribute_table;
+  attribute_tables[0] = lang_hooks.attribute_table;
+  attribute_tables[1] = targetm.attribute_table;
 
   if (flag_checking)
     check_attribute_tables ();
 
-  for (i = 0; i < ARRAY_SIZE (attribute_tables); ++i)
-    /* Put all the GNU attributes into the "gnu" namespace.  */
-    register_scoped_attributes (attribute_tables[i], "gnu");
+  for (auto scoped_array : attribute_tables)
+    for (auto scoped_attributes : scoped_array)
+      register_scoped_attributes (*scoped_attributes);
 
   vec<char *> *ignored = (vec<char *> *) flag_ignored_attributes;
   handle_ignored_attributes_option (ignored);
@@ -2645,10 +2619,6 @@ attr_access::array_as_string (tree type) const
 namespace selftest
 {
 
-/* Helper types to verify the consistency attribute exclusions.  */
-
-typedef std::pair<const char *, const char *> excl_pair;
-
 /* Self-test to verify that each attribute exclusion is symmetric,
    meaning that if attribute A is encoded as incompatible with
    attribute B then the opposite relationship is also encoded.
@@ -2663,55 +2633,54 @@ test_attribute_exclusions ()
   /* Iterate over the array of attribute tables first (with TI0 as
      the index) and over the array of attribute_spec in each table
      (with SI0 as the index).  */
-  const size_t ntables = ARRAY_SIZE (attribute_tables);
+  hash_set<excl_hash_traits> excl_set;
 
-  /* Set of pairs of mutually exclusive attributes.  */
-  typedef hash_set<excl_hash_traits> exclusion_set;
-  exclusion_set excl_set;
+  for (auto scoped_array : attribute_tables)
+    for (auto scoped_attributes : scoped_array)
+      for (const attribute_spec &attribute : scoped_attributes->attributes)
+       {
+         const attribute_spec::exclusions *excl = attribute.exclude;
 
-  for (size_t ti0 = 0; ti0 != ntables; ++ti0)
-    for (size_t s0 = 0; attribute_tables[ti0][s0].name; ++s0)
-      {
-       const attribute_spec::exclusions *excl
-         = attribute_tables[ti0][s0].exclude;
+         /* Skip each attribute that doesn't define exclusions.  */
+         if (!excl)
+           continue;
 
-       /* Skip each attribute that doesn't define exclusions.  */
-       if (!excl)
-         continue;
+         /* Skip standard (non-GNU) attributes, since currently the
+            exclusions are implicitly for GNU attributes only.
+            Also, C++ likely and unlikely get rewritten to gnu::hot
+            and gnu::cold, so symmetry isn't necessary there.  */
+         if (!scoped_attributes->ns)
+           continue;
 
-       const char *attr_name = attribute_tables[ti0][s0].name;
+         const char *attr_name = attribute.name;
 
-       /* Iterate over the set of exclusions for every attribute
-          (with EI0 as the index) adding the exclusions defined
-          for each to the set.  */
-       for (size_t ei0 = 0; excl[ei0].name; ++ei0)
-         {
-           const char *excl_name = excl[ei0].name;
+         /* Iterate over the set of exclusions for every attribute
+            (with EI0 as the index) adding the exclusions defined
+            for each to the set.  */
+         for (size_t ei0 = 0; excl[ei0].name; ++ei0)
+           {
+             const char *excl_name = excl[ei0].name;
 
-           if (!strcmp (attr_name, excl_name))
-             continue;
+             if (!strcmp (attr_name, excl_name))
+               continue;
 
-           excl_set.add (excl_pair (attr_name, excl_name));
-         }
-      }
+             excl_set.add ({ attr_name, excl_name });
+           }
+       }
 
   /* Traverse the set of mutually exclusive pairs of attributes
      and verify that they are symmetric.  */
-  for (exclusion_set::iterator it = excl_set.begin ();
-       it != excl_set.end ();
-       ++it)
-    {
-      if (!excl_set.contains (excl_pair ((*it).second, (*it).first)))
-       {
-         /* An exclusion for an attribute has been found that
-            doesn't have a corresponding exclusion in the opposite
-            direction.  */
-         char desc[120];
-         sprintf (desc, "'%s' attribute exclusion '%s' must be symmetric",
-                  (*it).first, (*it).second);
-         fail (SELFTEST_LOCATION, desc);
-       }
-    }
+  for (auto excl_pair : excl_set)
+    if (!excl_set.contains ({ excl_pair.second, excl_pair.first }))
+      {
+       /* An exclusion for an attribute has been found that
+          doesn't have a corresponding exclusion in the opposite
+          direction.  */
+       char desc[120];
+       sprintf (desc, "'%s' attribute exclusion '%s' must be symmetric",
+                excl_pair.first, excl_pair.second);
+       fail (SELFTEST_LOCATION, desc);
+      }
 }
 
 void
index 84a43658a70dab576c212491df234aa1049016fc..fdeebff1cd98691b4064287af52988f556ea2aec 100644 (file)
@@ -20,6 +20,13 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ATTRIBS_H
 #define GCC_ATTRIBS_H
 
+/* A set of attributes that belong to the same namespace, given by NS.  */
+struct scoped_attribute_specs
+{
+  const char *ns;
+  array_slice<const attribute_spec> attributes;
+};
+
 extern const struct attribute_spec *lookup_attribute_spec (const_tree);
 extern void free_attr_data ();
 extern void init_attributes (void);
@@ -42,9 +49,8 @@ extern tree make_attribute (const char *, const char *, tree);
 extern bool attribute_ignored_p (tree);
 extern bool attribute_ignored_p (const attribute_spec *const);
 
-extern struct scoped_attributes* register_scoped_attributes (const struct attribute_spec *,
-                                                            const char *,
-                                                            bool = false);
+extern struct scoped_attributes *
+  register_scoped_attributes (const scoped_attribute_specs &, bool = false);
 
 extern char *sorted_attr_string (tree);
 extern bool common_function_versions (tree, tree);
index 2b20e58c922c8acb6021f24bea9fb089b6ec2ab0..45af07453ea3c0c60fb4d291b3ebfff545bb0643 100644 (file)
@@ -289,7 +289,7 @@ static const struct attribute_spec::exclusions attr_stack_protect_exclusions[] =
 /* Table of machine-independent attributes common to all C-like languages.
 
    Current list of processed common attributes: nonnull.  */
-const struct attribute_spec c_common_attribute_table[] =
+const struct attribute_spec c_common_gnu_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -579,23 +579,31 @@ const struct attribute_spec c_common_attribute_table[] =
   { "fd_arg_write",       1, 1, false, true, true, false,
             handle_fd_arg_attribute, NULL},         
   { "null_terminated_string_arg", 1, 1, false, true, true, false,
-                             handle_null_terminated_string_arg_attribute, NULL},
-  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
+                             handle_null_terminated_string_arg_attribute, NULL}
+};
+
+const struct scoped_attribute_specs c_common_gnu_attribute_table =
+{
+  "gnu", c_common_gnu_attributes
 };
 
 /* Give the specifications for the format attributes, used by C and all
    descendants.
 
    Current list of processed format attributes: format, format_arg.  */
-const struct attribute_spec c_common_format_attribute_table[] =
+const struct attribute_spec c_common_format_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
   { "format",                 3, 3, false, true,  true, false,
                              handle_format_attribute, NULL },
   { "format_arg",             1, 1, false, true,  true, false,
-                             handle_format_arg_attribute, NULL },
-  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
+                             handle_format_arg_attribute, NULL }
+};
+
+const struct scoped_attribute_specs c_common_format_attribute_table =
+{
+  "gnu", c_common_format_attributes
 };
 
 /* Returns TRUE iff the attribute indicated by ATTR_ID takes a plain
index 3f772dbcca11ec3a296693036a8651f23e7ab3ed..cb9b6f301d8752f460209c0faa0c02765a1f4ebf 100644 (file)
@@ -821,8 +821,8 @@ enum conversion_safety {
 extern struct visibility_flags visibility_options;
 
 /* Attribute table common to the C front ends.  */
-extern const struct attribute_spec c_common_attribute_table[];
-extern const struct attribute_spec c_common_format_attribute_table[];
+extern const struct scoped_attribute_specs c_common_gnu_attribute_table;
+extern const struct scoped_attribute_specs c_common_format_attribute_table;
 
 /* Pointer to function to lazily generate the VAR_DECL for __FUNCTION__ etc.
    ID is the identifier to use, NAME is the string.
index d388e123704406e6bb1cc52f7db5f3ddc7e856fc..248d1bb3206f4dd800834d066aa379add03ed602 100644 (file)
@@ -4633,7 +4633,7 @@ handle_std_noreturn_attribute (tree *node, tree name, tree args,
 }
 
 /* Table of supported standard (C23) attributes.  */
-const struct attribute_spec std_attribute_table[] =
+static const attribute_spec std_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -4648,8 +4648,12 @@ const struct attribute_spec std_attribute_table[] =
   { "nodiscard", 0, 1, false, false, false, false,
     handle_nodiscard_attribute, NULL },
   { "noreturn", 0, 0, false, false, false, false,
-    handle_std_noreturn_attribute, NULL },
-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
+    handle_std_noreturn_attribute, NULL }
+};
+
+const scoped_attribute_specs std_attribute_table =
+{
+  nullptr, std_attributes
 };
 
 /* Create the predefined scalar types of C,
@@ -4665,8 +4669,6 @@ c_init_decl_processing (void)
   /* Initialize reserved words for parser.  */
   c_parse_init ();
 
-  register_scoped_attributes (std_attribute_table, NULL);
-
   current_function_decl = NULL_TREE;
 
   gcc_obstack_init (&parser_obstack);
index 63aff7004c56ae75e6efe711b986e81d10a71237..426d938bdb1ff0c16d8c69e1a2160db445edf089 100644 (file)
@@ -75,11 +75,15 @@ extern void c_register_features ();
 #undef LANG_HOOKS_FINALIZE_EARLY_DEBUG
 #define LANG_HOOKS_FINALIZE_EARLY_DEBUG c_common_finalize_early_debug
 
-/* Attribute hooks.  */
-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
-#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
+static const scoped_attribute_specs *const c_objc_attribute_table[] =
+{
+  &std_attribute_table,
+  &c_common_gnu_attribute_table,
+  &c_common_format_attribute_table
+};
+
+#undef LANG_HOOKS_ATTRIBUTE_TABLE
+#define LANG_HOOKS_ATTRIBUTE_TABLE c_objc_attribute_table
 
 #undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
 #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN c_dump_tree
index c6f38ec94a03c6d4ebd679894f55937ba0c0b5d2..d0bdc3df2c2c2205052cc9478887eb4c0aeab348 100644 (file)
@@ -910,6 +910,8 @@ extern vec<tree> incomplete_record_decls;
 
 extern const char *c_get_sarif_source_language (const char *filename);
 
+extern const struct scoped_attribute_specs std_attribute_table;
+
 #if CHECKING_P
 namespace selftest {
   extern void run_c_tests (void);
index 0f83ec0d09d976d3f549d3ff112f8bad1eed0ceb..fca64daf2a013aa6f78a795dece373a7cc93b4b3 100644 (file)
@@ -465,7 +465,7 @@ handle_aarch64_vector_pcs_attribute (tree *node, tree name, tree,
 }
 
 /* Table of machine attributes.  */
-static const struct attribute_spec aarch64_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (aarch64_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -476,9 +476,8 @@ static const struct attribute_spec aarch64_attribute_table[] =
                          NULL },
   { "Advanced SIMD type", 1, 1, false, true,  false, true,  NULL, NULL },
   { "SVE type",                  3, 3, false, true,  false, true,  NULL, NULL },
-  { "SVE sizeless type",  0, 0, false, true,  false, true,  NULL, NULL },
-  { NULL,                 0, 0, false, false, false, false, NULL, NULL }
-};
+  { "SVE sizeless type",  0, 0, false, true,  false, true,  NULL, NULL }
+});
 
 typedef enum aarch64_cond_code
 {
index db6b34be9cb0f064b42ba8da9c432428e16553f5..6aa937832268c4bf35f2427274d1a4680d4a4be3 100644 (file)
@@ -7482,14 +7482,13 @@ common_object_handler (tree *node, tree name ATTRIBUTE_UNUSED,
   return NULL_TREE;
 }
 
-static const struct attribute_spec vms_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (vms_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
   { COMMON_OBJECT,   0, 1, true,  false, false, false, common_object_handler,
-    NULL },
-  { NULL,            0, 0, false, false, false, false, NULL, NULL }
-};
+    NULL }
+});
 
 void
 vms_output_aligned_decl_common(FILE *file, tree decl, const char *name,
index 70ee41082887f46f9f44bf4c808d9bce70a20a44..3f4eb5a5736a51de8de1be4540950e90650a6f79 100644 (file)
@@ -187,44 +187,6 @@ static tree arc_handle_secure_attribute (tree *, tree, tree, int, bool *);
 static tree arc_handle_uncached_attribute (tree *, tree, tree, int, bool *);
 static tree arc_handle_aux_attribute (tree *, tree, tree, int, bool *);
 
-/* Initialized arc_attribute_table to NULL since arc doesnot have any
-   machine specific supported attributes.  */
-const struct attribute_spec arc_attribute_table[] =
-{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
-      affects_type_identity, handler, exclude } */
-  { "interrupt", 1, 1, true, false, false, true,
-    arc_handle_interrupt_attribute, NULL },
-  /* Function calls made to this symbol must be done indirectly, because
-     it may lie outside of the 21/25 bit addressing range of a normal function
-     call.  */
-  { "long_call",    0, 0, false, true,  true,  false, NULL, NULL },
-  /* Whereas these functions are always known to reside within the 25 bit
-     addressing range of unconditionalized bl.  */
-  { "medium_call",   0, 0, false, true,  true, false, NULL, NULL },
-  /* And these functions are always known to reside within the 21 bit
-     addressing range of blcc.  */
-  { "short_call",   0, 0, false, true,  true,  false, NULL, NULL },
-  /* Function which are not having the prologue and epilogue generated
-     by the compiler.  */
-  { "naked", 0, 0, true, false, false,  false, arc_handle_fndecl_attribute,
-    NULL },
-  /* Functions calls made using jli instruction.  The pointer in JLI
-     table is found latter.  */
-  { "jli_always",    0, 0, false, true,  true, false,  NULL, NULL },
-  /* Functions calls made using jli instruction.  The pointer in JLI
-     table is given as input parameter.  */
-  { "jli_fixed",    1, 1, false, true,  true, false, arc_handle_jli_attribute,
-    NULL },
-  /* Call a function using secure-mode.  */
-  { "secure_call",  1, 1, false, true, true, false, arc_handle_secure_attribute,
-    NULL },
-   /* Bypass caches using .di flag.  */
-  { "uncached", 0, 0, false, true, false, false, arc_handle_uncached_attribute,
-    NULL },
-  { "aux", 0, 1, true, false, false, false, arc_handle_aux_attribute, NULL },
-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
-};
 static int arc_comp_type_attributes (const_tree, const_tree);
 static void arc_file_start (void);
 static void arc_internal_label (FILE *, const char *, unsigned long);
@@ -773,6 +735,42 @@ static rtx arc_legitimize_address_0 (rtx, rtx, machine_mode mode);
 
 #include "target-def.h"
 
+TARGET_GNU_ATTRIBUTES (arc_attribute_table,
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+      affects_type_identity, handler, exclude } */
+  { "interrupt", 1, 1, true, false, false, true,
+    arc_handle_interrupt_attribute, NULL },
+  /* Function calls made to this symbol must be done indirectly, because
+     it may lie outside of the 21/25 bit addressing range of a normal function
+     call.  */
+  { "long_call",    0, 0, false, true,  true,  false, NULL, NULL },
+  /* Whereas these functions are always known to reside within the 25 bit
+     addressing range of unconditionalized bl.  */
+  { "medium_call",   0, 0, false, true,  true, false, NULL, NULL },
+  /* And these functions are always known to reside within the 21 bit
+     addressing range of blcc.  */
+  { "short_call",   0, 0, false, true,  true,  false, NULL, NULL },
+  /* Function which are not having the prologue and epilogue generated
+     by the compiler.  */
+  { "naked", 0, 0, true, false, false,  false, arc_handle_fndecl_attribute,
+    NULL },
+  /* Functions calls made using jli instruction.  The pointer in JLI
+     table is found latter.  */
+  { "jli_always",    0, 0, false, true,  true, false,  NULL, NULL },
+  /* Functions calls made using jli instruction.  The pointer in JLI
+     table is given as input parameter.  */
+  { "jli_fixed",    1, 1, false, true,  true, false, arc_handle_jli_attribute,
+    NULL },
+  /* Call a function using secure-mode.  */
+  { "secure_call",  1, 1, false, true, true, false, arc_handle_secure_attribute,
+    NULL },
+   /* Bypass caches using .di flag.  */
+  { "uncached", 0, 0, false, true, false, false, arc_handle_uncached_attribute,
+    NULL },
+  { "aux", 0, 1, true, false, false, false, arc_handle_aux_attribute, NULL }
+});
+
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
 #undef TARGET_ASM_ALIGNED_SI_OP
index 25a1ad736ad96f0cb18b063fec29a09c4cfdbd1d..5cb35e8d0617ef246d0325864a6acdd310d01668 100644 (file)
@@ -332,7 +332,7 @@ static rtx_insn *thumb1_md_asm_adjust (vec<rtx> &, vec<rtx> &,
 static const char *arm_identify_fpu_from_isa (sbitmap);
 \f
 /* Table of machine attributes.  */
-static const struct attribute_spec arm_attribute_table[] =
+static const attribute_spec arm_gnu_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -380,8 +380,17 @@ static const struct attribute_spec arm_attribute_table[] =
     arm_handle_cmse_nonsecure_entry, NULL },
   { "cmse_nonsecure_call", 0, 0, false, false, false, true,
     arm_handle_cmse_nonsecure_call, NULL },
-  { "Advanced SIMD type", 1, 1, false, true, false, true, NULL, NULL },
-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
+  { "Advanced SIMD type", 1, 1, false, true, false, true, NULL, NULL }
+};
+
+static const scoped_attribute_specs arm_gnu_attribute_table =
+{
+  "gnu", arm_gnu_attributes
+};
+
+static const scoped_attribute_specs *const arm_attribute_table[] =
+{
+  &arm_gnu_attribute_table
 };
 \f
 /* Initialize the GCC target structure.  */
index a297f4e092a8a89f50de0649d91f63423b4f09eb..3af9ca8d17f31e128d4062aae653fb265fd8cb29 100644 (file)
@@ -10442,7 +10442,7 @@ avr_eval_addr_attrib (rtx x)
 
 
 /* AVR attributes.  */
-static const struct attribute_spec avr_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (avr_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -10467,9 +10467,8 @@ static const struct attribute_spec avr_attribute_table[] =
   { "address",   1, 1, true, false, false,  false,
     avr_handle_addr_attribute, NULL },
   { "absdata",   0, 0, true, false, false,  false,
-    avr_handle_absdata_attribute, NULL },
-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
-};
+    avr_handle_absdata_attribute, NULL }
+});
 
 
 /* Return true if we support address space AS for the architecture in effect
index 5718babb6b2c8275813c2d7096725e62f7946e5c..c02136f5e0cdcceba72d136fb37bc1dc0fdc9f6b 100644 (file)
@@ -4896,7 +4896,7 @@ bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
 }
 
 /* Table of valid machine attributes.  */
-static const struct attribute_spec bfin_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (bfin_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -4921,9 +4921,8 @@ static const struct attribute_spec bfin_attribute_table[] =
     bfin_handle_l1_data_attribute, NULL },
   { "l1_data_B", 0, 0, true, false, false, false,
     bfin_handle_l1_data_attribute, NULL },
-  { "l2", 0, 0, true, false, false, false, bfin_handle_l2_attribute, NULL },
-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
-};
+  { "l2", 0, 0, true, false, false, false, bfin_handle_l2_attribute, NULL }
+});
 \f
 /* Implementation of TARGET_ASM_INTEGER.  When using FD-PIC, we need to
    tell the assembler to generate pointers to function descriptors in
index ffd83a731026da1fc1b27277c80c5726c4852f6f..f7a5c772e168636a5447b0756c7eb93b28d6db76 100644 (file)
@@ -140,7 +140,7 @@ bpf_handle_preserve_access_index_attribute (tree *node, tree name,
 
 /* Target-specific attributes.  */
 
-static const struct attribute_spec bpf_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (bpf_attribute_table,
 {
   /* Syntax: { name, min_len, max_len, decl_required, type_required,
               function_type_required, affects_type_identity, handler,
@@ -157,11 +157,8 @@ static const struct attribute_spec bpf_attribute_table[] =
 
  /* Support for `naked' function attribute.  */
  { "naked", 0, 1, false, false, false, false,
-   bpf_handle_fndecl_attribute, NULL },
-
- /* The last attribute spec is set to be NULL.  */
- { NULL,       0,  0, false, false, false, false, NULL, NULL }
-};
+   bpf_handle_fndecl_attribute, NULL }
+});
 
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE bpf_attribute_table
index 731f47cb2c0bfa2e40e373eab442d786b8897436..ac089feea620f8f9cd29e757358d16861e07888e 100644 (file)
@@ -211,16 +211,15 @@ const int csky_debugger_regno[FIRST_PSEUDO_REGISTER] =
 /* Table of machine attributes.  */
 static tree csky_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
 static tree csky_handle_isr_attribute (tree *, tree, tree, int, bool *);
-static const struct attribute_spec csky_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (csky_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
   { "naked",    0, 0, true,  false, false, false, csky_handle_fndecl_attribute, NULL },
   /* Interrupt Service Routines have special prologue and epilogue requirements.  */
   { "interrupt", 0, 1, false, false, false, false, csky_handle_isr_attribute,   NULL },
-  { "isr",      0, 1, false, false, false, false, csky_handle_isr_attribute,    NULL },
-  { NULL,       0, 0, false, false, false, false, NULL,                         NULL }
-};
+  { "isr",      0, 1, false, false, false, false, csky_handle_isr_attribute,    NULL }
+});
 
 /* A C structure for machine-specific, per-function data.
    This is added to the cfun structure.  */
index 68e748c688e9407a58de0f6acf3ff99050559824..e10e64de8237bc4d7150a744b9f9c11bdac992dc 100644 (file)
@@ -458,7 +458,7 @@ epiphany_init_reg_tables (void)
                      They unmask them while calling an interruptible
                     function, though.  */
 
-static const struct attribute_spec epiphany_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (epiphany_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -468,9 +468,8 @@ static const struct attribute_spec epiphany_attribute_table[] =
     epiphany_handle_forwarder_attribute, NULL },
   { "long_call",  0, 0, false, true, true, false, NULL, NULL },
   { "short_call", 0, 0, false, true, true, false, NULL, NULL },
-  { "disinterrupt", 0, 0, false, true, true, true, NULL, NULL },
-  { NULL,         0, 0, false, false, false, false, NULL, NULL }
-};
+  { "disinterrupt", 0, 0, false, true, true, true, NULL, NULL }
+});
 
 /* Handle an "interrupt" attribute; arguments as in
    struct attribute_spec.handler.  */
index 22d2b6ebf6d51b88d82806d7664f49e4d125a651..0781c2a47c24e775763d263476b8a983b810b13d 100644 (file)
@@ -358,14 +358,12 @@ gcn_handle_amdgpu_hsa_kernel_attribute (tree *node, tree name,
  
    Create target-specific __attribute__ types.  */
 
-static const struct attribute_spec gcn_attribute_table[] = {
+TARGET_GNU_ATTRIBUTES (gcn_attribute_table, {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
      affects_type_identity } */
   {"amdgpu_hsa_kernel", 0, GCN_KERNEL_ARG_TYPES, false, true,
-   true, true, gcn_handle_amdgpu_hsa_kernel_attribute, NULL},
-  /* End element.  */
-  {NULL, 0, 0, false, false, false, false, NULL, NULL}
-};
+   true, true, gcn_handle_amdgpu_hsa_kernel_attribute, NULL}
+});
 
 /* }}}  */
 /* {{{ Registers and modes.  */
index 4bbb1b711e8c23fb8dba8b52b2f55cf9d199fc78..5936cdca177c9b2e4f2cf7c764b07f7e27ef2a64 100644 (file)
@@ -4909,7 +4909,7 @@ h8300_insert_attributes (tree node, tree *attributes)
    tiny_data: This variable lives in the tiny data area and can be
    referenced with 16-bit absolute memory references.  */
 
-static const struct attribute_spec h8300_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (h8300_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -4926,9 +4926,8 @@ static const struct attribute_spec h8300_attribute_table[] =
   { "eightbit_data",     0, 0, true,  false, false, false,
     h8300_handle_eightbit_data_attribute, NULL },
   { "tiny_data",         0, 0, true,  false, false, false,
-    h8300_handle_tiny_data_attribute, NULL },
-  { NULL,                0, 0, false, false, false, false, NULL, NULL }
-};
+    h8300_handle_tiny_data_attribute, NULL }
+});
 
 
 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
index fb8638a3525b0a835319fed88ecd1be030fad07f..877659229d215f9f3e08e934eb55290a43ed59ce 100644 (file)
@@ -4086,7 +4086,7 @@ handle_nodirect_extern_access_attribute (tree *pnode, tree name,
 }
 
 /* Table of valid machine attributes.  */
-const struct attribute_spec ix86_attribute_table[] =
+static const attribute_spec ix86_gnu_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -4166,10 +4166,12 @@ const struct attribute_spec ix86_attribute_table[] =
   { "cf_check", 0, 0, true, false, false, false,
     ix86_handle_fndecl_attribute, NULL },
   { "nodirect_extern_access", 0, 0, true, false, false, false,
-    handle_nodirect_extern_access_attribute, NULL },
+    handle_nodirect_extern_access_attribute, NULL }
+};
 
-  /* End element.  */
-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
+const scoped_attribute_specs ix86_gnu_attribute_table =
+{
+  "gnu", ix86_gnu_attributes
 };
 
 #include "gt-i386-options.h"
index 68666067fea1e15ec79a1c2a1793bbb57008e9aa..6274c594647783a91a69ff6b8bdbc073c909855c 100644 (file)
@@ -82,7 +82,7 @@ void ix86_function_specific_print (FILE *, int,
                                   struct cl_target_option *);
 bool ix86_valid_target_attribute_p (tree, tree, tree, int);
 
-extern const struct attribute_spec ix86_attribute_table[];
+extern const struct scoped_attribute_specs ix86_gnu_attribute_table;
 
 
 #endif  /* GCC_I386_OPTIONS_H */
index 9390f525b99f0c078c912876aee8498bc3e7701b..0f91ee745021c394b12a333797a269ebe0978c91 100644 (file)
@@ -25968,6 +25968,11 @@ ix86_run_selftests (void)
 
 #endif /* CHECKING_P */
 
+static const scoped_attribute_specs *const ix86_attribute_table[] =
+{
+  &ix86_gnu_attribute_table
+};
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_RETURN_IN_MEMORY
 #define TARGET_RETURN_IN_MEMORY ix86_return_in_memory
index c241e1a50fc57353eb3152141e4340d894811239..f7766c256220a23ec4ac0913b3cb3ca41e524625 100644 (file)
@@ -358,7 +358,7 @@ static bool ia64_expand_vec_perm_const_1 (struct expand_vec_perm_d *d);
 
 \f
 /* Table of valid machine attributes.  */
-static const struct attribute_spec ia64_attribute_table[] =
+static const attribute_spec ia64_gnu_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -370,8 +370,17 @@ static const struct attribute_spec ia64_attribute_table[] =
     ia64_vms_common_object_attribute, NULL },
 #endif
   { "version_id",      1, 1, true, false, false, false,
-    ia64_handle_version_id_attribute, NULL },
-  { NULL,             0, 0, false, false, false, false, NULL, NULL }
+    ia64_handle_version_id_attribute, NULL }
+};
+
+static const scoped_attribute_specs ia64_gnu_attribute_table =
+{
+  "gnu", ia64_gnu_attributes
+};
+
+static const scoped_attribute_specs *const ia64_attribute_table[] =
+{
+  &ia64_gnu_attribute_table
 };
 
 /* Initialize the GCC target structure.  */
index f89c346815da854169a37abce3ffe33ab8e25aee..3545e66a10e462833c0e4fcbe36520170d6ebfed 100644 (file)
@@ -7840,15 +7840,13 @@ loongarch_handle_model_attribute (tree *node, tree name, tree arg, int,
   return NULL_TREE;
 }
 
-static const struct attribute_spec loongarch_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (loongarch_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
   { "model", 1, 1, true, false, false, false,
-    loongarch_handle_model_attribute, NULL },
-  /* The last attribute spec is set to be NULL.  */
-  {}
-};
+    loongarch_handle_model_attribute, NULL }
+});
 
 bool
 loongarch_use_anchors_for_symbol_p (const_rtx symbol)
index e18efc3c7f22c891b8873398334b8c108132e0ce..c63c75a6709df24907fbaaf7b62afe75282fd137 100644 (file)
@@ -2999,7 +2999,7 @@ current_function_special_page_vector (rtx x)
 
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE m32c_attribute_table
-static const struct attribute_spec m32c_attribute_table[] = {
+TARGET_GNU_ATTRIBUTES (m32c_attribute_table, {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
   { "interrupt", 0, 0, false, false, false, false, interrupt_handler, NULL },
@@ -3007,9 +3007,8 @@ static const struct attribute_spec m32c_attribute_table[] = {
   { "fast_interrupt", 0, 0, false, false, false, false,
     interrupt_handler, NULL },
   { "function_vector", 1, 1, true,  false, false, false,
-    function_vector_handler, NULL },
-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
-};
+    function_vector_handler, NULL }
+});
 
 #undef TARGET_COMP_TYPE_ATTRIBUTES
 #define TARGET_COMP_TYPE_ATTRIBUTES m32c_comp_type_attributes
index 63a1798da3d66451339fa21cebfd3a5f78f5b49e..1a9c8ef13915ce132d9639ac670d05dba1df0b87 100644 (file)
@@ -112,15 +112,14 @@ static HOST_WIDE_INT m32r_starting_frame_offset (void);
 \f
 /* M32R specific attributes.  */
 
-static const struct attribute_spec m32r_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (m32r_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
   { "interrupt", 0, 0, true,  false, false, false, NULL, NULL },
   { "model",     1, 1, true,  false, false, false, m32r_handle_model_attribute,
-    NULL },
-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
-};
+    NULL }
+});
 \f
 /* Initialize the GCC target structure.  */
 #undef  TARGET_ATTRIBUTE_TABLE
index 145a92d8710b6fe07ee650de7dd7edc2d2b6f2a4..001cf5bd9979b7383539d1b044ee047e84e65bc7 100644 (file)
@@ -361,7 +361,7 @@ static void m68k_asm_final_postscan_insn (FILE *, rtx_insn *insn, rtx [], int);
 #undef TARGET_ASM_FINAL_POSTSCAN_INSN
 #define TARGET_ASM_FINAL_POSTSCAN_INSN m68k_asm_final_postscan_insn
 
-static const struct attribute_spec m68k_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (m68k_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -370,9 +370,8 @@ static const struct attribute_spec m68k_attribute_table[] =
   { "interrupt_handler", 0, 0, true,  false, false, false,
     m68k_handle_fndecl_attribute, NULL },
   { "interrupt_thread", 0, 0, true,  false, false, false,
-    m68k_handle_fndecl_attribute, NULL },
-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
-};
+    m68k_handle_fndecl_attribute, NULL }
+});
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
index 6f1d7af79371f6a6c84e7f5f522766dadc03c647..ca6725474943c6076ac5128ee8de23d9f6a1f13e 100644 (file)
@@ -151,16 +151,15 @@ static bool         mcore_modes_tieable_p         (machine_mode, machine_mode);
 \f
 /* MCore specific attributes.  */
 
-static const struct attribute_spec mcore_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (mcore_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
   { "dllexport", 0, 0, true,  false, false, false, NULL, NULL },
   { "dllimport", 0, 0, true,  false, false, false, NULL, NULL },
   { "naked",     0, 0, true,  false, false, false,
-    mcore_handle_naked_attribute, NULL },
-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
-};
+    mcore_handle_naked_attribute, NULL }
+});
 \f
 /* Initialize the GCC target structure.  */
 #undef  TARGET_ASM_EXTERNAL_LIBCALL
index 60ad55120d2df8a58151a8e31e7f89567f7a1cb9..3ea177b835e0580a9259e44975f69c82094c5585 100644 (file)
@@ -218,15 +218,14 @@ int break_handler;
 int fast_interrupt;
 int save_volatiles;
 
-const struct attribute_spec microblaze_attribute_table[] = {
+TARGET_GNU_ATTRIBUTES (microblaze_attribute_table, {
   /* name         min_len, max_len, decl_req, type_req, fn_type_req,
      affects_type_identity, handler, exclude */
   {"interrupt_handler",        0,       0,    true, false, false, false, NULL, NULL },
   {"break_handler",    0,       0,    true, false, false, false, NULL, NULL },
   {"fast_interrupt",   0,       0,    true, false, false, false, NULL, NULL },
-  {"save_volatiles",   0,       0,    true, false, false, false, NULL, NULL },
-  { NULL,              0,       0,   false, false, false, false, NULL, NULL }
-};
+  {"save_volatiles",   0,       0,    true, false, false, false, NULL, NULL }
+});
 
 static int microblaze_interrupt_function_p (tree);
 
index cbd7d9bb2846009bf9f75509ca6d9bb4bf4be6ff..9180dbbf843c3aa2e928f68c9648b813a888fcb7 100644 (file)
@@ -611,7 +611,7 @@ static tree mips_handle_use_shadow_register_set_attr (tree *, tree, tree, int,
                                                      bool *);
 
 /* The value of TARGET_ATTRIBUTE_TABLE.  */
-static const struct attribute_spec mips_attribute_table[] = {
+TARGET_GNU_ATTRIBUTES (mips_attribute_table, {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
   { "long_call",   0, 0, false, true,  true,  false, NULL, NULL },
@@ -636,9 +636,8 @@ static const struct attribute_spec mips_attribute_table[] = {
     mips_handle_use_shadow_register_set_attr, NULL },
   { "keep_interrupts_masked",  0, 0, false, true,  true, false, NULL, NULL },
   { "use_debug_exception_return", 0, 0, false, true, true, false, NULL, NULL },
-  { "use_hazard_barrier_return", 0, 0, true, false, false, false, NULL, NULL },
-  { NULL,         0, 0, false, false, false, false, NULL, NULL }
-};
+  { "use_hazard_barrier_return", 0, 0, true, false, false, false, NULL, NULL }
+});
 \f
 /* A table describing all the processors GCC knows about; see
    mips-cpus.def for details.  */
index 061a9c77961a33a7261d8dcf54fb3018f1b4bead..85f499f175d2b95dd501d9f6e19e7a895cc436da 100644 (file)
@@ -2057,7 +2057,7 @@ static const struct attribute_spec::exclusions attr_either_exclusions[] =
 #define TARGET_ATTRIBUTE_TABLE         msp430_attribute_table
 
 /* Table of MSP430-specific attributes.  */
-const struct attribute_spec msp430_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (msp430_attribute_table,
   {
     /* { name, min_num_args, max_num_args, decl_req, type_req, fn_type_req,
         affects_type_identity, handler, exclude } */
@@ -2075,10 +2075,8 @@ const struct attribute_spec msp430_attribute_table[] =
     { ATTR_UPPER,       0, 0, true,  false, false, false, msp430_section_attr,
       attr_upper_exclusions },
     { ATTR_EITHER,      0, 0, true,  false, false, false, msp430_section_attr,
-      attr_either_exclusions },
-
-    { NULL,            0, 0, false, false, false, false, NULL,  NULL }
-  };
+      attr_either_exclusions }
+  });
 
 #undef TARGET_HANDLE_GENERIC_ATTRIBUTE
 #define TARGET_HANDLE_GENERIC_ATTRIBUTE msp430_handle_generic_attribute
index 1f8de2a514a24d57c69e9a06e671d35517dff4a4..e0a73985b663e2eadb806de299e85e98f90ad2f9 100644 (file)
@@ -288,7 +288,7 @@ static const int nds32_reg_alloc_order_for_speed[] =
 };
 
 /* Defining target-specific uses of __attribute__.  */
-static const struct attribute_spec nds32_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (nds32_attribute_table,
 {
   /* Syntax: { name, min_len, max_len, decl_required, type_required,
               function_type_required, affects_type_identity, handler,
@@ -326,11 +326,8 @@ static const struct attribute_spec nds32_attribute_table[] =
 
   /* FOR BACKWARD COMPATIBILITY,
      this attribute also tells no prologue/epilogue.  */
-  { "no_prologue",  0,  0, false, false, false, false, NULL, NULL },
-
-  /* The last attribute spec is set to be NULL.  */
-  { NULL,           0,  0, false, false, false, false, NULL, NULL }
-};
+  { "no_prologue",  0,  0, false, false, false, false, NULL, NULL }
+});
 
 
 /* ------------------------------------------------------------------------ */
index 570bcc7fc28de6676eff185a5b7a70780ea0f9e6..992d005e5b6c20eeaf817b0b5e46213639001e32 100644 (file)
@@ -5834,16 +5834,15 @@ nvptx_handle_shared_attribute (tree *node, tree name, tree ARG_UNUSED (args),
 }
 
 /* Table of valid machine attributes.  */
-static const struct attribute_spec nvptx_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (nvptx_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
   { "kernel", 0, 0, true, false,  false, false, nvptx_handle_kernel_attribute,
     NULL },
   { "shared", 0, 0, true, false,  false, false, nvptx_handle_shared_attribute,
-    NULL },
-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
-};
+    NULL }
+});
 \f
 /* Limit vector alignments to BIGGEST_ALIGNMENT.  */
 
index 58060b8600cf9aab87e685a54caecb973e509e31..3f111fa0393a489dc1dac3b05fae14c87b93e1a6 100644 (file)
@@ -434,7 +434,7 @@ static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *);
 static void riscv_legitimize_poly_move (machine_mode, rtx, rtx, rtx);
 
 /* Defining target-specific uses of __attribute__.  */
-static const struct attribute_spec riscv_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (riscv_attribute_table,
 {
   /* Syntax: { name, min_len, max_len, decl_required, type_required,
               function_type_required, affects_type_identity, handler,
@@ -450,11 +450,8 @@ static const struct attribute_spec riscv_attribute_table[] =
   /* The following two are used for the built-in properties of the Vector type
      and are not used externally */
   {"RVV sizeless type", 4, 4, false, true, false, true, NULL, NULL},
-  {"RVV type", 0, 0, false, true, false, true, NULL, NULL},
-
-  /* The last attribute spec is set to be NULL.  */
-  { NULL,      0,  0, false, false, false, false, NULL, NULL }
-};
+  {"RVV type", 0, 0, false, true, false, true, NULL, NULL}
+});
 
 /* Order for the CLOBBERs/USEs of gpr_save.  */
 static const unsigned gpr_save_reg_order[] = {
index 7f13e8304b235df1d28f2df1458dd80e58af0bcb..5d8fddbd905a4ceebba5cd30e28f2498cfd8916f 100644 (file)
@@ -898,7 +898,7 @@ rl78_handle_vector_attribute (tree * node,
 #define TARGET_ATTRIBUTE_TABLE         rl78_attribute_table
 
 /* Table of RL78-specific attributes.  */
-const struct attribute_spec rl78_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (rl78_attribute_table,
 {
   /* Name, min_len, max_len, decl_req, type_req, fn_type_req,
      affects_type_identity, handler, exclude.  */
@@ -911,9 +911,8 @@ const struct attribute_spec rl78_attribute_table[] =
   { "saddr",          0, 0, true, false, false, false,
     rl78_handle_saddr_attribute, NULL },
   { "vector",         1, -1, true, false, false, false,
-       rl78_handle_vector_attribute, NULL },
-  { NULL,             0, 0, false, false, false, false, NULL, NULL }
-};
+       rl78_handle_vector_attribute, NULL }
+});
 
 
 \f
index cee22c359f395d62601fcd64bbc07fed2ce06148..5386470f6f82c40d64b2ffb45140ef0c7c0df1da 100644 (file)
@@ -1255,7 +1255,7 @@ static const char alt_reg_names[][8] =
 
 /* Table of valid machine attributes.  */
 
-static const struct attribute_spec rs6000_attribute_table[] =
+static const attribute_spec rs6000_gnu_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -1272,7 +1272,16 @@ static const struct attribute_spec rs6000_attribute_table[] =
 #ifdef SUBTARGET_ATTRIBUTE_TABLE
   SUBTARGET_ATTRIBUTE_TABLE,
 #endif
-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
+};
+
+static const scoped_attribute_specs rs6000_gnu_attribute_table =
+{
+  "gnu", rs6000_gnu_attributes
+};
+
+static const scoped_attribute_specs *const rs6000_attribute_table[] =
+{
+  &rs6000_gnu_attribute_table
 };
 \f
 #ifndef TARGET_PROFILE_KERNEL
index 245c6a4413dac5c6cdf96c9db846ada242765840..0754e286552e4934f07e26f3be714b0d37b33835 100644 (file)
@@ -2760,7 +2760,7 @@ rx_handle_vector_attribute (tree * node,
 }
 
 /* Table of RX specific attributes.  */
-const struct attribute_spec rx_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (rx_attribute_table,
 {
   /* Name, min_len, max_len, decl_req, type_req, fn_type_req,
      affects_type_identity, handler, exclude.  */
@@ -2771,9 +2771,8 @@ const struct attribute_spec rx_attribute_table[] =
   { "naked",          0, 0, true, false, false, false,
     rx_handle_func_attribute, NULL },
   { "vector",         1, -1, true, false, false, false,
-    rx_handle_vector_attribute, NULL },
-  { NULL,             0, 0, false, false, false, false, NULL, NULL }
-};
+    rx_handle_vector_attribute, NULL }
+});
 
 /* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE.  */
 
index 0a969ec419e66a084c96961a5237fa03172abfb0..384fdb93df5309d466edbd9f7b65c738e04db4de 100644 (file)
@@ -1303,7 +1303,7 @@ s390_handle_string_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
   return NULL_TREE;
 }
 
-static const struct attribute_spec s390_attribute_table[] = {
+TARGET_GNU_ATTRIBUTES (s390_attribute_table, {
   { "hotpatch", 2, 2, true, false, false, false,
     s390_handle_hotpatch_attribute, NULL },
   { "s390_vector_bool", 0, 0, false, true, false, true,
@@ -1319,11 +1319,8 @@ static const struct attribute_spec s390_attribute_table[] = {
   { "function_return_reg", 1, 1, true, false, false, false,
     s390_handle_string_attribute, NULL },
   { "function_return_mem", 1, 1, true, false, false, false,
-    s390_handle_string_attribute, NULL },
-
-  /* End element.  */
-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
-};
+    s390_handle_string_attribute, NULL }
+});
 
 /* Return the alignment for LABEL.  We default to the -falign-labels
    value except for the literal pool base label.  */
index 6ec2eecf754685c8eeee7a51f8bb575f890b18bf..8c378b28b6d224755fa76bd0152c3e2164432940 100644 (file)
@@ -329,7 +329,7 @@ static bool sh_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool sh_modes_tieable_p (machine_mode, machine_mode);
 static bool sh_can_change_mode_class (machine_mode, machine_mode, reg_class_t);
 \f
-static const struct attribute_spec sh_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (sh_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -348,9 +348,8 @@ static const struct attribute_spec sh_attribute_table[] =
   { "resbank",           0, 0, true,  false, false, false,
     sh_handle_resbank_handler_attribute, NULL },
   { "function_vector",   1, 1, true,  false, false, false,
-    sh2a_handle_function_vector_handler_attribute, NULL },
-  { NULL,                0, 0, false, false, false, false, NULL, NULL }
-};
+    sh2a_handle_function_vector_handler_attribute, NULL }
+});
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ATTRIBUTE_TABLE
index e90739d0f125c6a882c28858b6eabc74451888ed..c09dbcde7c5997cded5163c3845990b471e85193 100644 (file)
@@ -721,13 +721,12 @@ static HARD_REG_SET sparc_zero_call_used_regs (HARD_REG_SET);
 \f
 #ifdef SUBTARGET_ATTRIBUTE_TABLE
 /* Table of valid machine attributes.  */
-static const struct attribute_spec sparc_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (sparc_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        do_diagnostic, handler, exclude } */
-  SUBTARGET_ATTRIBUTE_TABLE,
-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
-};
+  SUBTARGET_ATTRIBUTE_TABLE
+});
 #endif
 \f
 char sparc_hard_reg_printed[8];
index 10887153906ecf96ab2f8a4ce8ad73169e68e5bc..071043b41285aa1936cda2c325e009cc51a2a0a8 100644 (file)
@@ -2377,7 +2377,7 @@ static tree xstormy16_handle_interrupt_attribute
 static tree xstormy16_handle_below100_attribute
   (tree *, tree, tree, int, bool *);
 
-static const struct attribute_spec xstormy16_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (xstormy16_attribute_table,
 {
   /* name, min_len, max_len, decl_req, type_req, fn_type_req,
      affects_type_identity, handler, exclude.  */
@@ -2386,9 +2386,8 @@ static const struct attribute_spec xstormy16_attribute_table[] =
   { "BELOW100",  0, 0, false, false, false, false,
     xstormy16_handle_below100_attribute, NULL },
   { "below100",  0, 0, false, false, false, false,
-    xstormy16_handle_below100_attribute, NULL },
-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
-};
+    xstormy16_handle_below100_attribute, NULL }
+});
 
 /* Handle an "interrupt" attribute;
    arguments as in struct attribute_spec.handler.  */
index 416c2841a5c0c823b73166926e61cbe2a5e0dcd7..50c91c68b8ba81ad2f621619e26ada37d490c14c 100644 (file)
@@ -3114,7 +3114,7 @@ v850_adjust_insn_length (rtx_insn *insn, int length)
 \f
 /* V850 specific attributes.  */
 
-static const struct attribute_spec v850_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (v850_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -3127,9 +3127,8 @@ static const struct attribute_spec v850_attribute_table[] =
   { "tda",               0, 0, true,  false, false, false,
     v850_handle_data_area_attribute, NULL },
   { "zda",               0, 0, true,  false, false, false,
-    v850_handle_data_area_attribute, NULL },
-  { NULL,                0, 0, false, false, false, false, NULL, NULL }
-};
+    v850_handle_data_area_attribute, NULL }
+});
 \f
 static void
 v850_option_override (void)
index 5fadbc80be06acb86e392a11759353b35ba334fa..4a1877c2ac1cda5cfaa7d8c2539aea4b59981905 100644 (file)
@@ -145,14 +145,13 @@ static inline bool current_function_has_lr_slot (void);
 
 /* Supported attributes:
    interrupt -- specifies this function is an interrupt handler.   */
-static const struct attribute_spec visium_attribute_table[] =
+TARGET_GNU_ATTRIBUTES (visium_attribute_table,
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
   { "interrupt", 0, 0, true, false, false, false, visium_handle_interrupt_attr,
-    NULL},
-  { NULL, 0, 0, false, false, false, false, NULL, NULL },
-};
+    NULL}
+});
 
 static struct machine_function *visium_init_machine_status (void);
 
index 5b175b03fbbdf0baa03dc61b69418d32e3c3c9e1..b53d11e7a56b6754ac641beada8aad59853a2f8b 100644 (file)
@@ -123,13 +123,16 @@ extern tree cxx_simulate_record_decl (location_t, const char *,
 #undef LANG_HOOKS_FINALIZE_EARLY_DEBUG
 #define LANG_HOOKS_FINALIZE_EARLY_DEBUG c_common_finalize_early_debug
 
-/* Attribute hooks.  */
-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
-#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
+static const scoped_attribute_specs *const cp_objcp_attribute_table[] =
+{
+  &std_attribute_table,
+  &cxx_gnu_attribute_table,
+  &c_common_gnu_attribute_table,
+  &c_common_format_attribute_table
+};
+
 #undef LANG_HOOKS_ATTRIBUTE_TABLE
-#define LANG_HOOKS_ATTRIBUTE_TABLE cxx_attribute_table
+#define LANG_HOOKS_ATTRIBUTE_TABLE cp_objcp_attribute_table
 
 #undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
 #define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P cp_var_mod_type_p
index b9adc1742cefa9ed46ea6e12e055dff931dee70d..9979c5da6231eede706374f0be0ecd2b758985e4 100644 (file)
@@ -8034,7 +8034,8 @@ extern tree maybe_dummy_object                    (tree, tree *);
 extern bool is_dummy_object                    (const_tree);
 extern bool is_byte_access_type                        (tree);
 extern bool is_byte_access_type_not_plain_char (tree);
-extern const struct attribute_spec cxx_attribute_table[];
+extern const struct scoped_attribute_specs cxx_gnu_attribute_table;
+extern const struct scoped_attribute_specs std_attribute_table;
 extern tree make_ptrmem_cst                    (tree, tree);
 extern tree cp_build_type_attribute_variant     (tree, tree);
 extern tree cp_build_reference_type            (tree, bool);
index 5279579c20104c6ce5fc90df280f8eeec0794312..e0b9d512adccb3142d2a3df0e199927db0afc096 100644 (file)
@@ -5086,7 +5086,7 @@ handle_likeliness_attribute (tree *node, tree name, tree args,
 }
 
 /* Table of valid C++ attributes.  */
-const struct attribute_spec cxx_attribute_table[] =
+static const attribute_spec cxx_gnu_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -5094,11 +5094,15 @@ const struct attribute_spec cxx_attribute_table[] =
     handle_init_priority_attribute, NULL },
   { "abi_tag", 1, -1, false, false, false, true,
     handle_abi_tag_attribute, NULL },
-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
+};
+
+const scoped_attribute_specs cxx_gnu_attribute_table =
+{
+  "gnu", cxx_gnu_attributes
 };
 
 /* Table of C++ standard attributes.  */
-const struct attribute_spec std_attribute_table[] =
+static const attribute_spec std_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -5119,10 +5123,11 @@ const struct attribute_spec std_attribute_table[] =
   { "pre", 0, -1, false, false, false, false,
     handle_contract_attribute, NULL },
   { "post", 0, -1, false, false, false, false,
-    handle_contract_attribute, NULL },
-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
+    handle_contract_attribute, NULL }
 };
 
+const scoped_attribute_specs std_attribute_table = { nullptr, std_attributes };
+
 /* Handle an "init_priority" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
@@ -5718,7 +5723,6 @@ void
 init_tree (void)
 {
   list_hash_table = hash_table<list_hasher>::create_ggc (61);
-  register_scoped_attributes (std_attribute_table, NULL);
 }
 
 /* Returns the kind of special function that DECL (a FUNCTION_DECL)
index c0dc0e24ded871c136e54e5527e901d16cfa5ceb..f641105807215c23cdf6326f3fb5c67db1258678 100644 (file)
@@ -162,7 +162,7 @@ extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
 
 /* Table of machine-independent attributes.
    For internal use (marking of built-ins) only.  */
-const attribute_spec d_langhook_common_attribute_table[] =
+static const attribute_spec d_langhook_common_attributes[] =
 {
   ATTR_SPEC ("noreturn", 0, 0, true, false, false, false,
             handle_noreturn_attribute, attr_noreturn_exclusions),
@@ -190,11 +190,15 @@ const attribute_spec d_langhook_common_attribute_table[] =
             handle_fnspec_attribute, NULL),
   ATTR_SPEC ("omp declare simd", 0, -1, true,  false, false, false,
             handle_omp_declare_simd_attribute, NULL),
-  ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
+};
+
+const scoped_attribute_specs d_langhook_common_attribute_table =
+{
+  "gnu", d_langhook_common_attributes
 };
 
 /* Table of D language attributes exposed by `gcc.attribute' UDAs.  */
-const attribute_spec d_langhook_attribute_table[] =
+static const attribute_spec d_langhook_gnu_attributes[] =
 {
   ATTR_SPEC ("noinline", 0, 0, true, false, false, false,
             d_handle_noinline_attribute, attr_noinline_exclusions),
@@ -238,9 +242,12 @@ const attribute_spec d_langhook_attribute_table[] =
             d_handle_used_attribute, NULL),
   ATTR_SPEC ("visibility", 1, 1, false, false, false, false,
             d_handle_visibility_attribute, NULL),
-  ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
 };
 
+const scoped_attribute_specs d_langhook_gnu_attribute_table =
+{
+  "gnu", d_langhook_gnu_attributes
+};
 
 /* Insert the type attribute ATTRNAME with value VALUE into TYPE.
    Returns a new variant of the original type declaration.  */
@@ -283,20 +290,14 @@ uda_attribute_p (const char *name)
 
   /* Search both our language, and target attribute tables.
      Common and format attributes are kept internal.  */
-  for (const attribute_spec *p = d_langhook_attribute_table; p->name; p++)
-    {
-      if (get_identifier (p->name) == ident)
-       return true;
-    }
+  for (const attribute_spec &p : d_langhook_gnu_attributes)
+    if (get_identifier (p.name) == ident)
+      return true;
 
-  if (targetm.attribute_table)
-    {
-      for (const attribute_spec *p = targetm.attribute_table; p->name; p++)
-       {
-         if (get_identifier (p->name) == ident)
-           return true;
-       }
-    }
+  for (auto scoped_attributes : targetm.attribute_table)
+    for (const attribute_spec &p : scoped_attributes->attributes)
+      if (get_identifier (p.name) == ident)
+       return true;
 
   return false;
 }
index 61fc1608b4060bfe0fce5f0ae0509cba7b6ee0a4..dcbffec3752d7296c94276cd6b5848582899d7f5 100644 (file)
@@ -1927,6 +1927,12 @@ d_get_sarif_source_language (const char *)
   return "d";
 }
 
+const scoped_attribute_specs *const d_langhook_attribute_table[] =
+{
+  &d_langhook_gnu_attribute_table,
+  &d_langhook_common_attribute_table,
+};
+
 /* Definitions for our language-specific hooks.  */
 
 #undef LANG_HOOKS_NAME
@@ -1938,7 +1944,6 @@ d_get_sarif_source_language (const char *)
 #undef LANG_HOOKS_HANDLE_OPTION
 #undef LANG_HOOKS_POST_OPTIONS
 #undef LANG_HOOKS_PARSE_FILE
-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
 #undef LANG_HOOKS_ATTRIBUTE_TABLE
 #undef LANG_HOOKS_GET_ALIAS_SET
 #undef LANG_HOOKS_TYPES_COMPATIBLE_P
@@ -1971,7 +1976,6 @@ d_get_sarif_source_language (const char *)
 #define LANG_HOOKS_HANDLE_OPTION           d_handle_option
 #define LANG_HOOKS_POST_OPTIONS                    d_post_options
 #define LANG_HOOKS_PARSE_FILE              d_parse_file
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE   d_langhook_common_attribute_table
 #define LANG_HOOKS_ATTRIBUTE_TABLE         d_langhook_attribute_table
 #define LANG_HOOKS_GET_ALIAS_SET           d_get_alias_set
 #define LANG_HOOKS_TYPES_COMPATIBLE_P      d_types_compatible_p
index d19c3f50bd912c7fd6d14df57a1b69c6be79ce1f..46a28737daa1791f9ed828d3aeb1f192f90b3bd1 100644 (file)
@@ -520,8 +520,8 @@ extern tree insert_decl_attribute (tree, const char *, tree = NULL_TREE);
 extern void apply_user_attributes (Dsymbol *, tree);
 
 /* In d-builtins.cc.  */
-extern const attribute_spec d_langhook_attribute_table[];
-extern const attribute_spec d_langhook_common_attribute_table[];
+extern const struct scoped_attribute_specs d_langhook_gnu_attribute_table;
+extern const struct scoped_attribute_specs d_langhook_common_attribute_table;
 extern Type *build_frontend_type (tree);
 
 extern tree d_builtin_function (tree);
index ac50b07e7e3aad4b89d483338eff06919ebe0af0..7c5d2e523601dfe35cc92ecafa51198003db6272 100644 (file)
@@ -10546,12 +10546,33 @@ Target-specific attributes may be defined for functions, data and types.
 These are described using the following target hooks; they also need to
 be documented in @file{extend.texi}.
 
-@deftypevr {Target Hook} {const struct attribute_spec *} TARGET_ATTRIBUTE_TABLE
-If defined, this target hook points to an array of @samp{struct
-attribute_spec} (defined in @file{tree-core.h}) specifying the machine
-specific attributes for this target and some of the restrictions on the
-entities to which these attributes are applied and the arguments they
-take.
+@deftypevr {Target Hook} {array_slice<const struct scoped_attribute_specs *const>} TARGET_ATTRIBUTE_TABLE
+If defined, this target hook provides an array of
+@samp{scoped_attribute_spec}s (defined in @file{attribs.h}) that specify the
+machine-specific attributes for this target.  The information includes some
+of the restrictions on the entities to which these attributes are applied
+and the arguments that the attributes take.
+
+In C and C++, these attributes are associated with two syntaxes:
+the traditional GNU @code{__attribute__} syntax and the standard
+@samp{[[]]} syntax.  Attributes that support the GNU syntax must be
+placed in the @code{gnu} namespace.  Such attributes can then also be
+written @samp{[[gnu::@dots{}]]}.  Attributes that use only the standard
+syntax should be placed in whichever namespace the attribute specification
+requires.  For example, a target might choose to support vendor-specific
+@samp{[[]]} attributes that the vendor places in their own namespace.
+
+Targets that only define attributes in the @code{gnu} namespace
+can uase the following shorthand to define the table:
+
+@smallexample
+TARGET_GNU_ATTRIBUTES (@var{cpu_attribute_table}, @{
+  @{ "@var{attribute1}", @dots{} @},
+  @{ "@var{attribute2}", @dots{} @},
+  @dots{},
+  @{ "@var{attributen}", @dots{} @},
+@});
+@end smallexample
 @end deftypevr
 
 @deftypefn {Target Hook} bool TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P (const_tree @var{name})
index 350e6e379eb74ada21f752fd27aa5ed1443e877b..99dd76226a2f5b9b22bd43ee7ce225e28413ff27 100644 (file)
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cpp.h"
 #include "trans-types.h"
 #include "trans-const.h"
+#include "attribs.h"
 
 /* Language-dependent contents of an identifier.  */
 
@@ -87,7 +88,7 @@ gfc_handle_omp_declare_target_attribute (tree *, tree, tree, int, bool *)
 }
 
 /* Table of valid Fortran attributes.  */
-static const struct attribute_spec gfc_attribute_table[] =
+static const attribute_spec gfc_gnu_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -97,7 +98,16 @@ static const struct attribute_spec gfc_attribute_table[] =
     gfc_handle_omp_declare_target_attribute, NULL },
   { "oacc function", 0, -1, true,  false, false, false,
     gfc_handle_omp_declare_target_attribute, NULL },
-  { NULL,                0, 0, false, false, false, false, NULL, NULL }
+};
+
+static const scoped_attribute_specs gfc_gnu_attribute_table =
+{
+  "gnu", gfc_gnu_attributes
+};
+
+static const scoped_attribute_specs *const gfc_attribute_table[] =
+{
+  &gfc_gnu_attribute_table
 };
 
 /* Get a value for the SARIF v2.1.0 "artifact.sourceLanguage" property,
index a729086bafbd8aa6f97f6f32b9a7efe4806ccfae..61cc0e1ae66ea5560985a87ecd651578f5633c4b 100644 (file)
@@ -87,7 +87,7 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
 };
 
 /* Table of machine-independent attributes supported in libgccjit.  */
-const struct attribute_spec jit_attribute_table[] =
+static const attribute_spec jit_gnu_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -128,22 +128,36 @@ const struct attribute_spec jit_attribute_table[] =
   /* For internal use only.  The leading '*' both prevents its usage in
      source code and signals that it may be overridden by machine tables.  */
   { "*tm regparm",            0, 0, false, true, true, false,
-                             ignore_attribute, NULL },
-  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
+                             ignore_attribute, NULL }
+};
+
+static const scoped_attribute_specs jit_gnu_attribute_table =
+{
+  "gnu", jit_gnu_attributes
 };
 
 /* Give the specifications for the format attributes, used by C and all
    descendants.  */
 
-const struct attribute_spec jit_format_attribute_table[] =
+static const attribute_spec jit_format_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
   { "format",                 3, 3, false, true,  true, false,
                              handle_format_attribute, NULL },
   { "format_arg",             1, 1, false, true,  true, false,
-                             handle_format_arg_attribute, NULL },
-  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
+                             handle_format_arg_attribute, NULL }
+};
+
+static const scoped_attribute_specs jit_format_attribute_table =
+{
+  "gnu", jit_format_attributes
+};
+
+static const scoped_attribute_specs *const jit_attribute_table[] =
+{
+  &jit_gnu_attribute_table,
+  &jit_format_attribute_table
 };
 
 /* Attribute handlers.  */
@@ -719,10 +733,8 @@ jit_langhook_getdecls (void)
 #define LANG_HOOKS_GETDECLS            jit_langhook_getdecls
 
 /* Attribute hooks.  */
-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE jit_attribute_table
-#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE jit_format_attribute_table
+#undef LANG_HOOKS_ATTRIBUTE_TABLE
+#define LANG_HOOKS_ATTRIBUTE_TABLE jit_attribute_table
 
 #undef  LANG_HOOKS_DEEP_UNSHARING
 #define LANG_HOOKS_DEEP_UNSHARING      true
index c6d18526360cf081258af9336e05c522147201ab..c9cb65759c22ed73be4558ada1797d1b20b28513 100644 (file)
@@ -153,9 +153,7 @@ extern const char *lhd_get_sarif_source_language (const char *);
 #define LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE lhd_get_sarif_source_language
 
 /* Attribute hooks.  */
-#define LANG_HOOKS_ATTRIBUTE_TABLE             NULL
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE      NULL
-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE      NULL
+#define LANG_HOOKS_ATTRIBUTE_TABLE             {}
 
 /* Tree inlining hooks.  */
 #define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P \
@@ -367,8 +365,6 @@ extern void lhd_end_section (void);
   LANG_HOOKS_PRINT_ERROR_FUNCTION, \
   LANG_HOOKS_TO_TARGET_CHARSET, \
   LANG_HOOKS_ATTRIBUTE_TABLE, \
-  LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, \
-  LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, \
   LANG_HOOKS_TREE_INLINING_INITIALIZER, \
   LANG_HOOKS_TREE_DUMP_INITIALIZER, \
   LANG_HOOKS_DECLS, \
index cca75285fc2e61e3eb7d3d10d17738687bef82c3..2785a0070fc9112887a38fb2a270120538c56392 100644 (file)
@@ -532,9 +532,7 @@ struct lang_hooks
      table of attributes specific to the language, a table of
      attributes common to two or more languages (to allow easy
      sharing), and a table of attributes for checking formats.  */
-  const struct attribute_spec *attribute_table;
-  const struct attribute_spec *common_attribute_table;
-  const struct attribute_spec *format_attribute_table;
+  array_slice<const struct scoped_attribute_specs *const> attribute_table;
 
   struct lang_hooks_for_tree_inlining tree_inlining;
 
index 00bd3deb68d51a8674294438760b58c2f2c62d6a..41de35a9ff6f05b40584c455c040d233987fdcdd 100644 (file)
@@ -94,7 +94,7 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
 };
 
 /* Table of machine-independent attributes supported in GIMPLE.  */
-const struct attribute_spec lto_attribute_table[] =
+static const attribute_spec lto_gnu_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -135,14 +135,18 @@ const struct attribute_spec lto_attribute_table[] =
   /* For internal use only.  The leading '*' both prevents its usage in
      source code and signals that it may be overridden by machine tables.  */
   { "*tm regparm",            0, 0, false, true, true, false,
-                             ignore_attribute, NULL },
-  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
+                             ignore_attribute, NULL }
+};
+
+static const scoped_attribute_specs lto_gnu_attribute_table =
+{
+  "gnu", lto_gnu_attributes
 };
 
 /* Give the specifications for the format attributes, used by C and all
    descendants.  */
 
-const struct attribute_spec lto_format_attribute_table[] =
+static const attribute_spec lto_format_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
@@ -150,7 +154,17 @@ const struct attribute_spec lto_format_attribute_table[] =
                              handle_format_attribute, NULL },
   { "format_arg",             1, 1, false, true,  true, false,
                              handle_format_arg_attribute, NULL },
-  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
+};
+
+static const scoped_attribute_specs lto_format_attribute_table =
+{
+  "gnu", lto_format_attributes
+};
+
+static const scoped_attribute_specs *const lto_attribute_table[] =
+{
+  &lto_gnu_attribute_table,
+  &lto_format_attribute_table
 };
 
 enum built_in_attribute
@@ -1463,10 +1477,8 @@ static void lto_init_ts (void)
 #define LANG_HOOKS_EH_PERSONALITY lto_eh_personality
 
 /* Attribute hooks.  */
-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE lto_attribute_table
-#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE lto_format_attribute_table
+#undef LANG_HOOKS_ATTRIBUTE_TABLE
+#define LANG_HOOKS_ATTRIBUTE_TABLE lto_attribute_table
 
 #undef LANG_HOOKS_BEGIN_SECTION
 #define LANG_HOOKS_BEGIN_SECTION lto_obj_begin_section
index ee0a53ec4c95c0a4c4f6b8427d3e0abde6bd9c55..f306adfb3b928477e3e7a1eed043bdf0ca7bdc1b 100644 (file)
@@ -201,8 +201,7 @@ invoke_plugin_callbacks (int event ATTRIBUTE_UNUSED,
 
 extern void register_attribute (const struct attribute_spec *attr);
 /* The default argument for the third parameter is given in attribs.h.  */
-extern struct scoped_attributes* register_scoped_attributes (const struct attribute_spec *,
-                                                            const char *,
+extern struct scoped_attributes* register_scoped_attributes (const struct scoped_attribute_spec &,
                                                             bool);
 
 #endif /* PLUGIN_H */
index 847698a1e597d952788281cc2da54ad7a7c3dc5c..d03b039ab24b21c8ebdc059f9b6b30f868932c24 100644 (file)
 #define TARGET_FUNCTION_INCOMING_ARG TARGET_FUNCTION_ARG
 #endif
 
+/* Declare a target attribute table called NAME that only has GNU attributes.
+   There should be no null trailing element.  E.g.:
+
+     TARGET_GNU_ATTRIBUTES (aarch64_attribute_table,
+     {
+       { "aarch64_vector_pcs", ... },
+       ...
+     });  */
+
+#define TARGET_GNU_ATTRIBUTES(NAME, ...) \
+  static const attribute_spec NAME##_2[] = __VA_ARGS__; \
+  static const scoped_attribute_specs NAME##_1 = { "gnu", NAME##_2 }; \
+  static const scoped_attribute_specs *const NAME[] = { &NAME##_1 }
+
 #include "target-hooks-def.h"
 
 #include "hooks.h"
index eae7959cdccbfe669d234afe45c39545eae64234..c6562ed40ac8ffc80280c9424dd271b76f2fe2e4 100644 (file)
@@ -2218,15 +2218,36 @@ merging.",
  merge_type_attributes)
 
 /* Table of machine attributes and functions to handle them.
-   Ignored if NULL.  */
+   Ignored if empty.  */
 DEFHOOKPOD
 (attribute_table,
- "If defined, this target hook points to an array of @samp{struct\n\
-attribute_spec} (defined in @file{tree-core.h}) specifying the machine\n\
-specific attributes for this target and some of the restrictions on the\n\
-entities to which these attributes are applied and the arguments they\n\
-take.",
- const struct attribute_spec *, NULL)
+ "If defined, this target hook provides an array of\n\
+@samp{scoped_attribute_spec}s (defined in @file{attribs.h}) that specify the\n\
+machine-specific attributes for this target.  The information includes some\n\
+of the restrictions on the entities to which these attributes are applied\n\
+and the arguments that the attributes take.\n\
+\n\
+In C and C++, these attributes are associated with two syntaxes:\n\
+the traditional GNU @code{__attribute__} syntax and the standard\n\
+@samp{[[]]} syntax.  Attributes that support the GNU syntax must be\n\
+placed in the @code{gnu} namespace.  Such attributes can then also be\n\
+written @samp{[[gnu::@dots{}]]}.  Attributes that use only the standard\n\
+syntax should be placed in whichever namespace the attribute specification\n\
+requires.  For example, a target might choose to support vendor-specific\n\
+@samp{[[]]} attributes that the vendor places in their own namespace.\n\
+\n\
+Targets that only define attributes in the @code{gnu} namespace\n\
+can uase the following shorthand to define the table:\n\
+\n\
+@smallexample\n\
+TARGET_GNU_ATTRIBUTES (@var{cpu_attribute_table}, @{\n\
+  @{ \"@var{attribute1}\", @dots{} @},\n\
+  @{ \"@var{attribute2}\", @dots{} @},\n\
+  @dots{},\n\
+  @{ \"@var{attributen}\", @dots{} @},\n\
+@});\n\
+@end smallexample",
+ array_slice<const struct scoped_attribute_specs *const>, {})
 
 /* Return true iff attribute NAME expects a plain identifier as its first
    argument.  */
index 5984716684244d49cf43c759c98c4abe9cc520cf..e6d553059e3ec132891b72cbb82d698dc4cffca3 100644 (file)
@@ -4098,17 +4098,16 @@ inline_forbidden_p (tree fndecl)
 static bool
 function_attribute_inlinable_p (const_tree fndecl)
 {
-  if (targetm.attribute_table)
+  for (auto scoped_attributes : targetm.attribute_table)
     {
       const_tree a;
 
       for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
        {
          const_tree name = get_attribute_name (a);
-         int i;
 
-         for (i = 0; targetm.attribute_table[i].name != NULL; i++)
-           if (is_attribute_p (targetm.attribute_table[i].name, name))
+         for (const attribute_spec &attribute : scoped_attributes->attributes)
+           if (is_attribute_p (attribute.name, name))
              return targetm.function_attribute_inlinable_p (fndecl);
        }
     }