diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2023-12-02 13:49:52 +0000 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2023-12-02 13:49:52 +0000 |
commit | 7fa24687aa3a683fd105ce5ff6b176f48dca3b6c (patch) | |
tree | 1cd05c38aedc6093e9f839317bca7ac35f4071ae /gcc | |
parent | 193ef02a7f4f3e5349ad9cf8d3d4df466a99b677 (diff) | |
download | gcc-7fa24687aa3a683fd105ce5ff6b176f48dca3b6c.zip gcc-7fa24687aa3a683fd105ce5ff6b176f48dca3b6c.tar.gz gcc-7fa24687aa3a683fd105ce5ff6b176f48dca3b6c.tar.bz2 |
Allow target attributes in non-gnu namespaces
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.
Diffstat (limited to 'gcc')
61 files changed, 494 insertions, 408 deletions
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index eb5496f..63ccf31 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -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 diff --git a/gcc/ada/gcc-interface/misc.cc b/gcc/ada/gcc-interface/misc.cc index 7d6d446..01e8267 100644 --- a/gcc/ada/gcc-interface/misc.cc +++ b/gcc/ada/gcc-interface/misc.cc @@ -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 diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc index e7b5c77..f46454d 100644 --- a/gcc/ada/gcc-interface/utils.cc +++ b/gcc/ada/gcc-interface/utils.cc @@ -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 diff --git a/gcc/attribs.cc b/gcc/attribs.cc index c7209c2..8ad9b3b 100644 --- a/gcc/attribs.cc +++ b/gcc/attribs.cc @@ -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 diff --git a/gcc/attribs.h b/gcc/attribs.h index 84a4365..fdeebff 100644 --- a/gcc/attribs.h +++ b/gcc/attribs.h @@ -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); diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index 2b20e58..45af074 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -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 diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 3f772db..cb9b6f3 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -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. diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index d388e12..248d1bb 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -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); diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h index 63aff70..426d938 100644 --- a/gcc/c/c-objc-common.h +++ b/gcc/c/c-objc-common.h @@ -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 diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index c6f38ec..d0bdc3d 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -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); diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 0f83ec0..fca64da 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -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 { diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc index db6b34b..6aa9378 100644 --- a/gcc/config/alpha/alpha.cc +++ b/gcc/config/alpha/alpha.cc @@ -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, diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc index 70ee410..3f4eb5a 100644 --- a/gcc/config/arc/arc.cc +++ b/gcc/config/arc/arc.cc @@ -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 diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index 25a1ad7..5cb35e8 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -332,7 +332,7 @@ static rtx_insn *thumb1_md_asm_adjust (vec<rtx> &, vec<rtx> &, static const char *arm_identify_fpu_from_isa (sbitmap); /* 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 }; /* Initialize the GCC target structure. */ diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index a297f4e..3af9ca8 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -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 diff --git a/gcc/config/bfin/bfin.cc b/gcc/config/bfin/bfin.cc index 5718bab..c02136f 100644 --- a/gcc/config/bfin/bfin.cc +++ b/gcc/config/bfin/bfin.cc @@ -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 } +}); /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to tell the assembler to generate pointers to function descriptors in diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc index ffd83a7..f7a5c77 100644 --- a/gcc/config/bpf/bpf.cc +++ b/gcc/config/bpf/bpf.cc @@ -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 diff --git a/gcc/config/csky/csky.cc b/gcc/config/csky/csky.cc index 731f47c..ac089fe 100644 --- a/gcc/config/csky/csky.cc +++ b/gcc/config/csky/csky.cc @@ -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. */ diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc index 68e748c..e10e64d 100644 --- a/gcc/config/epiphany/epiphany.cc +++ b/gcc/config/epiphany/epiphany.cc @@ -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. */ diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc index 22d2b6e..0781c2a 100644 --- a/gcc/config/gcn/gcn.cc +++ b/gcc/config/gcn/gcn.cc @@ -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. */ diff --git a/gcc/config/h8300/h8300.cc b/gcc/config/h8300/h8300.cc index 4bbb1b7..5936cdc 100644 --- a/gcc/config/h8300/h8300.cc +++ b/gcc/config/h8300/h8300.cc @@ -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 diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index fb8638a..8776592 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -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" diff --git a/gcc/config/i386/i386-options.h b/gcc/config/i386/i386-options.h index 6866606..6274c59 100644 --- a/gcc/config/i386/i386-options.h +++ b/gcc/config/i386/i386-options.h @@ -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 */ diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 9390f52..0f91ee7 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -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 diff --git a/gcc/config/ia64/ia64.cc b/gcc/config/ia64/ia64.cc index c241e1a..f7766c2 100644 --- a/gcc/config/ia64/ia64.cc +++ b/gcc/config/ia64/ia64.cc @@ -358,7 +358,7 @@ static bool ia64_expand_vec_perm_const_1 (struct expand_vec_perm_d *d); /* 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. */ diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index f89c346..3545e66 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -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) diff --git a/gcc/config/m32c/m32c.cc b/gcc/config/m32c/m32c.cc index e18efc3..c63c75a 100644 --- a/gcc/config/m32c/m32c.cc +++ b/gcc/config/m32c/m32c.cc @@ -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 diff --git a/gcc/config/m32r/m32r.cc b/gcc/config/m32r/m32r.cc index 63a1798..1a9c8ef 100644 --- a/gcc/config/m32r/m32r.cc +++ b/gcc/config/m32r/m32r.cc @@ -112,15 +112,14 @@ static HOST_WIDE_INT m32r_starting_frame_offset (void); /* 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 } +}); /* Initialize the GCC target structure. */ #undef TARGET_ATTRIBUTE_TABLE diff --git a/gcc/config/m68k/m68k.cc b/gcc/config/m68k/m68k.cc index 145a92d..001cf5b 100644 --- a/gcc/config/m68k/m68k.cc +++ b/gcc/config/m68k/m68k.cc @@ -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; diff --git a/gcc/config/mcore/mcore.cc b/gcc/config/mcore/mcore.cc index 6f1d7af..ca67254 100644 --- a/gcc/config/mcore/mcore.cc +++ b/gcc/config/mcore/mcore.cc @@ -151,16 +151,15 @@ static bool mcore_modes_tieable_p (machine_mode, machine_mode); /* 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 } +}); /* Initialize the GCC target structure. */ #undef TARGET_ASM_EXTERNAL_LIBCALL diff --git a/gcc/config/microblaze/microblaze.cc b/gcc/config/microblaze/microblaze.cc index 60ad551..3ea177b 100644 --- a/gcc/config/microblaze/microblaze.cc +++ b/gcc/config/microblaze/microblaze.cc @@ -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); diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc index cbd7d9b..9180dbb 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -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 } +}); /* A table describing all the processors GCC knows about; see mips-cpus.def for details. */ diff --git a/gcc/config/msp430/msp430.cc b/gcc/config/msp430/msp430.cc index 061a9c7..85f499f 100644 --- a/gcc/config/msp430/msp430.cc +++ b/gcc/config/msp430/msp430.cc @@ -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 diff --git a/gcc/config/nds32/nds32.cc b/gcc/config/nds32/nds32.cc index 1f8de2a..e0a7398 100644 --- a/gcc/config/nds32/nds32.cc +++ b/gcc/config/nds32/nds32.cc @@ -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 } +}); /* ------------------------------------------------------------------------ */ diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc index 570bcc7..992d005 100644 --- a/gcc/config/nvptx/nvptx.cc +++ b/gcc/config/nvptx/nvptx.cc @@ -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 } +}); /* Limit vector alignments to BIGGEST_ALIGNMENT. */ diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 58060b8..3f111fa 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -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[] = { diff --git a/gcc/config/rl78/rl78.cc b/gcc/config/rl78/rl78.cc index 7f13e83..5d8fddb 100644 --- a/gcc/config/rl78/rl78.cc +++ b/gcc/config/rl78/rl78.cc @@ -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 } +}); diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index cee22c3..5386470 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -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 }; #ifndef TARGET_PROFILE_KERNEL diff --git a/gcc/config/rx/rx.cc b/gcc/config/rx/rx.cc index 245c6a4..0754e28 100644 --- a/gcc/config/rx/rx.cc +++ b/gcc/config/rx/rx.cc @@ -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. */ diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc index 0a969ec..384fdb9 100644 --- a/gcc/config/s390/s390.cc +++ b/gcc/config/s390/s390.cc @@ -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. */ diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc index 6ec2eec..8c378b2 100644 --- a/gcc/config/sh/sh.cc +++ b/gcc/config/sh/sh.cc @@ -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); -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 } +}); /* Initialize the GCC target structure. */ #undef TARGET_ATTRIBUTE_TABLE diff --git a/gcc/config/sparc/sparc.cc b/gcc/config/sparc/sparc.cc index e90739d..c09dbcd 100644 --- a/gcc/config/sparc/sparc.cc +++ b/gcc/config/sparc/sparc.cc @@ -721,13 +721,12 @@ static HARD_REG_SET sparc_zero_call_used_regs (HARD_REG_SET); #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 char sparc_hard_reg_printed[8]; diff --git a/gcc/config/stormy16/stormy16.cc b/gcc/config/stormy16/stormy16.cc index 1088715..071043b 100644 --- a/gcc/config/stormy16/stormy16.cc +++ b/gcc/config/stormy16/stormy16.cc @@ -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. */ diff --git a/gcc/config/v850/v850.cc b/gcc/config/v850/v850.cc index 416c284..50c91c6 100644 --- a/gcc/config/v850/v850.cc +++ b/gcc/config/v850/v850.cc @@ -3114,7 +3114,7 @@ v850_adjust_insn_length (rtx_insn *insn, int length) /* 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 } +}); static void v850_option_override (void) diff --git a/gcc/config/visium/visium.cc b/gcc/config/visium/visium.cc index 5fadbc8..4a1877c 100644 --- a/gcc/config/visium/visium.cc +++ b/gcc/config/visium/visium.cc @@ -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); diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index 5b175b0..b53d11e 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -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 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b9adc17..9979c5d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index 5279579..e0b9d51 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -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) diff --git a/gcc/d/d-attribs.cc b/gcc/d/d-attribs.cc index c0dc0e2..f641105 100644 --- a/gcc/d/d-attribs.cc +++ b/gcc/d/d-attribs.cc @@ -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; } diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc index 61fc160..dcbffec 100644 --- a/gcc/d/d-lang.cc +++ b/gcc/d/d-lang.cc @@ -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 diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index d19c3f5..46a2873 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -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); diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index ac50b07..7c5d2e5 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -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}) diff --git a/gcc/fortran/f95-lang.cc b/gcc/fortran/f95-lang.cc index 350e6e3..99dd762 100644 --- a/gcc/fortran/f95-lang.cc +++ b/gcc/fortran/f95-lang.cc @@ -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, diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc index a729086..61cc0e1 100644 --- a/gcc/jit/dummy-frontend.cc +++ b/gcc/jit/dummy-frontend.cc @@ -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 diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index c6d1852..c9cb657 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -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, \ diff --git a/gcc/langhooks.h b/gcc/langhooks.h index cca7528..2785a00 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -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; diff --git a/gcc/lto/lto-lang.cc b/gcc/lto/lto-lang.cc index 00bd3de..41de35a 100644 --- a/gcc/lto/lto-lang.cc +++ b/gcc/lto/lto-lang.cc @@ -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[] = +{ + <o_gnu_attribute_table, + <o_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 diff --git a/gcc/plugin.h b/gcc/plugin.h index ee0a53e..f306adf 100644 --- a/gcc/plugin.h +++ b/gcc/plugin.h @@ -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 */ diff --git a/gcc/target-def.h b/gcc/target-def.h index 847698a..d03b039 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -118,6 +118,20 @@ #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" diff --git a/gcc/target.def b/gcc/target.def index eae7959..c6562ed 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -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. */ diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc index 5984716..e6d55305 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -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); } } |