Projects
openEuler:24.03:SP1:Everything
gcc
_service:tar_scm:0172-Backport-SME-Allow-target...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0172-Backport-SME-Allow-target-attributes-in-non-gnu-name.patch of Package gcc
From 82d654912e3671055034e789a8f7110f6d87d447 Mon Sep 17 00:00:00 2001 From: Richard Sandiford <richard.sandiford@arm.com> Date: Sat, 2 Dec 2023 13:49:52 +0000 Subject: [PATCH 073/157] [Backport][SME] Allow target attributes in non-gnu namespaces Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=7fa24687aa3a683fd105ce5ff6b176f48dca3b6c 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. --- gcc/ada/gcc-interface/gigi.h | 2 +- gcc/ada/gcc-interface/misc.cc | 7 +- gcc/ada/gcc-interface/utils.cc | 8 +- gcc/attribs.cc | 221 ++++++++++++---------------- gcc/attribs.h | 12 +- gcc/c-family/c-attribs.cc | 20 ++- gcc/c-family/c-common.h | 4 +- gcc/c/c-decl.cc | 12 +- gcc/c/c-objc-common.h | 14 +- gcc/c/c-tree.h | 2 + gcc/config/aarch64/aarch64.cc | 7 +- gcc/config/alpha/alpha.cc | 7 +- gcc/config/arc/arc.cc | 74 +++++----- gcc/config/arm/arm.cc | 15 +- gcc/config/avr/avr.cc | 7 +- gcc/config/bfin/bfin.cc | 7 +- gcc/config/bpf/bpf.cc | 9 +- gcc/config/csky/csky.cc | 7 +- gcc/config/epiphany/epiphany.cc | 7 +- gcc/config/gcn/gcn.cc | 8 +- gcc/config/h8300/h8300.cc | 7 +- gcc/config/i386/i386-options.cc | 10 +- gcc/config/i386/i386-options.h | 2 +- gcc/config/i386/i386.cc | 5 + gcc/config/ia64/ia64.cc | 15 +- gcc/config/m32c/m32c.cc | 7 +- gcc/config/m32r/m32r.cc | 7 +- gcc/config/m68k/m68k.cc | 7 +- gcc/config/mcore/mcore.cc | 7 +- gcc/config/microblaze/microblaze.cc | 7 +- gcc/config/mips/mips.cc | 7 +- gcc/config/msp430/msp430.cc | 8 +- gcc/config/nds32/nds32.cc | 9 +- gcc/config/nvptx/nvptx.cc | 7 +- gcc/config/riscv/riscv.cc | 9 +- gcc/config/rl78/rl78.cc | 7 +- gcc/config/rs6000/rs6000.cc | 13 +- gcc/config/rx/rx.cc | 7 +- gcc/config/s390/s390.cc | 9 +- gcc/config/sh/sh.cc | 7 +- gcc/config/sparc/sparc.cc | 7 +- gcc/config/stormy16/stormy16.cc | 7 +- gcc/config/v850/v850.cc | 7 +- gcc/config/visium/visium.cc | 7 +- gcc/cp/cp-objcp-common.h | 15 +- gcc/cp/cp-tree.h | 3 +- gcc/cp/tree.cc | 16 +- gcc/d/d-attribs.cc | 35 ++--- gcc/d/d-lang.cc | 8 +- gcc/d/d-tree.h | 4 +- gcc/doc/tm.texi | 33 ++++- gcc/fortran/f95-lang.cc | 14 +- gcc/jit/dummy-frontend.cc | 32 ++-- gcc/langhooks-def.h | 6 +- gcc/langhooks.h | 4 +- gcc/lto/lto-lang.cc | 30 ++-- gcc/plugin.h | 3 +- gcc/target-def.h | 14 ++ gcc/target.def | 35 ++++- gcc/tree-inline.cc | 7 +- 60 files changed, 491 insertions(+), 403 deletions(-) diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index bd559d176..6ababfcbb 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -349,7 +349,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 2caa83ff8..8dd055772 100644 --- a/gcc/ada/gcc-interface/misc.cc +++ b/gcc/ada/gcc-interface/misc.cc @@ -1339,6 +1339,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 @@ -1404,7 +1409,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 049cf74eb..ef8524fa9 100644 --- a/gcc/ada/gcc-interface/utils.cc +++ b/gcc/ada/gcc-interface/utils.cc @@ -134,7 +134,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 } */ @@ -207,9 +207,11 @@ const struct attribute_spec gnat_internal_attribute_table[] = fake_attribute_handler, NULL }, { "format_arg", 1, 1, false, true, true, false, 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 16d05b1da..656ea739e 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 @@ -280,7 +262,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) @@ -292,22 +274,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 ()); } } @@ -327,27 +310,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); @@ -2551,10 +2525,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. @@ -2569,55 +2539,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 5b6f63ede..0856f98fb 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 111a33f40..d5c0392b7 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -282,7 +282,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 } */ @@ -554,23 +554,31 @@ const struct attribute_spec c_common_attribute_table[] = { "*dealloc", 1, 2, true, false, false, false, handle_dealloc_attribute, NULL }, { "tainted_args", 0, 0, true, false, false, false, - handle_tainted_args_attribute, NULL }, - { NULL, 0, 0, false, false, false, false, NULL, NULL } + handle_tainted_args_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 3d5b9c40e..d1503c5a7 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -819,8 +819,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 619a20909..9d87a8cdb 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -4460,7 +4460,7 @@ handle_nodiscard_attribute (tree *node, tree name, tree /*args*/, return NULL_TREE; } /* Table of supported standard (C2x) 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 } */ @@ -4471,8 +4471,12 @@ const struct attribute_spec std_attribute_table[] = { "maybe_unused", 0, 0, false, false, false, false, handle_unused_attribute, NULL }, { "nodiscard", 0, 1, false, false, false, false, - handle_nodiscard_attribute, NULL }, - { NULL, 0, 0, false, false, false, false, NULL, NULL } + handle_nodiscard_attribute, NULL } +}; + +const scoped_attribute_specs std_attribute_table = +{ + nullptr, std_attributes }; /* Create the predefined scalar types of C, @@ -4488,8 +4492,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 0b60df975..bc3dded23 100644 --- a/gcc/c/c-objc-common.h +++ b/gcc/c/c-objc-common.h @@ -70,11 +70,15 @@ along with GCC; see the file COPYING3. If not see #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 c70f0ba5a..654bd4094 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -835,6 +835,8 @@ set_c_expr_source_range (c_expr *expr, /* In c-fold.cc */ extern vec<tree> incomplete_record_decls; +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 4194dfc70..114252a3c 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -2986,7 +2986,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 } */ @@ -2997,9 +2997,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 } +}); /* An ISA extension in the co-processor and main instruction set space. */ struct aarch64_option_extension diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc index 66c17149d..7fb491918 100644 --- a/gcc/config/alpha/alpha.cc +++ b/gcc/config/alpha/alpha.cc @@ -7475,14 +7475,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 fbc17e684..1c6adcab4 100644 --- a/gcc/config/arc/arc.cc +++ b/gcc/config/arc/arc.cc @@ -230,44 +230,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); @@ -819,6 +781,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 c72e9c0b0..3bdc7e18e 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -329,7 +329,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 } */ @@ -377,8 +377,17 @@ static const struct attribute_spec arm_attribute_table[] = arm_handle_cmse_nonsecure_entry, NULL }, { "cmse_nonsecure_call", 0, 0, true, 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 1b5a95410..7b37278ca 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -9723,7 +9723,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 } */ @@ -9748,9 +9748,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 b2a9142f5..fbc5c84d1 100644 --- a/gcc/config/bfin/bfin.cc +++ b/gcc/config/bfin/bfin.cc @@ -4895,7 +4895,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 } */ @@ -4920,9 +4920,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 6a0e3bbca..0343af9c7 100644 --- a/gcc/config/bpf/bpf.cc +++ b/gcc/config/bpf/bpf.cc @@ -146,7 +146,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, @@ -159,11 +159,8 @@ static const struct attribute_spec bpf_attribute_table[] = /* CO-RE support: attribute to mark that all accesses to the declared struct/union/array should be recorded. */ { "preserve_access_index", 0, -1, false, true, false, true, - bpf_handle_preserve_access_index_attribute, NULL }, - - /* The last attribute spec is set to be NULL. */ - { NULL, 0, 0, false, false, false, false, NULL, NULL } -}; + bpf_handle_preserve_access_index_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 e315e09a8..b511fafe5 100644 --- a/gcc/config/csky/csky.cc +++ b/gcc/config/csky/csky.cc @@ -211,16 +211,15 @@ const int csky_dbx_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 62636b1ec..8a7c0a988 100644 --- a/gcc/config/epiphany/epiphany.cc +++ b/gcc/config/epiphany/epiphany.cc @@ -460,7 +460,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 } */ @@ -470,9 +470,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 e2cbdd1ac..0b049abcc 100644 --- a/gcc/config/gcn/gcn.cc +++ b/gcc/config/gcn/gcn.cc @@ -363,14 +363,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 78cf15f15..a0fa689de 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 86932d719..991661fe4 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -3875,7 +3875,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 } */ @@ -3955,10 +3955,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 ce4034f62..a7bdb22c0 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 83a0d8abb..ade965927 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -24293,6 +24293,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 f9fb681a3..b9ced1c46 100644 --- a/gcc/config/ia64/ia64.cc +++ b/gcc/config/ia64/ia64.cc @@ -357,7 +357,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 } */ @@ -369,8 +369,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/m32c/m32c.cc b/gcc/config/m32c/m32c.cc index 11ca9a43a..a8f6523df 100644 --- a/gcc/config/m32c/m32c.cc +++ b/gcc/config/m32c/m32c.cc @@ -2996,7 +2996,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 }, @@ -3004,9 +3004,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 bca768172..78a17f0a1 100644 --- a/gcc/config/m32r/m32r.cc +++ b/gcc/config/m32r/m32r.cc @@ -111,15 +111,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 62898dafe..effb6db8d 100644 --- a/gcc/config/m68k/m68k.cc +++ b/gcc/config/m68k/m68k.cc @@ -360,7 +360,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 } */ @@ -369,9 +369,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 28e707496..e497b0f44 100644 --- a/gcc/config/mcore/mcore.cc +++ b/gcc/config/mcore/mcore.cc @@ -150,16 +150,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 f32effecf..6b14d3e29 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 02d11ddbf..5474ca152 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -607,7 +607,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 }, @@ -629,9 +629,8 @@ static const struct attribute_spec mips_attribute_table[] = { { "use_shadow_register_set", 0, 1, false, true, true, false, 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 }, - { NULL, 0, 0, false, false, false, false, NULL, NULL } -}; + { "use_debug_exception_return", 0, 0, false, true, true, 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 7a378ceac..f58855978 100644 --- a/gcc/config/msp430/msp430.cc +++ b/gcc/config/msp430/msp430.cc @@ -2055,7 +2055,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 } */ @@ -2073,10 +2073,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 27530495f..519b11e4c 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 7f2103ba6..9a3e418f4 100644 --- a/gcc/config/nvptx/nvptx.cc +++ b/gcc/config/nvptx/nvptx.cc @@ -5817,16 +5817,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 9cf79beba..f5a27bdc9 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -336,7 +336,7 @@ static tree riscv_handle_fndecl_attribute (tree *, tree, tree, int, bool *); static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *); /* 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, @@ -347,11 +347,8 @@ static const struct attribute_spec riscv_attribute_table[] = riscv_handle_fndecl_attribute, NULL }, /* This attribute generates prologue/epilogue for interrupt handlers. */ { "interrupt", 0, 1, false, true, true, false, - riscv_handle_type_attribute, NULL }, - - /* The last attribute spec is set to be NULL. */ - { NULL, 0, 0, false, false, false, false, NULL, NULL } -}; + riscv_handle_type_attribute, 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 b3727c0a8..97386c7ea 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 55d4ce751..46e3d1a12 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -1276,7 +1276,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 } */ @@ -1293,7 +1293,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 412a3a354..2f1178b00 100644 --- a/gcc/config/rx/rx.cc +++ b/gcc/config/rx/rx.cc @@ -2759,7 +2759,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. */ @@ -2770,9 +2770,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 f1599a5c5..dcdf7dad0 100644 --- a/gcc/config/s390/s390.cc +++ b/gcc/config/s390/s390.cc @@ -1247,7 +1247,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, @@ -1263,11 +1263,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 74d61c43b..5717b7ab8 100644 --- a/gcc/config/sh/sh.cc +++ b/gcc/config/sh/sh.cc @@ -328,7 +328,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 } */ @@ -347,9 +347,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 27db12e6b..61bf302db 100644 --- a/gcc/config/sparc/sparc.cc +++ b/gcc/config/sparc/sparc.cc @@ -719,13 +719,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 fabf09ab9..3adc0212a 100644 --- a/gcc/config/stormy16/stormy16.cc +++ b/gcc/config/stormy16/stormy16.cc @@ -2202,7 +2202,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. */ @@ -2211,9 +2211,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 c7d432990..b7bbfb810 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 35b46ced9..b572603bb 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 3c04e5c02..ff0d0883a 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 64b3196d1..52d19faa3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7897,7 +7897,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 a7933ad2c..6cfc7a2d7 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -5004,7 +5004,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 } */ @@ -5012,11 +5012,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 } */ @@ -5031,10 +5035,11 @@ const struct attribute_spec std_attribute_table[] = { "unlikely", 0, 0, false, false, false, false, handle_likeliness_attribute, attr_cold_hot_exclusions }, { "noreturn", 0, 0, true, false, false, false, - handle_noreturn_attribute, attr_noreturn_exclusions }, - { NULL, 0, 0, false, false, false, false, NULL, NULL } + handle_noreturn_attribute, attr_noreturn_exclusions } }; +const scoped_attribute_specs std_attribute_table = { nullptr, std_attributes }; + /* Handle an "init_priority" attribute; arguments as in struct attribute_spec.handler. */ static tree @@ -5617,7 +5622,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 c271de0c7..e402c0c11 100644 --- a/gcc/d/d-attribs.cc +++ b/gcc/d/d-attribs.cc @@ -157,7 +157,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), @@ -183,11 +183,15 @@ const attribute_spec d_langhook_common_attribute_table[] = handle_type_generic_attribute, NULL), ATTR_SPEC ("fn spec", 1, 1, false, true, true, false, handle_fnspec_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), @@ -223,9 +227,12 @@ const attribute_spec d_langhook_attribute_table[] = d_handle_restrict_attribute, NULL), ATTR_SPEC ("used", 0, 0, true, false, false, false, d_handle_used_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. */ @@ -270,20 +277,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 f078f24fc..da9d6d4a2 100644 --- a/gcc/d/d-lang.cc +++ b/gcc/d/d-lang.cc @@ -1938,6 +1938,12 @@ d_enum_underlying_base_type (const_tree type) return TREE_TYPE (type); } +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 @@ -1949,7 +1955,6 @@ d_enum_underlying_base_type (const_tree type) #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 @@ -1981,7 +1986,6 @@ d_enum_underlying_base_type (const_tree type) #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 aedbdd80a..d4245b63b 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -496,8 +496,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 4f93facf7..95d96ce1b 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10427,12 +10427,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 468a0b7e3..27ffc7511 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 }; #undef LANG_HOOKS_NAME diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc index 84ff359bf..5f9f5336c 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. */ @@ -722,10 +736,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 e22639517..11998e40f 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -151,9 +151,7 @@ extern void lhd_finalize_early_debug (void); #define LANG_HOOKS_FINALIZE_EARLY_DEBUG lhd_finalize_early_debug /* 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 \ @@ -365,8 +363,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 4731f089a..5954f58e8 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -530,9 +530,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 8d58d924d..601e92e86 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 @@ -1453,10 +1467,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 ff999c405..e29651d35 100644 --- a/gcc/plugin.h +++ b/gcc/plugin.h @@ -198,8 +198,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 f81f8fe3b..70fb393f3 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -114,6 +114,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 60096c60c..6cdc09fc2 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -2199,15 +2199,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 f50dbbc52..67879c2c8 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -4105,17 +4105,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); } } -- 2.33.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2