aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ada/gcc-interface/gigi.h2
-rw-r--r--gcc/ada/gcc-interface/misc.cc7
-rw-r--r--gcc/ada/gcc-interface/utils.cc8
-rw-r--r--gcc/attribs.cc221
-rw-r--r--gcc/attribs.h12
-rw-r--r--gcc/c-family/c-attribs.cc20
-rw-r--r--gcc/c-family/c-common.h4
-rw-r--r--gcc/c/c-decl.cc12
-rw-r--r--gcc/c/c-objc-common.h14
-rw-r--r--gcc/c/c-tree.h2
-rw-r--r--gcc/config/aarch64/aarch64.cc7
-rw-r--r--gcc/config/alpha/alpha.cc7
-rw-r--r--gcc/config/arc/arc.cc74
-rw-r--r--gcc/config/arm/arm.cc15
-rw-r--r--gcc/config/avr/avr.cc7
-rw-r--r--gcc/config/bfin/bfin.cc7
-rw-r--r--gcc/config/bpf/bpf.cc9
-rw-r--r--gcc/config/csky/csky.cc7
-rw-r--r--gcc/config/epiphany/epiphany.cc7
-rw-r--r--gcc/config/gcn/gcn.cc8
-rw-r--r--gcc/config/h8300/h8300.cc7
-rw-r--r--gcc/config/i386/i386-options.cc10
-rw-r--r--gcc/config/i386/i386-options.h2
-rw-r--r--gcc/config/i386/i386.cc5
-rw-r--r--gcc/config/ia64/ia64.cc15
-rw-r--r--gcc/config/loongarch/loongarch.cc8
-rw-r--r--gcc/config/m32c/m32c.cc7
-rw-r--r--gcc/config/m32r/m32r.cc7
-rw-r--r--gcc/config/m68k/m68k.cc7
-rw-r--r--gcc/config/mcore/mcore.cc7
-rw-r--r--gcc/config/microblaze/microblaze.cc7
-rw-r--r--gcc/config/mips/mips.cc7
-rw-r--r--gcc/config/msp430/msp430.cc8
-rw-r--r--gcc/config/nds32/nds32.cc9
-rw-r--r--gcc/config/nvptx/nvptx.cc7
-rw-r--r--gcc/config/riscv/riscv.cc9
-rw-r--r--gcc/config/rl78/rl78.cc7
-rw-r--r--gcc/config/rs6000/rs6000.cc13
-rw-r--r--gcc/config/rx/rx.cc7
-rw-r--r--gcc/config/s390/s390.cc9
-rw-r--r--gcc/config/sh/sh.cc7
-rw-r--r--gcc/config/sparc/sparc.cc7
-rw-r--r--gcc/config/stormy16/stormy16.cc7
-rw-r--r--gcc/config/v850/v850.cc7
-rw-r--r--gcc/config/visium/visium.cc7
-rw-r--r--gcc/cp/cp-objcp-common.h15
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/tree.cc16
-rw-r--r--gcc/d/d-attribs.cc35
-rw-r--r--gcc/d/d-lang.cc8
-rw-r--r--gcc/d/d-tree.h4
-rw-r--r--gcc/doc/tm.texi33
-rw-r--r--gcc/fortran/f95-lang.cc14
-rw-r--r--gcc/jit/dummy-frontend.cc32
-rw-r--r--gcc/langhooks-def.h6
-rw-r--r--gcc/langhooks.h4
-rw-r--r--gcc/lto/lto-lang.cc30
-rw-r--r--gcc/plugin.h3
-rw-r--r--gcc/target-def.h14
-rw-r--r--gcc/target.def35
-rw-r--r--gcc/tree-inline.cc7
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[] =
+{
+ &lto_gnu_attribute_table,
+ &lto_format_attribute_table
};
enum built_in_attribute
@@ -1463,10 +1477,8 @@ static void lto_init_ts (void)
#define LANG_HOOKS_EH_PERSONALITY lto_eh_personality
/* Attribute hooks. */
-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE lto_attribute_table
-#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE lto_format_attribute_table
+#undef LANG_HOOKS_ATTRIBUTE_TABLE
+#define LANG_HOOKS_ATTRIBUTE_TABLE lto_attribute_table
#undef LANG_HOOKS_BEGIN_SECTION
#define LANG_HOOKS_BEGIN_SECTION lto_obj_begin_section
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);
}
}