aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Macleod <amacleod@redhat.com>2016-02-02 19:33:11 +0000
committerAndrew Macleod <amacleod@redhat.com>2016-02-02 19:33:11 +0000
commit5218814a83efd098d0f1732f7491c801351036da (patch)
tree1ebe5b1fdeaca03c1423de7e67ea989bc1f82363
parent0845df6be640024cc7f6dece396252b65e78975a (diff)
split attributes into types and non-types
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/ttype-7@233091 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ada/gcc-interface/utils.c60
-rw-r--r--gcc/attribs.c456
-rw-r--r--gcc/attribs.h1
-rw-r--r--gcc/c-family/c-common.c766
-rw-r--r--gcc/c/c-decl.c8
-rw-r--r--gcc/config/alpha/alpha.c9
-rw-r--r--gcc/config/arc/arc.c15
-rw-r--r--gcc/config/arm/arm.c122
-rw-r--r--gcc/config/avr/avr.c61
-rw-r--r--gcc/config/bfin/bfin.c76
-rw-r--r--gcc/config/cr16/cr16.c8
-rw-r--r--gcc/config/darwin.h8
-rw-r--r--gcc/config/epiphany/epiphany.c16
-rw-r--r--gcc/config/h8300/h8300.c20
-rw-r--r--gcc/config/i386/cygming.h6
-rw-r--r--gcc/config/i386/i386.c98
-rw-r--r--gcc/config/ia64/ia64.c14
-rw-r--r--gcc/config/m32c/m32c.c29
-rw-r--r--gcc/config/m32r/m32r.c10
-rw-r--r--gcc/config/m68k/m68k.c12
-rw-r--r--gcc/config/mcore/mcore.c12
-rw-r--r--gcc/config/mep/mep.c113
-rw-r--r--gcc/config/microblaze/microblaze.c16
-rw-r--r--gcc/config/mips/mips.c30
-rw-r--r--gcc/config/msp430/msp430.c35
-rw-r--r--gcc/config/nds32/nds32.c27
-rw-r--r--gcc/config/nvptx/nvptx.c9
-rw-r--r--gcc/config/rl78/rl78.c12
-rw-r--r--gcc/config/rs6000/rs6000.c69
-rw-r--r--gcc/config/rx/rx.c14
-rw-r--r--gcc/config/s390/s390.c6
-rw-r--r--gcc/config/sh/sh.c22
-rw-r--r--gcc/config/sol2.h4
-rw-r--r--gcc/config/sparc/sparc.c6
-rw-r--r--gcc/config/spu/spu.c12
-rw-r--r--gcc/config/stormy16/stormy16.c24
-rw-r--r--gcc/config/v850/v850.c16
-rw-r--r--gcc/cp/decl.c8
-rw-r--r--gcc/cp/decl2.c15
-rw-r--r--gcc/cp/tree.c209
-rw-r--r--gcc/fortran/f95-lang.c10
-rw-r--r--gcc/java/lang.c5
-rw-r--r--gcc/lto/lto-lang.c43
-rw-r--r--gcc/testsuite/g++.dg/plugin/attribute_plugin.c2
-rw-r--r--gcc/tree-core.h6
-rw-r--r--gcc/tree.c65
-rw-r--r--gcc/tree.h3
47 files changed, 1539 insertions, 1049 deletions
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 0ce571a8d6a..77d26d93d90 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -105,44 +105,46 @@ static tree fake_attribute_handler (tree *, tree, tree, int, bool *);
this minimal set of attributes to accommodate the needs of builtins. */
const struct attribute_spec gnat_internal_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
{ "const", 0, 0, true, false, false, handle_const_attribute,
- false },
+ NULL, false },
{ "nothrow", 0, 0, true, false, false, handle_nothrow_attribute,
- false },
+ NULL, false },
{ "pure", 0, 0, true, false, false, handle_pure_attribute,
- false },
+ NULL, false },
{ "no vops", 0, 0, true, false, false, handle_novops_attribute,
- false },
- { "nonnull", 0, -1, false, true, true, handle_nonnull_attribute,
- false },
- { "sentinel", 0, 1, false, true, true, handle_sentinel_attribute,
- false },
+ NULL, false },
+ { "nonnull", 0, -1, false, true, true, NULL,
+ handle_nonnull_attribute, false },
+ { "sentinel", 0, 1, false, true, true, NULL,
+ handle_sentinel_attribute, false },
{ "noreturn", 0, 0, true, false, false, handle_noreturn_attribute,
- false },
+ NULL, false },
{ "leaf", 0, 0, true, false, false, handle_leaf_attribute,
- false },
+ NULL, false },
{ "always_inline",0, 0, true, false, false, handle_always_inline_attribute,
- false },
+ NULL, false },
{ "malloc", 0, 0, true, false, false, handle_malloc_attribute,
- false },
- { "type generic", 0, 0, false, true, true, handle_type_generic_attribute,
- false },
+ NULL, false },
+ { "type generic", 0, 0, false, true, true, NULL,
+ handle_type_generic_attribute, false },
- { "vector_size", 1, 1, false, true, false, handle_vector_size_attribute,
- false },
- { "vector_type", 0, 0, false, true, false, handle_vector_type_attribute,
- false },
- { "may_alias", 0, 0, false, true, false, NULL, false },
+ { "vector_size", 1, 1, false, true, false, NULL,
+ handle_vector_size_attribute, false },
+ { "vector_type", 0, 0, false, true, false, NULL,
+ handle_vector_type_attribute, false },
+ { "may_alias", 0, 0, false, true, false, NULL, NULL, false },
/* ??? format and format_arg are heavy and not supported, which actually
prevents support for stdio builtins, which we however declare as part
of the common builtins.def contents. */
- { "format", 3, 3, false, true, true, fake_attribute_handler, false },
- { "format_arg", 1, 1, false, true, true, fake_attribute_handler, false },
+ { "format", 3, 3, false, true, true, NULL,
+ fake_attribute_handler, false },
+ { "format_arg", 1, 1, false, true, true, NULL,
+ fake_attribute_handler, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Associates a GNAT tree node to a GCC tree node. It is used in
@@ -1718,7 +1720,7 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
efficient packing in almost all cases. */
#ifdef TARGET_MS_BITFIELD_LAYOUT
if (TARGET_MS_BITFIELD_LAYOUT && TYPE_PACKED (record_type))
- decl_attributes (&record_type,
+ type_attributes (&record_type,
tree_cons (get_identifier ("gcc_struct"),
NULL_TREE, NULL_TREE),
ATTR_FLAG_TYPE_IN_PLACE);
@@ -2766,8 +2768,12 @@ process_attributes (tree *node, struct attrib **attr_list, bool in_place,
{
case ATTR_MACHINE_ATTRIBUTE:
Sloc_to_locus (Sloc (gnat_node), &input_location);
- decl_attributes (node, tree_cons (attr->name, attr->args, NULL_TREE),
- in_place ? ATTR_FLAG_TYPE_IN_PLACE : 0);
+ if (TYPE_P (*node))
+ type_attributes (node, tree_cons (attr->name, attr->args, NULL_TREE),
+ in_place ? ATTR_FLAG_TYPE_IN_PLACE : 0);
+ else
+ decl_attributes (node, tree_cons (attr->name, attr->args, NULL_TREE),
+ in_place ? ATTR_FLAG_TYPE_IN_PLACE : 0);
break;
case ATTR_LINK_ALIAS:
diff --git a/gcc/attribs.c b/gcc/attribs.c
index 16996e9f283..e7e3009e4c3 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -94,7 +94,7 @@ static bool attributes_initialized = false;
static const struct attribute_spec empty_attribute_table[] =
{
- { NULL, 0, 0, false, false, false, NULL, false }
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Return base name of the attribute. Ie '__attr__' is turned into 'attr'.
@@ -343,15 +343,269 @@ get_attribute_namespace (const_tree attr)
return get_identifier ("gnu");
}
+/* Lookup the spec for attribute A using FLAGS, and issue any warnings or
+ errors as appropriate. Return NULL or a valid spec. */
+
+static const struct attribute_spec *
+process_attribute_spec (tree a, int flags)
+{
+ tree name = get_attribute_name (a);
+ tree ns = get_attribute_namespace (a);
+ tree args = TREE_VALUE (a);
+ const struct attribute_spec *spec = lookup_scoped_attribute_spec (ns, name);
+
+ if (spec == NULL)
+ {
+ if (!(flags & (int) ATTR_FLAG_BUILT_IN))
+ {
+ if (ns == NULL_TREE || !cxx11_attribute_p (a))
+ warning (OPT_Wattributes, "%qE attribute directive ignored",
+ name);
+ else
+ warning (OPT_Wattributes,
+ "%<%E::%E%> scoped attribute directive ignored",
+ ns, name);
+ }
+ return NULL;
+ }
+ else if (list_length (args) < spec->min_length
+ || (spec->max_length >= 0
+ && list_length (args) > spec->max_length))
+ {
+ error ("wrong number of arguments specified for %qE attribute",
+ name);
+ return NULL;
+ }
+ gcc_assert (is_attribute_p (spec->name, name));
+ return spec;
+}
+
+/* Perform the type specific processing of type_attribute. This is factored
+ out to allow decl_attributes() to process underlying types when necessary.
+ In those cases, DECL_NODE is passed in so the decl can have re-layout
+ called. SPEC is the already verified attribute spec structure. Otherwise
+ the parameters match those of type_attribute. */
+
+static tree
+finalize_type_attribute (tree *node, const struct attribute_spec *spec,
+ tree a, tree returned_attrs, int flags,
+ tree *decl_node = NULL)
+{
+ bool no_add_attrs = 0;
+ int fn_ptr_quals = 0;
+ tree fn_ptr_tmp = NULL_TREE;
+ tree name = get_attribute_name (a);
+ tree args = TREE_VALUE (a);
+ tree *anode = node;
+
+ gcc_checking_assert (TYPE_P (*node));
+
+ if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
+ && TREE_CODE (*anode) != METHOD_TYPE)
+ {
+ if (TREE_CODE (*anode) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
+ || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
+ {
+ /* OK, this is a bit convoluted. We can't just make a copy
+ of the pointer type and modify its TREE_TYPE, because if
+ we change the attributes of the target type the pointer
+ type needs to have a different TYPE_MAIN_VARIANT. So we
+ pull out the target type now, frob it as appropriate, and
+ rebuild the pointer type later.
+
+ This would all be simpler if attributes were part of the
+ declarator, grumble grumble. */
+ fn_ptr_tmp = TREE_TYPE (*anode);
+ fn_ptr_quals = TYPE_QUALS (*anode);
+ anode = &fn_ptr_tmp;
+ flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
+ }
+ else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
+ {
+ /* Pass on this attribute to be tried again. */
+ returned_attrs = tree_cons (name, args, returned_attrs);
+ return returned_attrs;
+ }
+
+ if (TREE_CODE (*anode) != FUNCTION_TYPE
+ && TREE_CODE (*anode) != METHOD_TYPE)
+ {
+ warning (OPT_Wattributes,
+ "%qE attribute only applies to function types",
+ name);
+ return returned_attrs;
+ }
+ }
+
+ if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
+ && TYPE_SIZE (*anode) != NULL_TREE)
+ {
+ warning (OPT_Wattributes,
+ "type attributes ignored after type is already defined");
+ return returned_attrs;
+ }
+
+ if (spec->type_handler != NULL)
+ {
+ int cxx11_flag =
+ cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0;
+
+ returned_attrs = chainon ((*spec->type_handler) (anode, name, args,
+ flags|cxx11_flag,
+ &no_add_attrs),
+ returned_attrs);
+ }
+
+ /* If there was a decl change the layout in case anything changed. */
+ if (decl_node && spec->type_required
+ && (TREE_CODE (*decl_node) == VAR_DECL
+ || TREE_CODE (*decl_node) == PARM_DECL
+ || TREE_CODE (*decl_node) == RESULT_DECL))
+ relayout_decl (*decl_node);
+
+ if (!no_add_attrs)
+ {
+ tree old_attrs;
+ tree a;
+
+ old_attrs = TYPE_ATTRIBUTES (*anode);
+
+ for (a = lookup_attribute (spec->name, old_attrs);
+ a != NULL_TREE;
+ a = lookup_attribute (spec->name, TREE_CHAIN (a)))
+ {
+ if (simple_cst_equal (TREE_VALUE (a), args) == 1)
+ break;
+ }
+
+ if (a == NULL_TREE)
+ {
+ if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
+ {
+ TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
+ /* If this is the main variant, also push the attributes
+ out to the other variants. */
+ if (*anode == TYPE_MAIN_VARIANT (*anode))
+ {
+ tree variant;
+ for (variant = *anode; variant;
+ variant = TYPE_NEXT_VARIANT (variant))
+ {
+ if (TYPE_ATTRIBUTES (variant) == old_attrs)
+ TYPE_ATTRIBUTES (variant)
+ = TYPE_ATTRIBUTES (*anode);
+ else if (!lookup_attribute
+ (spec->name, TYPE_ATTRIBUTES (variant)))
+ TYPE_ATTRIBUTES (variant) = tree_cons
+ (name, args, TYPE_ATTRIBUTES (variant));
+ }
+ }
+ }
+ else
+ *anode = build_type_attribute_variant (*anode,
+ tree_cons (name, args,
+ old_attrs));
+ }
+ }
+
+ if (fn_ptr_tmp)
+ {
+ /* Rebuild the function pointer type and put it in the
+ appropriate place. */
+ fn_ptr_tmp = build_pointer_type (fn_ptr_tmp);
+ if (fn_ptr_quals)
+ fn_ptr_tmp = build_qualified_type (fn_ptr_tmp, fn_ptr_quals);
+ if (decl_node)
+ TREE_TYPE (*decl_node) = fn_ptr_tmp;
+ else
+ {
+ gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
+ *node = fn_ptr_tmp;
+ }
+ }
+ return returned_attrs;
+
+}
+
+/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
+ which is a TYPE. A copy should be created unless ATTR_FLAG_TYPE_IN_PLACE
+ is set in FLAGS. FLAGS gives further information, in the form of a
+ bitwise OR of flags in enum attribute_flags from tree.h.
+ Depending on these flags, some attributes may be returned to be
+ applied at a later stage (for example, to apply a decl attribute to the
+ declaration rather than to its type). */
+
+tree
+type_attributes (tree *node, tree attributes, int flags)
+{
+ tree a;
+ tree returned_attrs = NULL_TREE;
+
+ if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node)
+ return NULL_TREE;
+
+ gcc_checking_assert (TYPE_P (*node));
+
+ if (!attributes_initialized)
+ init_attributes ();
+
+ targetm.insert_attributes (*node, &attributes);
+
+ for (a = attributes; a; a = TREE_CHAIN (a))
+ {
+ tree name = get_attribute_name (a);
+ tree args = TREE_VALUE (a);
+ const struct attribute_spec *spec = process_attribute_spec (a, flags);
+
+ if (!spec)
+ continue;
+
+ if (cxx11_attribute_p (a) && !(flags & ATTR_FLAG_TYPE_IN_PLACE))
+ {
+ /* This is a c++11 attribute that appertains to a
+ type-specifier, outside of the definition of, a class
+ type. Ignore it. */
+ warning (OPT_Wattributes, "attribute ignored");
+ inform (input_location,
+ "an attribute that appertains to a type-specifier "
+ "is ignored");
+ continue;
+ }
+
+ if (spec->decl_required)
+ {
+ if (flags & ((int) ATTR_FLAG_DECL_NEXT
+ | (int) ATTR_FLAG_FUNCTION_NEXT
+ | (int) ATTR_FLAG_ARRAY_NEXT))
+ {
+ /* Pass on this attribute to be tried again. */
+ returned_attrs = tree_cons (name, args, returned_attrs);
+ continue;
+ }
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute does not apply to types",
+ name);
+ continue;
+ }
+ }
+
+ returned_attrs = finalize_type_attribute (node, spec, a, returned_attrs,
+ flags);
+ }
+
+ return returned_attrs;
+}
+
+
+
/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
- which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL,
- it should be modified in place; if a TYPE, a copy should be created
- unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS. FLAGS gives further
- information, in the form of a bitwise OR of flags in enum attribute_flags
- from tree.h. Depending on these flags, some attributes may be
- returned to be applied at a later stage (for example, to apply
- a decl attribute to the declaration rather than to its type). */
+ which is a DECL (including a TYPE_DECL) it should be modified in place;
+ FLAGS gives further information, in the form of a bitwise OR of flags in
+ enum attribute_flags from tree.h. Depending on these flags, some
+ attributes may be returned to be applied at a later stage. */
tree
decl_attributes (tree *node, tree attributes, int flags)
@@ -362,6 +616,8 @@ decl_attributes (tree *node, tree attributes, int flags)
if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node)
return NULL_TREE;
+ gcc_checking_assert (DECL_P (*node));
+
if (!attributes_initialized)
init_attributes ();
@@ -418,155 +674,47 @@ decl_attributes (tree *node, tree attributes, int flags)
for (a = attributes; a; a = TREE_CHAIN (a))
{
- tree ns = get_attribute_namespace (a);
tree name = get_attribute_name (a);
tree args = TREE_VALUE (a);
tree *anode = node;
- const struct attribute_spec *spec =
- lookup_scoped_attribute_spec (ns, name);
+ const struct attribute_spec *spec = process_attribute_spec (a, flags);
bool no_add_attrs = 0;
- int fn_ptr_quals = 0;
- tree fn_ptr_tmp = NULL_TREE;
- if (spec == NULL)
- {
- if (!(flags & (int) ATTR_FLAG_BUILT_IN))
- {
- if (ns == NULL_TREE || !cxx11_attribute_p (a))
- warning (OPT_Wattributes, "%qE attribute directive ignored",
- name);
- else
- warning (OPT_Wattributes,
- "%<%E::%E%> scoped attribute directive ignored",
- ns, name);
- }
- continue;
- }
- else if (list_length (args) < spec->min_length
- || (spec->max_length >= 0
- && list_length (args) > spec->max_length))
- {
- error ("wrong number of arguments specified for %qE attribute",
- name);
- continue;
- }
- gcc_assert (is_attribute_p (spec->name, name));
+ gcc_assert (DECL_P (*node));
- if (TYPE_P (*node)
- && cxx11_attribute_p (a)
- && !(flags & ATTR_FLAG_TYPE_IN_PLACE))
- {
- /* This is a c++11 attribute that appertains to a
- type-specifier, outside of the definition of, a class
- type. Ignore it. */
- if (warning (OPT_Wattributes, "attribute ignored"))
- inform (input_location,
- "an attribute that appertains to a type-specifier "
- "is ignored");
- continue;
- }
-
- if (spec->decl_required && !DECL_P (*anode))
- {
- if (flags & ((int) ATTR_FLAG_DECL_NEXT
- | (int) ATTR_FLAG_FUNCTION_NEXT
- | (int) ATTR_FLAG_ARRAY_NEXT))
- {
- /* Pass on this attribute to be tried again. */
- returned_attrs = tree_cons (name, args, returned_attrs);
- continue;
- }
- else
- {
- warning (OPT_Wattributes, "%qE attribute does not apply to types",
- name);
- continue;
- }
- }
+ if (!spec)
+ continue;
/* If we require a type, but were passed a decl, set up to make a
new type and update the one in the decl. ATTR_FLAG_TYPE_IN_PLACE
would have applied if we'd been passed a type, but we cannot modify
the decl's type in place here. */
- if (spec->type_required && DECL_P (*anode))
+ if (spec->type_required)
{
anode = &TREE_TYPE (*anode);
flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
- }
-
- if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
- && TREE_CODE (*anode) != METHOD_TYPE)
- {
- if (TREE_CODE (*anode) == POINTER_TYPE
- && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
- {
- /* OK, this is a bit convoluted. We can't just make a copy
- of the pointer type and modify its TREE_TYPE, because if
- we change the attributes of the target type the pointer
- type needs to have a different TYPE_MAIN_VARIANT. So we
- pull out the target type now, frob it as appropriate, and
- rebuild the pointer type later.
-
- This would all be simpler if attributes were part of the
- declarator, grumble grumble. */
- fn_ptr_tmp = TREE_TYPE (*anode);
- fn_ptr_quals = TYPE_QUALS (*anode);
- anode = &fn_ptr_tmp;
- flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
- }
- else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
- {
- /* Pass on this attribute to be tried again. */
- returned_attrs = tree_cons (name, args, returned_attrs);
- continue;
- }
-
- if (TREE_CODE (*anode) != FUNCTION_TYPE
- && TREE_CODE (*anode) != METHOD_TYPE)
- {
- warning (OPT_Wattributes,
- "%qE attribute only applies to function types",
- name);
- continue;
- }
- }
-
- if (TYPE_P (*anode)
- && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
- && TYPE_SIZE (*anode) != NULL_TREE)
- {
- warning (OPT_Wattributes, "type attributes ignored after type is already defined");
+ returned_attrs = finalize_type_attribute (anode, spec, a,
+ returned_attrs, flags,
+ node);
continue;
}
- if (spec->handler != NULL)
+ if (spec->decl_handler != NULL)
{
int cxx11_flag =
cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0;
-
- returned_attrs = chainon ((*spec->handler) (anode, name, args,
- flags|cxx11_flag,
- &no_add_attrs),
+ returned_attrs = chainon ((*spec->decl_handler) (anode, name, args,
+ flags|cxx11_flag,
+ &no_add_attrs),
returned_attrs);
}
- /* Layout the decl in case anything changed. */
- if (spec->type_required && DECL_P (*node)
- && (TREE_CODE (*node) == VAR_DECL
- || TREE_CODE (*node) == PARM_DECL
- || TREE_CODE (*node) == RESULT_DECL))
- relayout_decl (*node);
-
if (!no_add_attrs)
{
tree old_attrs;
tree a;
- if (DECL_P (*anode))
- old_attrs = DECL_ATTRIBUTES (*anode);
- else
- old_attrs = TYPE_ATTRIBUTES (*anode);
+ old_attrs = DECL_ATTRIBUTES (*anode);
for (a = lookup_attribute (spec->name, old_attrs);
a != NULL_TREE;
@@ -577,55 +725,11 @@ decl_attributes (tree *node, tree attributes, int flags)
}
if (a == NULL_TREE)
- {
- /* This attribute isn't already in the list. */
- if (DECL_P (*anode))
- DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
- else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
- {
- TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
- /* If this is the main variant, also push the attributes
- out to the other variants. */
- if (*anode == TYPE_MAIN_VARIANT (*anode))
- {
- tree variant;
- for (variant = *anode; variant;
- variant = TYPE_NEXT_VARIANT (variant))
- {
- if (TYPE_ATTRIBUTES (variant) == old_attrs)
- TYPE_ATTRIBUTES (variant)
- = TYPE_ATTRIBUTES (*anode);
- else if (!lookup_attribute
- (spec->name, TYPE_ATTRIBUTES (variant)))
- TYPE_ATTRIBUTES (variant) = tree_cons
- (name, args, TYPE_ATTRIBUTES (variant));
- }
- }
- }
- else
- *anode = build_type_attribute_variant (*anode,
- tree_cons (name, args,
- old_attrs));
- }
+ /* This attribute isn't already in the list. */
+ DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
}
- if (fn_ptr_tmp)
- {
- /* Rebuild the function pointer type and put it in the
- appropriate place. */
- fn_ptr_tmp = build_pointer_type (fn_ptr_tmp);
- if (fn_ptr_quals)
- fn_ptr_tmp = build_qualified_type (fn_ptr_tmp, fn_ptr_quals);
- if (DECL_P (*node))
- TREE_TYPE (*node) = fn_ptr_tmp;
- else
- {
- gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
- *node = fn_ptr_tmp;
- }
- }
}
-
return returned_attrs;
}
@@ -670,7 +774,7 @@ get_attribute_name (const_tree attr)
void
apply_tm_attr (tree fndecl, tree attr)
{
- decl_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0);
+ type_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0);
}
/* Makes a function attribute of the form NAME(ARG_NAME) and chains
diff --git a/gcc/attribs.h b/gcc/attribs.h
index 9e64a7a7e80..2b3e5c58f83 100644
--- a/gcc/attribs.h
+++ b/gcc/attribs.h
@@ -31,6 +31,7 @@ extern void init_attributes (void);
from tree.h. Depending on these flags, some attributes may be
returned to be applied at a later stage (for example, to apply
a decl attribute to the declaration rather than to its type). */
+extern tree type_attributes (tree *, tree, int);
extern tree decl_attributes (tree *, tree, int);
extern bool cxx11_attribute_p (const_tree);
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 378afaec6b5..34c7f2de8fb 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -303,7 +303,8 @@ static tree check_case_value (location_t, tree);
static bool check_case_bounds (location_t, tree, tree, tree *, tree *,
bool *);
-static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
+static tree handle_packed_decl_attribute (tree *, tree, tree, int, bool *);
+static tree handle_packed_type_attribute (tree *, tree, tree, int, bool *);
static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
static tree handle_common_attribute (tree *, tree, tree, int, bool *);
static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
@@ -327,29 +328,37 @@ static tree handle_artificial_attribute (tree *, tree, tree, int, bool *);
static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
static tree handle_error_attribute (tree *, tree, tree, int, bool *);
static tree handle_used_attribute (tree *, tree, tree, int, bool *);
-static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
+static tree handle_unused_decl_attribute (tree *, tree, tree, int, bool *);
+static tree handle_unused_type_attribute (tree *, tree, tree, int, bool *);
static tree handle_externally_visible_attribute (tree *, tree, tree, int,
bool *);
static tree handle_no_reorder_attribute (tree *, tree, tree, int,
bool *);
static tree handle_const_attribute (tree *, tree, tree, int, bool *);
-static tree handle_transparent_union_attribute (tree *, tree, tree,
- int, bool *);
-static tree handle_scalar_storage_order_attribute (tree *, tree, tree,
- int, bool *);
+static tree handle_transparent_union_decl_attribute (tree *, tree, tree,
+ int, bool *);
+static tree handle_transparent_union_type_attribute (tree *, tree, tree,
+ int, bool *);
+static tree handle_scalar_storage_order_type_attribute (tree *, tree, tree,
+ int, bool *);
+static tree handle_scalar_storage_order_decl_attribute (tree *, tree, tree,
+ int, bool *);
static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
static tree handle_section_attribute (tree *, tree, tree, int, bool *);
-static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
+static tree handle_aligned_type_attribute (tree *, tree, tree, int, bool *);
+static tree handle_aligned_decl_attribute (tree *, tree, tree, int, bool *);
static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ;
static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *);
static tree handle_ifunc_attribute (tree *, tree, tree, int, bool *);
static tree handle_alias_attribute (tree *, tree, tree, int, bool *);
static tree handle_weakref_attribute (tree *, tree, tree, int, bool *) ;
-static tree handle_visibility_attribute (tree *, tree, tree, int,
- bool *);
+static tree handle_visibility_decl_attribute (tree *, tree, tree, int,
+ bool *);
+static tree handle_visibility_type_attribute (tree *, tree, tree, int,
+ bool *);
static tree handle_tls_model_attribute (tree *, tree, tree, int,
bool *);
static tree handle_no_instrument_function_attribute (tree *, tree,
@@ -359,11 +368,14 @@ static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
bool *);
static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
-static tree handle_tm_attribute (tree *, tree, tree, int, bool *);
+static tree handle_tm_decl_attribute (tree *, tree, tree, int, bool *);
+static tree handle_tm_type_attribute (tree *, tree, tree, int, bool *);
static tree handle_tm_wrap_attribute (tree *, tree, tree, int, bool *);
static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
-static tree handle_deprecated_attribute (tree *, tree, tree, int,
- bool *);
+static tree handle_deprecated_type_attribute (tree *, tree, tree, int,
+ bool *);
+static tree handle_deprecated_decl_attribute (tree *, tree, tree, int,
+ bool *);
static tree handle_vector_size_attribute (tree *, tree, tree, int,
bool *);
static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
@@ -382,7 +394,8 @@ static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
static tree ignore_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
-static tree handle_warn_unused_attribute (tree *, tree, tree, int, bool *);
+static tree handle_warn_unused_decl_attribute (tree *, tree, tree, int, bool *);
+static tree handle_warn_unused_type_attribute (tree *, tree, tree, int, bool *);
static tree handle_returns_nonnull_attribute (tree *, tree, tree, int, bool *);
static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int,
bool *);
@@ -645,196 +658,214 @@ const unsigned int num_c_common_reswords =
Current list of processed common attributes: nonnull. */
const struct attribute_spec c_common_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
{ "packed", 0, 0, false, false, false,
- handle_packed_attribute , false},
+ handle_packed_decl_attribute,
+ handle_packed_type_attribute, false},
{ "nocommon", 0, 0, true, false, false,
- handle_nocommon_attribute, false},
+ handle_nocommon_attribute, NULL, false},
{ "common", 0, 0, true, false, false,
- handle_common_attribute, false },
+ handle_common_attribute, NULL, false },
/* FIXME: logically, noreturn attributes should be listed as
"false, true, true" and apply to function types. But implementing this
would require all the places in the compiler that use TREE_THIS_VOLATILE
on a decl to identify non-returning functions to be located and fixed
to check the function type instead. */
{ "noreturn", 0, 0, true, false, false,
- handle_noreturn_attribute, false },
+ handle_noreturn_attribute, NULL, false },
{ "volatile", 0, 0, true, false, false,
- handle_noreturn_attribute, false },
+ handle_noreturn_attribute, NULL, false },
{ "stack_protect", 0, 0, true, false, false,
- handle_stack_protect_attribute, false },
+ handle_stack_protect_attribute, NULL, false },
{ "noinline", 0, 0, true, false, false,
- handle_noinline_attribute, false },
+ handle_noinline_attribute, NULL, false },
{ "noclone", 0, 0, true, false, false,
- handle_noclone_attribute, false },
+ handle_noclone_attribute, NULL, false },
{ "no_icf", 0, 0, true, false, false,
- handle_noicf_attribute, false },
+ handle_noicf_attribute, NULL, false },
{ "leaf", 0, 0, true, false, false,
- handle_leaf_attribute, false },
+ handle_leaf_attribute, NULL, false },
{ "always_inline", 0, 0, true, false, false,
- handle_always_inline_attribute, false },
+ handle_always_inline_attribute, NULL, false },
{ "gnu_inline", 0, 0, true, false, false,
- handle_gnu_inline_attribute, false },
+ handle_gnu_inline_attribute, NULL, false },
{ "artificial", 0, 0, true, false, false,
- handle_artificial_attribute, false },
+ handle_artificial_attribute, NULL, false },
{ "flatten", 0, 0, true, false, false,
- handle_flatten_attribute, false },
+ handle_flatten_attribute, NULL, false },
{ "used", 0, 0, true, false, false,
- handle_used_attribute, false },
+ handle_used_attribute, NULL, false },
{ "unused", 0, 0, false, false, false,
- handle_unused_attribute, false },
+ handle_unused_decl_attribute,
+ handle_unused_type_attribute, false },
{ "externally_visible", 0, 0, true, false, false,
- handle_externally_visible_attribute, false },
+ handle_externally_visible_attribute, NULL,
+ false },
{ "no_reorder", 0, 0, true, false, false,
- handle_no_reorder_attribute, false },
+ handle_no_reorder_attribute, NULL, false },
/* The same comments as for noreturn attributes apply to const ones. */
{ "const", 0, 0, true, false, false,
- handle_const_attribute, false },
+ handle_const_attribute, NULL, false },
{ "scalar_storage_order", 1, 1, false, false, false,
- handle_scalar_storage_order_attribute, false },
+ handle_scalar_storage_order_decl_attribute,
+ handle_scalar_storage_order_type_attribute,
+ false },
{ "transparent_union", 0, 0, false, false, false,
- handle_transparent_union_attribute, false },
+ handle_transparent_union_decl_attribute,
+ handle_transparent_union_type_attribute, false },
{ "constructor", 0, 1, true, false, false,
- handle_constructor_attribute, false },
+ handle_constructor_attribute, NULL, false },
{ "destructor", 0, 1, true, false, false,
- handle_destructor_attribute, false },
- { "mode", 1, 1, false, true, false,
+ handle_destructor_attribute, NULL, false },
+ { "mode", 1, 1, false, true, false, NULL,
handle_mode_attribute, false },
{ "section", 1, 1, true, false, false,
- handle_section_attribute, false },
+ handle_section_attribute, NULL, false },
{ "aligned", 0, 1, false, false, false,
- handle_aligned_attribute, false },
+ handle_aligned_decl_attribute,
+ handle_aligned_type_attribute, false },
{ "weak", 0, 0, true, false, false,
- handle_weak_attribute, false },
+ handle_weak_attribute, NULL, false },
{ "noplt", 0, 0, true, false, false,
- handle_noplt_attribute, false },
+ handle_noplt_attribute, NULL, false },
{ "ifunc", 1, 1, true, false, false,
- handle_ifunc_attribute, false },
+ handle_ifunc_attribute, NULL, false },
{ "alias", 1, 1, true, false, false,
- handle_alias_attribute, false },
+ handle_alias_attribute, NULL, false },
{ "weakref", 0, 1, true, false, false,
- handle_weakref_attribute, false },
+ handle_weakref_attribute, NULL, false },
{ "no_instrument_function", 0, 0, true, false, false,
handle_no_instrument_function_attribute,
- false },
+ NULL, false },
{ "malloc", 0, 0, true, false, false,
- handle_malloc_attribute, false },
+ handle_malloc_attribute, NULL, false },
{ "returns_twice", 0, 0, true, false, false,
- handle_returns_twice_attribute, false },
+ handle_returns_twice_attribute, NULL, false },
{ "no_stack_limit", 0, 0, true, false, false,
- handle_no_limit_stack_attribute, false },
+ handle_no_limit_stack_attribute, NULL, false },
{ "pure", 0, 0, true, false, false,
- handle_pure_attribute, false },
+ handle_pure_attribute, NULL, false },
{ "transaction_callable", 0, 0, false, true, false,
- handle_tm_attribute, false },
+ handle_tm_decl_attribute,
+ handle_tm_type_attribute, false },
{ "transaction_unsafe", 0, 0, false, true, false,
- handle_tm_attribute, true },
+ handle_tm_decl_attribute,
+ handle_tm_type_attribute, true },
{ "transaction_safe", 0, 0, false, true, false,
- handle_tm_attribute, true },
+ handle_tm_decl_attribute,
+ handle_tm_type_attribute, true },
{ "transaction_safe_dynamic", 0, 0, true, false, false,
- handle_tm_attribute, false },
+ handle_tm_decl_attribute,
+ handle_tm_type_attribute, false },
{ "transaction_may_cancel_outer", 0, 0, false, true, false,
- handle_tm_attribute, false },
+ handle_tm_decl_attribute,
+ handle_tm_type_attribute, false },
/* ??? These two attributes didn't make the transition from the
Intel language document to the multi-vendor language document. */
{ "transaction_pure", 0, 0, false, true, false,
- handle_tm_attribute, false },
+ handle_tm_decl_attribute,
+ handle_tm_type_attribute, false },
{ "transaction_wrap", 1, 1, true, false, false,
- handle_tm_wrap_attribute, false },
+ handle_tm_wrap_attribute, NULL, false },
/* For internal use (marking of builtins) only. The name contains space
to prevent its usage in source code. */
{ "no vops", 0, 0, true, false, false,
- handle_novops_attribute, false },
+ handle_novops_attribute, NULL, false },
{ "deprecated", 0, 1, false, false, false,
- handle_deprecated_attribute, false },
+ handle_deprecated_decl_attribute,
+ handle_deprecated_type_attribute, false },
{ "vector_size", 1, 1, false, true, false,
- handle_vector_size_attribute, false },
+ NULL, handle_vector_size_attribute, false },
{ "visibility", 1, 1, false, false, false,
- handle_visibility_attribute, false },
+ handle_visibility_decl_attribute,
+ handle_visibility_type_attribute, false },
{ "tls_model", 1, 1, true, false, false,
- handle_tls_model_attribute, false },
+ handle_tls_model_attribute, NULL, false },
{ "nonnull", 0, -1, false, true, true,
- handle_nonnull_attribute, false },
+ NULL, handle_nonnull_attribute, false },
{ "nothrow", 0, 0, true, false, false,
- handle_nothrow_attribute, false },
- { "may_alias", 0, 0, false, true, false, NULL, false },
+ handle_nothrow_attribute, NULL, false },
+ { "may_alias", 0, 0, false, true, false, NULL, NULL, false },
{ "cleanup", 1, 1, true, false, false,
- handle_cleanup_attribute, false },
- { "warn_unused_result", 0, 0, false, true, true,
+ handle_cleanup_attribute, NULL, false },
+ { "warn_unused_result", 0, 0, false, true, true, NULL,
handle_warn_unused_result_attribute, false },
{ "sentinel", 0, 1, false, true, true,
- handle_sentinel_attribute, false },
+ NULL, handle_sentinel_attribute, false },
/* For internal use (marking of builtins) only. The name contains space
to prevent its usage in source code. */
{ "type generic", 0, 0, false, true, true,
- handle_type_generic_attribute, false },
+ NULL, handle_type_generic_attribute, false },
{ "alloc_size", 1, 2, false, true, true,
- handle_alloc_size_attribute, false },
+ NULL, handle_alloc_size_attribute, false },
{ "cold", 0, 0, true, false, false,
- handle_cold_attribute, false },
+ handle_cold_attribute, NULL, false },
{ "hot", 0, 0, true, false, false,
- handle_hot_attribute, false },
+ handle_hot_attribute, NULL, false },
{ "no_address_safety_analysis",
0, 0, true, false, false,
handle_no_address_safety_analysis_attribute,
- false },
+ NULL, false },
{ "no_sanitize_address", 0, 0, true, false, false,
handle_no_sanitize_address_attribute,
- false },
+ NULL, false },
{ "no_sanitize_thread", 0, 0, true, false, false,
handle_no_sanitize_address_attribute,
- false },
+ NULL, false },
{ "no_sanitize_undefined", 0, 0, true, false, false,
handle_no_sanitize_undefined_attribute,
- false },
+ NULL, false },
{ "warning", 1, 1, true, false, false,
- handle_error_attribute, false },
+ handle_error_attribute, NULL, false },
{ "error", 1, 1, true, false, false,
- handle_error_attribute, false },
+ handle_error_attribute, NULL, false },
{ "target", 1, -1, true, false, false,
- handle_target_attribute, false },
+ handle_target_attribute, NULL, false },
{ "target_clones", 1, -1, true, false, false,
- handle_target_clones_attribute, false },
+ handle_target_clones_attribute, NULL, false },
{ "optimize", 1, -1, true, false, false,
- handle_optimize_attribute, false },
+ handle_optimize_attribute, NULL, false },
/* 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,
- ignore_attribute, false },
+ NULL, ignore_attribute, false },
{ "no_split_stack", 0, 0, true, false, false,
- handle_no_split_stack_attribute, false },
+ handle_no_split_stack_attribute, NULL, false },
/* For internal use (marking of builtins and runtime functions) only.
The name contains space to prevent its usage in source code. */
{ "fn spec", 1, 1, false, true, true,
- handle_fnspec_attribute, false },
+ NULL, handle_fnspec_attribute, false },
{ "warn_unused", 0, 0, false, false, false,
- handle_warn_unused_attribute, false },
+ handle_warn_unused_decl_attribute,
+ handle_warn_unused_type_attribute, false },
{ "returns_nonnull", 0, 0, false, true, true,
- handle_returns_nonnull_attribute, false },
+ NULL, handle_returns_nonnull_attribute, false },
{ "omp declare simd", 0, -1, true, false, false,
- handle_omp_declare_simd_attribute, false },
+ handle_omp_declare_simd_attribute, NULL, false },
{ "cilk simd function", 0, -1, true, false, false,
- handle_omp_declare_simd_attribute, false },
+ handle_omp_declare_simd_attribute, NULL, false },
{ "simd", 0, 1, true, false, false,
- handle_simd_attribute, false },
+ handle_simd_attribute, NULL, false },
{ "omp declare target", 0, 0, true, false, false,
- handle_omp_declare_target_attribute, false },
+ handle_omp_declare_target_attribute, NULL,
+ false },
{ "omp declare target link", 0, 0, true, false, false,
- handle_omp_declare_target_attribute, false },
+ handle_omp_declare_target_attribute, NULL,
+ false },
{ "alloc_align", 1, 1, false, true, true,
- handle_alloc_align_attribute, false },
+ NULL, handle_alloc_align_attribute, false },
{ "assume_aligned", 1, 2, false, true, true,
- handle_assume_aligned_attribute, false },
+ NULL, handle_assume_aligned_attribute, false },
{ "designated_init", 0, 0, false, true, false,
- handle_designated_init_attribute, false },
+ NULL, handle_designated_init_attribute, false },
{ "bnd_variable_size", 0, 0, true, false, false,
- handle_bnd_variable_size_attribute, false },
+ handle_bnd_variable_size_attribute, NULL, false },
{ "bnd_legacy", 0, 0, true, false, false,
- handle_bnd_legacy, false },
+ handle_bnd_legacy, NULL, false },
{ "bnd_instrument", 0, 0, true, false, false,
- handle_bnd_instrument, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ handle_bnd_instrument, NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Give the specifications for the format attributes, used by C and all
@@ -849,10 +880,10 @@ const struct attribute_spec c_common_format_attribute_table[] =
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
affects_type_identity } */
{ "format", 3, 3, false, true, true,
- handle_format_attribute, false },
+ NULL, handle_format_attribute, false },
{ "format_arg", 1, 1, false, true, true,
- handle_format_arg_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ NULL, handle_format_arg_attribute, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Return identifier for address space AS. */
@@ -6553,20 +6584,14 @@ attribute_takes_identifier_p (const_tree attr_id)
/* Attribute handlers common to C front ends. */
-/* Handle a "packed" attribute; arguments as in
+/* Handle a "packed" decl attribute; arguments as in
struct attribute_spec.handler. */
static tree
-handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
- int flags, bool *no_add_attrs)
+handle_packed_decl_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
- if (TYPE_P (*node))
- {
- if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *node = build_variant_type_copy (*node);
- TYPE_PACKED (*node) = 1;
- }
- else if (TREE_CODE (*node) == FIELD_DECL)
+ if (TREE_CODE (*node) == FIELD_DECL)
{
if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT
/* Still pack bitfields. */
@@ -6590,6 +6615,21 @@ handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
return NULL_TREE;
}
+/* Handle a "packed" type attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_packed_type_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args),
+ int flags, bool *ARG_UNUSED (no_add_attrs))
+{
+ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ *node = build_variant_type_copy (*node);
+ TYPE_PACKED (*node) = 1;
+
+ return NULL_TREE;
+}
+
/* Handle a "nocommon" attribute; arguments as in
struct attribute_spec.handler. */
@@ -7018,42 +7058,48 @@ handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
return NULL_TREE;
}
-/* Handle a "unused" attribute; arguments as in
+/* Handle a "unused" decl attribute; arguments as in
struct attribute_spec.handler. */
static tree
-handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
- int flags, bool *no_add_attrs)
+handle_unused_decl_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
- if (DECL_P (*node))
- {
- tree decl = *node;
+ tree decl = *node;
- if (TREE_CODE (decl) == PARM_DECL
- || VAR_OR_FUNCTION_DECL_P (decl)
- || TREE_CODE (decl) == LABEL_DECL
- || TREE_CODE (decl) == TYPE_DECL)
- {
- TREE_USED (decl) = 1;
- if (VAR_P (decl) || TREE_CODE (decl) == PARM_DECL)
- DECL_READ_P (decl) = 1;
- }
- else
- {
- warning (OPT_Wattributes, "%qE attribute ignored", name);
- *no_add_attrs = true;
- }
+ if (TREE_CODE (decl) == PARM_DECL
+ || VAR_OR_FUNCTION_DECL_P (decl)
+ || TREE_CODE (decl) == LABEL_DECL
+ || TREE_CODE (decl) == TYPE_DECL)
+ {
+ TREE_USED (decl) = 1;
+ if (VAR_P (decl) || TREE_CODE (decl) == PARM_DECL)
+ DECL_READ_P (decl) = 1;
}
else
{
- if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *node = build_variant_type_copy (*node);
- TREE_USED (*node) = 1;
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
}
return NULL_TREE;
}
+/* Handle a "unused" type attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_unused_type_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int flags,
+ bool *ARG_UNUSED (no_add_attrs))
+{
+ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ *node = build_variant_type_copy (*node);
+ TREE_USED (*node) = 1;
+
+ return NULL_TREE;
+}
+
/* Handle a "externally_visible" attribute; arguments as in
struct attribute_spec.handler. */
@@ -7137,20 +7183,15 @@ handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
return NULL_TREE;
}
-/* Handle a "scalar_storage_order" attribute; arguments as in
+/* Handle a "scalar_storage_order" type attribute; arguments as in
struct attribute_spec.handler. */
static tree
-handle_scalar_storage_order_attribute (tree *node, tree name, tree args,
- int flags, bool *no_add_attrs)
+handle_scalar_storage_order_type_attribute (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs)
{
tree id = TREE_VALUE (args);
- tree type;
-
- if (TREE_CODE (*node) == TYPE_DECL
- && ! (flags & ATTR_FLAG_CXX11))
- node = &TREE_TYPE (*node);
- type = *node;
+ tree type = *node;
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
{
@@ -7193,22 +7234,36 @@ handle_scalar_storage_order_attribute (tree *node, tree name, tree args,
return NULL_TREE;
}
-/* Handle a "transparent_union" attribute; arguments as in
+/* Handle a "scalar_storage_order" decl attribute; arguments as in
struct attribute_spec.handler. */
static tree
-handle_transparent_union_attribute (tree *node, tree name,
- tree ARG_UNUSED (args), int flags,
- bool *no_add_attrs)
+handle_scalar_storage_order_decl_attribute (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs)
{
- tree type;
+ if (TREE_CODE (*node) == TYPE_DECL && ! (flags & ATTR_FLAG_CXX11))
+ {
+ node = &TREE_TYPE (*node);
+ return handle_scalar_storage_order_type_attribute (node, name, args,
+ flags, no_add_attrs);
+ }
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
+ return NULL_TREE;
+}
- if (TREE_CODE (*node) == TYPE_DECL
- && ! (flags & ATTR_FLAG_CXX11))
- node = &TREE_TYPE (*node);
- type = *node;
+/* Handle a "transparent_union" type attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_transparent_union_type_attribute (tree *node, tree name,
+ tree ARG_UNUSED (args), int flags,
+ bool *no_add_attrs)
+{
+ tree type = *node;
+
+ *no_add_attrs = true;
if (TREE_CODE (type) == UNION_TYPE)
{
@@ -7250,6 +7305,23 @@ handle_transparent_union_attribute (tree *node, tree name,
return NULL_TREE;
}
+/* Handle a "transparent_union" decl attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_transparent_union_decl_attribute (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs)
+{
+ *no_add_attrs = true;
+
+ if (TREE_CODE (*node) == TYPE_DECL && !(flags & ATTR_FLAG_CXX11))
+ return handle_transparent_union_type_attribute (&TREE_TYPE (*node), name,
+ args, flags, no_add_attrs);
+
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ return NULL_TREE;
+}
+
/* Subroutine of handle_{con,de}structor_attribute. Evaluate ARGS to
get the requested priority for a constructor or destructor,
possibly issuing diagnostics for invalid or reserved
@@ -7771,18 +7843,12 @@ check_cxx_fundamental_alignment_constraints (tree node,
return !alignment_too_large_p;
}
-/* Handle a "aligned" attribute; arguments as in
- struct attribute_spec.handler. */
+/* Return the alignment expression from tree_list element ARGS. */
static tree
-handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
- int flags, bool *no_add_attrs)
+get_align_expr (tree args)
{
- tree decl = NULL_TREE;
- tree *type = NULL;
- int is_type = 0;
tree align_expr;
- int i;
if (args)
{
@@ -7794,40 +7860,62 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
else
align_expr = size_int (ATTRIBUTE_ALIGNED_VALUE / BITS_PER_UNIT);
- if (DECL_P (*node))
- {
- decl = *node;
- type = &TREE_TYPE (decl);
- is_type = TREE_CODE (*node) == TYPE_DECL;
- }
- else if (TYPE_P (*node))
- type = node, is_type = 1;
+ return align_expr;
+}
+
+/* Set the type alignment fields of NODE, based on FLAGS to I. */
+
+static void
+handle_aligned_type (tree *node, int flags, int i)
+{
+ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ *node = build_variant_type_copy (*node);
+
+ TYPE_ALIGN (*node) = (1U << i) * BITS_PER_UNIT;
+ TYPE_USER_ALIGN (*node) = 1;
+}
+
+/* Handle a "aligned" type attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_aligned_type_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+ int flags, bool *no_add_attrs)
+{
+ tree align_expr;
+ int i;
+
+ align_expr = get_align_expr (args);
if ((i = check_user_alignment (align_expr, false)) == -1
|| !check_cxx_fundamental_alignment_constraints (*node, i, flags))
*no_add_attrs = true;
- else if (is_type)
- {
- if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- /* OK, modify the type in place. */;
- /* If we have a TYPE_DECL, then copy the type, so that we
- don't accidentally modify a builtin type. See pushdecl. */
- else if (decl && TREE_TYPE (decl) != error_mark_node
- && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
- {
- tree tt = TREE_TYPE (decl);
- *type = build_variant_type_copy (*type);
- DECL_ORIGINAL_TYPE (decl) = tt;
- TYPE_NAME (*type) = decl;
- TREE_USED (*type) = TREE_USED (decl);
- TREE_TYPE (decl) = *type;
- }
- else
- *type = build_variant_type_copy (*type);
+ else
+ handle_aligned_type (node, flags, i);
+
+ return NULL_TREE;
+}
+
+/* Handle a "aligned" decl attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_aligned_decl_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+ int flags, bool *no_add_attrs)
+{
+ tree align_expr;
+ tree decl = *node;
+ int i;
+
+ align_expr = get_align_expr (args);
- TYPE_ALIGN (*type) = (1U << i) * BITS_PER_UNIT;
- TYPE_USER_ALIGN (*type) = 1;
+ if ((i = check_user_alignment (align_expr, false)) == -1
+ || !check_cxx_fundamental_alignment_constraints (*node, i, flags))
+ {
+ *no_add_attrs = true;
}
+ else if (TREE_CODE (*node) == TYPE_DECL)
+ handle_aligned_type (&TREE_TYPE (*node), flags, i);
else if (! VAR_OR_FUNCTION_DECL_P (decl)
&& TREE_CODE (decl) != FIELD_DECL)
{
@@ -8089,58 +8177,11 @@ handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
/* Handle an "visibility" attribute; arguments as in
struct attribute_spec.handler. */
-static tree
-handle_visibility_attribute (tree *node, tree name, tree args,
- int ARG_UNUSED (flags),
- bool *ARG_UNUSED (no_add_attrs))
+static void
+handle_decl_visibility (tree decl, tree id, tree attributes)
{
- tree decl = *node;
- tree id = TREE_VALUE (args);
enum symbol_visibility vis;
- if (TYPE_P (*node))
- {
- if (TREE_CODE (*node) == ENUMERAL_TYPE)
- /* OK */;
- else if (!RECORD_OR_UNION_TYPE_P (*node))
- {
- warning (OPT_Wattributes, "%qE attribute ignored on non-class types",
- name);
- return NULL_TREE;
- }
- else if (TYPE_FIELDS (*node))
- {
- error ("%qE attribute ignored because %qT is already defined",
- name, *node);
- return NULL_TREE;
- }
- }
- else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl))
- {
- warning (OPT_Wattributes, "%qE attribute ignored", name);
- return NULL_TREE;
- }
-
- if (TREE_CODE (id) != STRING_CST)
- {
- error ("visibility argument not a string");
- return NULL_TREE;
- }
-
- /* If this is a type, set the visibility on the type decl. */
- if (TYPE_P (decl))
- {
- decl = TYPE_NAME (decl);
- if (!decl)
- return NULL_TREE;
- if (TREE_CODE (decl) == IDENTIFIER_NODE)
- {
- warning (OPT_Wattributes, "%qE attribute ignored on types",
- name);
- return NULL_TREE;
- }
- }
-
if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
vis = VISIBILITY_DEFAULT;
else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
@@ -8158,9 +8199,6 @@ handle_visibility_attribute (tree *node, tree name, tree args,
if (DECL_VISIBILITY_SPECIFIED (decl)
&& vis != DECL_VISIBILITY (decl))
{
- tree attributes = (TYPE_P (*node)
- ? TYPE_ATTRIBUTES (*node)
- : DECL_ATTRIBUTES (decl));
if (lookup_attribute ("visibility", attributes))
error ("%qD redeclared with different visibility", decl);
else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
@@ -8175,6 +8213,84 @@ handle_visibility_attribute (tree *node, tree name, tree args,
DECL_VISIBILITY (decl) = vis;
DECL_VISIBILITY_SPECIFIED (decl) = 1;
+}
+
+/* Handle a "visibility" decl attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_visibility_decl_attribute (tree *node, tree name, tree args,
+ int ARG_UNUSED (flags),
+ bool *ARG_UNUSED (no_add_attrs))
+{
+ tree decl = *node;
+ tree id = TREE_VALUE (args);
+
+ if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (id) != STRING_CST)
+ {
+ error ("visibility argument not a string");
+ return NULL_TREE;
+ }
+
+ handle_decl_visibility (decl, id, DECL_ATTRIBUTES (decl));
+ /* Go ahead and attach the attribute to the node as well. This is needed
+ so we can determine whether we have VISIBILITY_DEFAULT because the
+ visibility was not specified, or because it was explicitly overridden
+ from the containing scope. */
+
+ return NULL_TREE;
+}
+
+/* Handle a "visibility" type attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_visibility_type_attribute (tree *node, tree name, tree args,
+ int ARG_UNUSED (flags),
+ bool *ARG_UNUSED (no_add_attrs))
+{
+ tree decl;
+ tree id = TREE_VALUE (args);
+
+ if (TREE_CODE (*node) == ENUMERAL_TYPE)
+ /* OK */;
+ else if (!RECORD_OR_UNION_TYPE_P (*node))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored on non-class types",
+ name);
+ return NULL_TREE;
+ }
+ else if (TYPE_FIELDS (*node))
+ {
+ error ("%qE attribute ignored because %qT is already defined",
+ name, *node);
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (id) != STRING_CST)
+ {
+ error ("visibility argument not a string");
+ return NULL_TREE;
+ }
+
+ decl = TYPE_NAME (*node);
+ if (!decl)
+ return NULL_TREE;
+
+ if (TREE_CODE (decl) == IDENTIFIER_NODE)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored on types",
+ name);
+ return NULL_TREE;
+ }
+
+ handle_decl_visibility (decl, id, TYPE_ATTRIBUTES (*node));
/* Go ahead and attach the attribute to the node as well. This is needed
so we can determine whether we have VISIBILITY_DEFAULT because the
@@ -8398,7 +8514,7 @@ handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
tree args, int ARG_UNUSED (flags),
bool *no_add_attrs ATTRIBUTE_UNUSED)
{
- gcc_assert (args
+ gcc_assert (TYPE_P (*node) && args
&& TREE_CODE (TREE_VALUE (args)) == STRING_CST
&& !TREE_CHAIN (args));
return NULL_TREE;
@@ -8452,24 +8568,33 @@ handle_bnd_instrument (tree *node, tree name, tree ARG_UNUSED (args),
return NULL_TREE;
}
-/* Handle a "warn_unused" attribute; arguments as in
+/* Handle a "warn_unused" type attribute; arguments as in
struct attribute_spec.handler. */
static tree
-handle_warn_unused_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
-{
- if (TYPE_P (*node))
- /* Do nothing else, just set the attribute. We'll get at
- it later with lookup_attribute. */
- ;
- else
- {
- warning (OPT_Wattributes, "%qE attribute ignored", name);
- *no_add_attrs = true;
- }
+handle_warn_unused_type_attribute (tree *node ATTRIBUTE_UNUSED,
+ tree name ATTRIBUTE_UNUSED,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED,
+ bool *no_add_attrs ATTRIBUTE_UNUSED)
+{
+ /* Do nothing else, just set the attribute. We'll get at
+ it later with lookup_attribute. */
+ return NULL_TREE;
+}
+/* Handle a "warn_unused" decl attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_warn_unused_decl_attribute (tree *node ATTRIBUTE_UNUSED,
+ tree name ATTRIBUTE_UNUSED,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED,
+ bool *no_add_attrs ATTRIBUTE_UNUSED)
+{
+ /* Do nothing else, just set the attribute. We'll get at
+ it later with lookup_attribute. */
return NULL_TREE;
}
@@ -8727,7 +8852,49 @@ find_tm_attribute (tree list)
processing given by function_type_required. */
static tree
-handle_tm_attribute (tree *node, tree name, tree args,
+handle_tm_decl_attribute (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs)
+{
+ /* Only one path adds the attribute; others don't. */
+ *no_add_attrs = true;
+
+ switch (TREE_CODE (*node))
+ {
+ case FUNCTION_DECL:
+ {
+ /* transaction_safe_dynamic goes on the FUNCTION_DECL, but we also
+ want to set transaction_safe on the type. */
+ gcc_assert (is_attribute_p ("transaction_safe_dynamic", name));
+ if (!TYPE_P (DECL_CONTEXT (*node)))
+ error_at (DECL_SOURCE_LOCATION (*node),
+ "%<transaction_safe_dynamic%> may only be specified for "
+ "a virtual function");
+ *no_add_attrs = false;
+ type_attributes (&TREE_TYPE (*node),
+ build_tree_list (get_identifier ("transaction_safe"),
+ NULL_TREE),
+ 0);
+ break;
+ }
+
+ default:
+ /* If a function is next, pass it on to be tried next. */
+ if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
+ return tree_cons (name, args, NULL);
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle the TM attributes; arguments as in struct attribute_spec.handler.
+ Here we accept only function types, and verify that none of the other
+ function TM attributes are also applied. */
+/* ??? We need to accept class types for C++, but not C. This greatly
+ complicates this function, since we can no longer rely on the extra
+ processing given by function_type_required. */
+
+static tree
+handle_tm_type_attribute (tree *node, tree name, tree args,
int flags, bool *no_add_attrs)
{
/* Only one path adds the attribute; others don't. */
@@ -8755,30 +8922,13 @@ handle_tm_attribute (tree *node, tree name, tree args,
}
break;
- case FUNCTION_DECL:
- {
- /* transaction_safe_dynamic goes on the FUNCTION_DECL, but we also
- want to set transaction_safe on the type. */
- gcc_assert (is_attribute_p ("transaction_safe_dynamic", name));
- if (!TYPE_P (DECL_CONTEXT (*node)))
- error_at (DECL_SOURCE_LOCATION (*node),
- "%<transaction_safe_dynamic%> may only be specified for "
- "a virtual function");
- *no_add_attrs = false;
- decl_attributes (&TREE_TYPE (*node),
- build_tree_list (get_identifier ("transaction_safe"),
- NULL_TREE),
- 0);
- break;
- }
-
case POINTER_TYPE:
{
enum tree_code subcode = TREE_CODE (TREE_TYPE (*node));
if (subcode == FUNCTION_TYPE || subcode == METHOD_TYPE)
{
tree fn_tmp = TREE_TYPE (*node);
- decl_attributes (&fn_tmp, tree_cons (name, args, NULL), 0);
+ type_attributes (&fn_tmp, tree_cons (name, args, NULL), 0);
*node = build_pointer_type (fn_tmp);
break;
}
@@ -8866,18 +9016,14 @@ handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
return NULL_TREE;
}
-/* Handle a "deprecated" attribute; arguments as in
+/* Handle a "deprecated" type attribute; arguments as in
struct attribute_spec.handler. */
static tree
-handle_deprecated_attribute (tree *node, tree name,
- tree args, int flags,
- bool *no_add_attrs)
+handle_deprecated_type_attribute (tree *node, tree ARG_UNUSED (name),
+ tree args, int flags,
+ bool *no_add_attrs)
{
- tree type = NULL_TREE;
- int warn = 0;
- tree what = NULL_TREE;
-
if (!args)
*no_add_attrs = true;
else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
@@ -8886,33 +9032,42 @@ handle_deprecated_attribute (tree *node, tree name,
*no_add_attrs = true;
}
- if (DECL_P (*node))
- {
- tree decl = *node;
- type = TREE_TYPE (decl);
+ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ *node = build_variant_type_copy (*node);
+ TREE_DEPRECATED (*node) = 1;
- if (TREE_CODE (decl) == TYPE_DECL
- || TREE_CODE (decl) == PARM_DECL
- || VAR_OR_FUNCTION_DECL_P (decl)
- || TREE_CODE (decl) == FIELD_DECL
- || TREE_CODE (decl) == CONST_DECL
- || objc_method_decl (TREE_CODE (decl)))
- TREE_DEPRECATED (decl) = 1;
- else
- warn = 1;
- }
- else if (TYPE_P (*node))
+ return NULL_TREE;
+}
+
+/* Handle a "deprecated" decl attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_deprecated_decl_attribute (tree *node, tree ARG_UNUSED (name),
+ tree args, int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ tree decl = *node;
+ tree what = NULL_TREE;
+
+ if (!args)
+ *no_add_attrs = true;
+ else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
{
- if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *node = build_variant_type_copy (*node);
- TREE_DEPRECATED (*node) = 1;
- type = *node;
+ error ("deprecated message is not a string");
+ *no_add_attrs = true;
}
- else
- warn = 1;
- if (warn)
+ if (TREE_CODE (decl) == TYPE_DECL
+ || TREE_CODE (decl) == PARM_DECL
+ || VAR_OR_FUNCTION_DECL_P (decl)
+ || TREE_CODE (decl) == FIELD_DECL
+ || TREE_CODE (decl) == CONST_DECL
+ || objc_method_decl (TREE_CODE (decl)))
+ TREE_DEPRECATED (decl) = 1;
+ else
{
+ tree type = TREE_TYPE (decl);
*no_add_attrs = true;
if (type && TYPE_NAME (type))
{
@@ -8930,7 +9085,6 @@ handle_deprecated_attribute (tree *node, tree name,
return NULL_TREE;
}
-
/* Handle a "vector_size" attribute; arguments as in
struct attribute_spec.handler. */
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index fe7bec0a53a..46414cc3bf5 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -4384,7 +4384,7 @@ groktypename (struct c_type_name *type_name, tree *expr,
DEPRECATED_NORMAL);
/* Apply attributes. */
- decl_attributes (&type, attrs, 0);
+ type_attributes (&type, attrs, 0);
return type;
}
@@ -5696,7 +5696,7 @@ grokdeclarator (const struct c_declarator *declarator,
attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
else if (inner_decl->kind == cdk_array)
attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
- returned_attrs = decl_attributes (&type,
+ returned_attrs = type_attributes (&type,
chainon (returned_attrs, attrs),
attr_flags);
break;
@@ -7612,7 +7612,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
TYPE_SIZE (t) = 0;
- decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
+ type_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
if (pedantic)
{
@@ -8008,7 +8008,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
bool toplevel = (file_scope == current_scope);
struct lang_type *lt;
- decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
+ type_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
/* Calculate the maximum value of any enumerator in this type. */
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index e023d3bc278..736dace3c1a 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -7476,10 +7476,11 @@ common_object_handler (tree *node, tree name ATTRIBUTE_UNUSED,
static const struct attribute_spec vms_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { COMMON_OBJECT, 0, 1, true, false, false, common_object_handler, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
+ { COMMON_OBJECT, 0, 1, true, false, false, common_object_handler, NULL,
+ false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
void
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index b9799a016cb..c6ef61d45af 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -188,20 +188,21 @@ static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
machine specific supported attributes. */
const struct attribute_spec arc_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute, true },
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
+ { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute,
+ NULL, true },
/* 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, NULL, false },
+ { "long_call", 0, 0, false, true, true, NULL, NULL, false },
/* Whereas these functions are always known to reside within the 25 bit
addressing range of unconditionalized bl. */
- { "medium_call", 0, 0, false, true, true, NULL, false },
+ { "medium_call", 0, 0, false, true, true, NULL, NULL, false },
/* And these functions are always known to reside within the 21 bit
addressing range of blcc. */
- { "short_call", 0, 0, false, true, true, NULL, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ { "short_call", 0, 0, false, true, true, NULL, NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
static int arc_comp_type_attributes (const_tree, const_tree);
static void arc_file_start (void);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index d8a2745f86b..2ce56cbffa0 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -131,7 +131,8 @@ static unsigned long arm_isr_value (tree);
static unsigned long arm_compute_func_type (void);
static tree arm_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
static tree arm_handle_pcs_attribute (tree *, tree, tree, int, bool *);
-static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *);
+static tree arm_handle_isr_decl_attribute (tree *, tree, tree, int, bool *);
+static tree arm_handle_isr_type_attribute (tree *, tree, tree, int, bool *);
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *);
#endif
@@ -304,25 +305,26 @@ static void arm_sched_fusion_priority (rtx_insn *, int, int *, int*);
/* Table of machine attributes. */
static const struct attribute_spec arm_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
/* Function calls made to this symbol must be done indirectly, because
it may lie outside of the 26 bit addressing range of a normal function
call. */
- { "long_call", 0, 0, false, true, true, NULL, false },
+ { "long_call", 0, 0, false, true, true, NULL, NULL, false },
/* Whereas these functions are always known to reside within the 26 bit
addressing range. */
- { "short_call", 0, 0, false, true, true, NULL, false },
+ { "short_call", 0, 0, false, true, true, NULL, NULL, false },
/* Specify the procedure call conventions for a function. */
- { "pcs", 1, 1, false, true, true, arm_handle_pcs_attribute,
+ { "pcs", 1, 1, false, true, true, NULL, arm_handle_pcs_attribute,
false },
/* Interrupt Service Routines have special prologue and epilogue requirements. */
- { "isr", 0, 1, false, false, false, arm_handle_isr_attribute,
- false },
- { "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute,
+ { "isr", 0, 1, false, false, false, arm_handle_isr_decl_attribute,
+ arm_handle_isr_type_attribute, false },
+ { "interrupt", 0, 1, false, false, false, arm_handle_isr_decl_attribute,
+ arm_handle_isr_type_attribute,
false },
{ "naked", 0, 0, true, false, false, arm_handle_fndecl_attribute,
- false },
+ NULL, false },
#ifdef ARM_PE
/* ARM/PE has three new attributes:
interfacearm - ?
@@ -333,17 +335,19 @@ static const struct attribute_spec arm_attribute_table[] =
them with spaces. We do NOT support this. Instead, use __declspec
multiple times.
*/
- { "dllimport", 0, 0, true, false, false, NULL, false },
- { "dllexport", 0, 0, true, false, false, NULL, false },
+ { "dllimport", 0, 0, true, false, false, NULL, NULL, false },
+ { "dllexport", 0, 0, true, false, false, NULL, NULL, false },
{ "interfacearm", 0, 0, true, false, false, arm_handle_fndecl_attribute,
- false },
+ NULL, false },
#elif TARGET_DLLIMPORT_DECL_ATTRIBUTES
- { "dllimport", 0, 0, false, false, false, handle_dll_attribute, false },
- { "dllexport", 0, 0, false, false, false, handle_dll_attribute, false },
- { "notshared", 0, 0, false, true, false, arm_handle_notshared_attribute,
- false },
+ { "dllimport", 0, 0, false, false, false, handle_dll_decl_attribute,
+ handle_dll_type_attribute, false },
+ { "dllexport", 0, 0, false, false, false, handle_dll_decl_attribute,
+ handle_dll_type_attribute, false },
+ { "notshared", 0, 0, false, true, false, NULL,
+ arm_handle_notshared_attribute, false },
#endif
- { NULL, 0, 0, false, false, false, NULL, false }
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Initialize the GCC target structure. */
@@ -6452,61 +6456,65 @@ arm_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
return NULL_TREE;
}
-/* Handle an "interrupt" or "isr" attribute;
+/* Handle an "interrupt" or "isr" decl attribute;
+ arguments as in struct attribute_spec.handler. */
+static tree
+arm_handle_isr_decl_attribute (tree *node, tree name, tree args, int flags,
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute only applies to functions",
+ name);
+ *no_add_attrs = true;
+ }
+ /* FIXME: the argument if any is checked for type attributes;
+ should it be checked for decl ones? */
+
+ return NULL_TREE;
+}
+
+/* Handle an "interrupt" or "isr" type attribute;
arguments as in struct attribute_spec.handler. */
static tree
-arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
- bool *no_add_attrs)
+arm_handle_isr_type_attribute (tree *node, tree name, tree args, int flags,
+ bool *no_add_attrs)
{
- if (DECL_P (*node))
+ if (TREE_CODE (*node) == FUNCTION_TYPE
+ || TREE_CODE (*node) == METHOD_TYPE)
{
- if (TREE_CODE (*node) != FUNCTION_DECL)
+ if (arm_isr_value (args) == ARM_FT_UNKNOWN)
{
- warning (OPT_Wattributes, "%qE attribute only applies to functions",
+ warning (OPT_Wattributes, "%qE attribute ignored",
name);
*no_add_attrs = true;
}
- /* FIXME: the argument if any is checked for type attributes;
- should it be checked for decl ones? */
+ }
+ else if (TREE_CODE (*node) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE
+ || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE)
+ && arm_isr_value (args) != ARM_FT_UNKNOWN)
+ {
+ *node = build_variant_type_copy (*node);
+ TREE_TYPE (*node) = build_type_attribute_variant
+ (TREE_TYPE (*node),
+ tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node))));
+ *no_add_attrs = true;
}
else
{
- if (TREE_CODE (*node) == FUNCTION_TYPE
- || TREE_CODE (*node) == METHOD_TYPE)
+ /* Possibly pass this attribute on from the type to a decl. */
+ if (flags & ((int) ATTR_FLAG_DECL_NEXT
+ | (int) ATTR_FLAG_FUNCTION_NEXT
+ | (int) ATTR_FLAG_ARRAY_NEXT))
{
- if (arm_isr_value (args) == ARM_FT_UNKNOWN)
- {
- warning (OPT_Wattributes, "%qE attribute ignored",
- name);
- *no_add_attrs = true;
- }
- }
- else if (TREE_CODE (*node) == POINTER_TYPE
- && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE)
- && arm_isr_value (args) != ARM_FT_UNKNOWN)
- {
- *node = build_variant_type_copy (*node);
- TREE_TYPE (*node) = build_type_attribute_variant
- (TREE_TYPE (*node),
- tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node))));
*no_add_attrs = true;
+ return tree_cons (name, args, NULL_TREE);
}
else
{
- /* Possibly pass this attribute on from the type to a decl. */
- if (flags & ((int) ATTR_FLAG_DECL_NEXT
- | (int) ATTR_FLAG_FUNCTION_NEXT
- | (int) ATTR_FLAG_ARRAY_NEXT))
- {
- *no_add_attrs = true;
- return tree_cons (name, args, NULL_TREE);
- }
- else
- {
- warning (OPT_Wattributes, "%qE attribute ignored",
- name);
- }
+ warning (OPT_Wattributes, "%qE attribute ignored",
+ name);
}
}
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index e5577726c96..74d2211803c 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -8928,6 +8928,33 @@ avr_class_likely_spilled_p (reg_class_t c)
naked - Don't generate function prologue/epilogue and RET
instruction. */
+/* Handle a type attribute by ignoring it; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+avr_ignore_type_attribute (tree *node ATTRIBUTE_UNUSED,
+ tree name ATTRIBUTE_UNUSED,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED,
+ bool *no_add_attrs ATTRIBUTE_UNUSED)
+{
+ return NULL_TREE;
+}
+
+/* Handle a type attribute by issuing a warning; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+avr_warning_type_attribute (tree *node ATTRIBUTE_UNUSED, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+ warning (OPT_Wattributes, "%qE attribute does not apply to types",
+ name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
/* Handle a "progmem" attribute; arguments as in
struct attribute_spec.handler. */
@@ -9089,27 +9116,29 @@ avr_eval_addr_attrib (rtx x)
static const struct attribute_spec
avr_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute,
- false },
- { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute,
- false },
- { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute,
- false },
- { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute,
- false },
- { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute,
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
+ { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute,
+ avr_ignore_type_attribute,
false },
- { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute,
+ { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute,
+ avr_warning_type_attribute, false },
+ { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute,
+ avr_warning_type_attribute, false },
+ { "naked", 0, 0, false, true, true, NULL, avr_handle_fntype_attribute,
false },
- { "io", 0, 1, false, false, false, avr_handle_addr_attribute,
+ { "OS_task", 0, 0, false, true, true, NULL, avr_handle_fntype_attribute,
false },
- { "io_low", 0, 1, false, false, false, avr_handle_addr_attribute,
+ { "OS_main", 0, 0, false, true, true, NULL, avr_handle_fntype_attribute,
false },
- { "address", 1, 1, false, false, false, avr_handle_addr_attribute,
+ { "io", 0, 1, false, false, false, avr_handle_addr_attribute,
+ avr_warning_type_attribute, false },
+ { "io_low", 0, 1, false, false, false, avr_handle_addr_attribute,
+ avr_warning_type_attribute,
false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ { "address", 1, 1, false, false, false, avr_handle_addr_attribute,
+ avr_warning_type_attribute, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 120cd791927..1cc225476dc 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -4654,19 +4654,16 @@ bfin_reorg (void)
workaround_rts_anomaly ();
}
-/* Handle interrupt_handler, exception_handler and nmi_handler function
+/* Handle interrupt_handler, exception_handler and nmi_handler function type
attributes; arguments as in struct attribute_spec.handler. */
static tree
-handle_int_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
- bool *no_add_attrs)
+handle_int_type_attribute (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED,
+ bool *no_add_attrs)
{
tree x = *node;
- if (TREE_CODE (x) == FUNCTION_DECL)
- x = TREE_TYPE (x);
-
if (TREE_CODE (x) != FUNCTION_TYPE)
{
warning (OPT_Wattributes, "%qE attribute only applies to functions",
@@ -4679,6 +4676,24 @@ handle_int_attribute (tree *node, tree name,
return NULL_TREE;
}
+/* Handle interrupt_handler, exception_handler and nmi_handler function decl
+ attributes; arguments as in struct attribute_spec.handler. */
+
+static tree
+handle_int_decl_attribute (tree *node, tree name, tree args, int flags,
+ bool *no_add_attrs)
+{
+ tree x = *node;
+ if (TREE_CODE (x) == FUNCTION_DECL)
+ return handle_int_type_attribute (&TREE_TYPE(x), name, args, flags,
+ no_add_attrs);
+
+ warning (OPT_Wattributes, "%qE attribute only applies to functions", name);
+ *no_add_attrs = true;
+
+ return NULL_TREE;
+}
+
/* Return 0 if the attributes for two types are incompatible, 1 if they
are compatible, and 2 if they are nearly compatible (which causes a
warning to be generated). */
@@ -4726,9 +4741,7 @@ bfin_handle_longcall_attribute (tree *node, tree name,
int flags ATTRIBUTE_UNUSED,
bool *no_add_attrs)
{
- if (TREE_CODE (*node) != FUNCTION_TYPE
- && TREE_CODE (*node) != FIELD_DECL
- && TREE_CODE (*node) != TYPE_DECL)
+ if (TREE_CODE (*node) != FUNCTION_TYPE)
{
warning (OPT_Wattributes, "%qE attribute only applies to functions",
name);
@@ -4874,30 +4887,31 @@ bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
/* Table of valid machine attributes. */
static const struct attribute_spec bfin_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute,
- false },
- { "exception_handler", 0, 0, false, true, true, handle_int_attribute,
- false },
- { "nmi_handler", 0, 0, false, true, true, handle_int_attribute, false },
- { "nesting", 0, 0, false, true, true, NULL, false },
- { "kspisusp", 0, 0, false, true, true, NULL, false },
- { "saveall", 0, 0, false, true, true, NULL, false },
- { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
- false },
- { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
- false },
- { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute,
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
+ { "interrupt_handler", 0, 0, false, true, true, handle_int_decl_attribute,
+ handle_int_type_attribute, false },
+ { "exception_handler", 0, 0, false, true, true, handle_int_decl_attribute,
+ handle_int_type_attribute, false },
+ { "nmi_handler", 0, 0, false, true, true, handle_int_decl_attribute,
+ handle_int_type_attribute, false },
+ { "nesting", 0, 0, false, true, true, NULL, NULL, false },
+ { "kspisusp", 0, 0, false, true, true, NULL, NULL, false },
+ { "saveall", 0, 0, false, true, true, NULL, NULL, false },
+ { "longcall", 0, 0, false, true, true, NULL,
+ bfin_handle_longcall_attribute, false },
+ { "shortcall", 0, 0, false, true, true, NULL,
+ bfin_handle_longcall_attribute, false },
+ { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute, NULL,
false },
- { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
+ { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute, NULL,
false },
- { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
+ { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute, NULL,
false },
- { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
+ { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute, NULL,
false },
- { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute, NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
diff --git a/gcc/config/cr16/cr16.c b/gcc/config/cr16/cr16.c
index 141b8bc895f..d20045fc674 100644
--- a/gcc/config/cr16/cr16.c
+++ b/gcc/config/cr16/cr16.c
@@ -197,10 +197,10 @@ static void cr16_print_operand_address (FILE *, machine_mode, rtx);
/* Table of machine attributes. */
static const struct attribute_spec cr16_attribute_table[] = {
/* ISRs have special prologue and epilogue requirements. */
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity }. */
- {"interrupt", 0, 0, false, true, true, NULL, false},
- {NULL, 0, 0, false, false, false, NULL, false}
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity }. */
+ {"interrupt", 0, 0, false, true, true, NULL, NULL, false},
+ {NULL, 0, 0, false, false, false, NULL, NULL, false}
};
/* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index 9f686d3ad3a..414087f12d3 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -710,12 +710,12 @@ extern GTY(()) section * darwin_sections[NUM_DARWIN_SECTIONS];
/* Extra attributes for Darwin. */
#define SUBTARGET_ATTRIBUTE_TABLE \
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, \
- affects_type_identity } */ \
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,\
+ type_handler, affects_type_identity } */ \
{ "apple_kext_compatibility", 0, 0, false, true, false, \
- darwin_handle_kext_attribute, false }, \
+ NULL, darwin_handle_kext_attribute, false }, \
{ "weak_import", 0, 0, true, false, false, \
- darwin_handle_weak_import_attribute, false }
+ darwin_handle_weak_import_attribute, NULL, false }
#undef ASM_GENERATE_INTERNAL_LABEL
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c
index f09a65769ca..b53c64910d2 100644
--- a/gcc/config/epiphany/epiphany.c
+++ b/gcc/config/epiphany/epiphany.c
@@ -446,13 +446,15 @@ epiphany_init_reg_tables (void)
static const struct attribute_spec epiphany_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- { "interrupt", 0, 9, true, false, false, epiphany_handle_interrupt_attribute, true },
- { "forwarder_section", 1, 1, true, false, false, epiphany_handle_forwarder_attribute, false },
- { "long_call", 0, 0, false, true, true, NULL, false },
- { "short_call", 0, 0, false, true, true, NULL, false },
- { "disinterrupt", 0, 0, false, true, true, NULL, true },
- { NULL, 0, 0, false, false, false, NULL, false }
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler } */
+ { "interrupt", 0, 9, true, false, false,
+ epiphany_handle_interrupt_attribute, NULL, true },
+ { "forwarder_section", 1, 1, true, false, false, epiphany_handle_forwarder_attribute, NULL, false },
+ { "long_call", 0, 0, false, true, true, NULL, NULL, false },
+ { "short_call", 0, 0, false, true, true, NULL, NULL, false },
+ { "disinterrupt", 0, 0, false, true, true, NULL, NULL, true },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Handle an "interrupt" attribute; arguments as in
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index 1818684c72b..a32218c5395 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -5420,23 +5420,23 @@ h8300_insert_attributes (tree node, tree *attributes)
static const struct attribute_spec h8300_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
{ "interrupt_handler", 0, 0, true, false, false,
- h8300_handle_fndecl_attribute, false },
+ h8300_handle_fndecl_attribute, NULL, false },
{ "saveall", 0, 0, true, false, false,
- h8300_handle_fndecl_attribute, false },
+ h8300_handle_fndecl_attribute, NULL, false },
{ "OS_Task", 0, 0, true, false, false,
- h8300_handle_fndecl_attribute, false },
+ h8300_handle_fndecl_attribute, NULL, false },
{ "monitor", 0, 0, true, false, false,
- h8300_handle_fndecl_attribute, false },
+ h8300_handle_fndecl_attribute, NULL, false },
{ "function_vector", 0, 0, true, false, false,
- h8300_handle_fndecl_attribute, false },
+ h8300_handle_fndecl_attribute, NULL, false },
{ "eightbit_data", 0, 0, true, false, false,
- h8300_handle_eightbit_data_attribute, false },
+ h8300_handle_eightbit_data_attribute, NULL, false },
{ "tiny_data", 0, 0, true, false, false,
- h8300_handle_tiny_data_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ h8300_handle_tiny_data_attribute, NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index 7cd8ac51d93..7b33b294d3a 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -447,9 +447,9 @@ do { \
#define SUBTARGET_ATTRIBUTE_TABLE \
{ "selectany", 0, 0, true, false, false, ix86_handle_selectany_attribute, \
- false }
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
+ NULL, false }
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
/* mcount() does not need a counter variable. */
#undef NO_PROFILE_COUNTERS
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index b5002337cf4..df61c23750c 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -6781,9 +6781,7 @@ ix86_handle_cconv_attribute (tree *node, tree name,
bool *no_add_attrs)
{
if (TREE_CODE (*node) != FUNCTION_TYPE
- && TREE_CODE (*node) != METHOD_TYPE
- && TREE_CODE (*node) != FIELD_DECL
- && TREE_CODE (*node) != TYPE_DECL)
+ && TREE_CODE (*node) != METHOD_TYPE)
{
warning (OPT_Wattributes, "%qE attribute only applies to functions",
name);
@@ -6942,7 +6940,10 @@ ix86_handle_tm_regparm_attribute (tree *node, tree, tree,
alt = tree_cons (NULL, build_int_cst (NULL, 2), NULL);
alt = tree_cons (get_identifier ("regparm"), alt, NULL);
}
- decl_attributes (node, alt, flags);
+ if (TYPE_P (*node))
+ type_attributes (node, alt, flags);
+ else
+ decl_attributes (node, alt, flags);
return NULL_TREE;
}
@@ -35307,7 +35308,7 @@ ix86_init_tm_builtins (void)
attrs);
/* add_builtin_function() will set the DECL_ATTRIBUTES, now
set the TYPE_ATTRIBUTES. */
- decl_attributes (&TREE_TYPE (decl), attrs_type, ATTR_FLAG_BUILT_IN);
+ type_attributes (&TREE_TYPE (decl), attrs_type, ATTR_FLAG_BUILT_IN);
set_builtin_decl (code, decl, false);
}
@@ -44450,25 +44451,15 @@ ix86_handle_abi_attribute (tree *node, tree name, tree, int,
return NULL_TREE;
}
-/* Handle a "ms_struct" or "gcc_struct" attribute; arguments as in
+/* Handle a "ms_struct" or "gcc_struct" type attribute; arguments as in
struct attribute_spec.handler. */
static tree
-ix86_handle_struct_attribute (tree *node, tree name, tree, int,
- bool *no_add_attrs)
+ix86_handle_struct_type_attribute (tree *type, tree name, tree, int,
+ bool *no_add_attrs)
{
- tree *type = NULL;
- if (DECL_P (*node))
+ if (!(RECORD_OR_UNION_TYPE_P (*type)))
{
- if (TREE_CODE (*node) == TYPE_DECL)
- type = &TREE_TYPE (*node);
- }
- else
- type = node;
-
- if (!(type && RECORD_OR_UNION_TYPE_P (*type)))
- {
- warning (OPT_Wattributes, "%qE attribute ignored",
- name);
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
@@ -44485,6 +44476,22 @@ ix86_handle_struct_attribute (tree *node, tree name, tree, int,
return NULL_TREE;
}
+/* Handle a "ms_struct" or "gcc_struct" decl attribute; arguments as in
+ struct attribute_spec.handler. */
+static tree
+ix86_handle_struct_decl_attribute (tree *node, tree name, tree arg, int flags,
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == TYPE_DECL)
+ return ix86_handle_struct_type_attribute (&(TREE_TYPE (*node)), name, arg,
+ flags, no_add_attrs);
+
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+
+ return NULL_TREE;
+}
+
static tree
ix86_handle_fndecl_attribute (tree *node, tree name, tree, int,
bool *no_add_attrs)
@@ -48655,61 +48662,64 @@ ix86_expand_round_sse4 (rtx op0, rtx op1)
/* Table of valid machine attributes. */
static const struct attribute_spec ix86_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
/* Stdcall attribute says callee is responsible for popping arguments
if they are not variable. */
- { "stdcall", 0, 0, false, true, true, ix86_handle_cconv_attribute,
+ { "stdcall", 0, 0, false, true, true, NULL, ix86_handle_cconv_attribute,
true },
/* Fastcall attribute says callee is responsible for popping arguments
if they are not variable. */
- { "fastcall", 0, 0, false, true, true, ix86_handle_cconv_attribute,
+ { "fastcall", 0, 0, false, true, true, NULL, ix86_handle_cconv_attribute,
true },
/* Thiscall attribute says callee is responsible for popping arguments
if they are not variable. */
- { "thiscall", 0, 0, false, true, true, ix86_handle_cconv_attribute,
+ { "thiscall", 0, 0, false, true, true, NULL, ix86_handle_cconv_attribute,
true },
/* Cdecl attribute says the callee is a normal C declaration */
- { "cdecl", 0, 0, false, true, true, ix86_handle_cconv_attribute,
+ { "cdecl", 0, 0, false, true, true, NULL, ix86_handle_cconv_attribute,
true },
/* Regparm attribute specifies how many integer arguments are to be
passed in registers. */
- { "regparm", 1, 1, false, true, true, ix86_handle_cconv_attribute,
+ { "regparm", 1, 1, false, true, true, NULL, ix86_handle_cconv_attribute,
true },
/* Sseregparm attribute says we are using x86_64 calling conventions
for FP arguments. */
- { "sseregparm", 0, 0, false, true, true, ix86_handle_cconv_attribute,
+ { "sseregparm", 0, 0, false, true, true, NULL, ix86_handle_cconv_attribute,
true },
/* The transactional memory builtins are implicitly regparm or fastcall
depending on the ABI. Override the generic do-nothing attribute that
these builtins were declared with. */
- { "*tm regparm", 0, 0, false, true, true, ix86_handle_tm_regparm_attribute,
- true },
+ { "*tm regparm", 0, 0, false, true, true, NULL,
+ ix86_handle_tm_regparm_attribute, true },
/* force_align_arg_pointer says this function realigns the stack at entry. */
- { (const char *)&ix86_force_align_arg_pointer_string, 0, 0,
- false, true, true, ix86_handle_force_align_arg_pointer_attribute, false },
+ { (const char *)&ix86_force_align_arg_pointer_string, 0, 0, false,
+ true, true, NULL, ix86_handle_force_align_arg_pointer_attribute, false },
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
- { "dllimport", 0, 0, false, false, false, handle_dll_attribute, false },
- { "dllexport", 0, 0, false, false, false, handle_dll_attribute, false },
- { "shared", 0, 0, true, false, false, ix86_handle_shared_attribute,
+ { "dllimport", 0, 0, false, false, false, handle_dll_decl_attribute,
+ handle_dll_type_attribute, false },
+ { "dllexport", 0, 0, false, false, false, handle_dll_decl_attribute,
+ handle_dll_type_attribute, false },
+ { "shared", 0, 0, true, false, false, ix86_handle_shared_attribute, NULL,
false },
#endif
- { "ms_struct", 0, 0, false, false, false, ix86_handle_struct_attribute,
- false },
- { "gcc_struct", 0, 0, false, false, false, ix86_handle_struct_attribute,
- false },
+ { "ms_struct", 0, 0, false, false, false, ix86_handle_struct_decl_attribute,
+ ix86_handle_struct_type_attribute, false },
+ { "gcc_struct", 0, 0, false, false, false, ix86_handle_struct_decl_attribute,
+ ix86_handle_struct_type_attribute, false },
#ifdef SUBTARGET_ATTRIBUTE_TABLE
SUBTARGET_ATTRIBUTE_TABLE,
#endif
/* ms_abi and sysv_abi calling convention function attributes. */
- { "ms_abi", 0, 0, false, true, true, ix86_handle_abi_attribute, true },
- { "sysv_abi", 0, 0, false, true, true, ix86_handle_abi_attribute, true },
+ { "ms_abi", 0, 0, false, true, true, NULL, ix86_handle_abi_attribute, true },
+ { "sysv_abi", 0, 0, false, true, true, NULL, ix86_handle_abi_attribute,
+ true },
{ "ms_hook_prologue", 0, 0, true, false, false, ix86_handle_fndecl_attribute,
- false },
- { "callee_pop_aggregate_return", 1, 1, false, true, true,
+ NULL, false },
+ { "callee_pop_aggregate_return", 1, 1, false, true, true, NULL,
ix86_handle_callee_pop_aggregate_return, true },
/* End element. */
- { NULL, 0, 0, false, false, false, NULL, false }
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Implement targetm.vectorize.builtin_vectorization_cost. */
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 3fcc3b5385d..772ca142c2a 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -351,18 +351,18 @@ 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[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "syscall_linkage", 0, 0, false, true, true, NULL, false },
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
+ { "syscall_linkage", 0, 0, false, true, true, NULL, NULL, false },
{ "model", 1, 1, true, false, false, ia64_handle_model_attribute,
- false },
+ NULL, false },
#if TARGET_ABI_OPEN_VMS
{ "common_object", 1, 1, true, false, false,
- ia64_vms_common_object_attribute, false },
+ ia64_vms_common_object_attribute, NULL, false },
#endif
{ "version_id", 1, 1, true, false, false,
- ia64_handle_version_id_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ ia64_handle_version_id_attribute, NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Initialize the GCC target structure. */
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index 6f6d7e4e45e..02a0022c9a3 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -58,7 +58,8 @@ typedef enum
} Push_Pop_Type;
static bool m32c_function_needs_enter (void);
-static tree interrupt_handler (tree *, tree, tree, int, bool *);
+static tree interrupt_decl_handler (tree *, tree, tree, int, bool *);
+static tree interrupt_type_handler (tree *, tree, tree, int, bool *);
static tree function_vector_handler (tree *, tree, tree, int, bool *);
static int interrupt_p (tree node);
static int bank_switch_p (tree node);
@@ -2881,8 +2882,9 @@ fast_interrupt_p (tree node ATTRIBUTE_UNUSED)
return 0;
}
+/* Do nothing decl handler. */
static tree
-interrupt_handler (tree * node ATTRIBUTE_UNUSED,
+interrupt_decl_handler (tree * node ATTRIBUTE_UNUSED,
tree name ATTRIBUTE_UNUSED,
tree args ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED,
@@ -2891,6 +2893,16 @@ interrupt_handler (tree * node ATTRIBUTE_UNUSED,
return NULL_TREE;
}
+/* Do nothing type handler. */
+static tree
+interrupt_type_handler (tree * node ATTRIBUTE_UNUSED,
+ tree name ATTRIBUTE_UNUSED,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED,
+ bool * no_add_attrs ATTRIBUTE_UNUSED)
+{
+ return NULL_TREE;
+}
/* Returns TRUE if given tree has the "function_vector" attribute. */
int
m32c_special_page_vector_p (tree func)
@@ -2990,12 +3002,15 @@ 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[] = {
- {"interrupt", 0, 0, false, false, false, interrupt_handler, false},
- {"bank_switch", 0, 0, false, false, false, interrupt_handler, false},
- {"fast_interrupt", 0, 0, false, false, false, interrupt_handler, false},
- {"function_vector", 1, 1, true, false, false, function_vector_handler,
+ {"interrupt", 0, 0, false, false, false, interrupt_decl_handler,
+ interrupt_type_handler, false},
+ {"bank_switch", 0, 0, false, false, false, interrupt_decl_handler,
+ interrupt_type_handler, false},
+ {"fast_interrupt", 0, 0, false, false, false, interrupt_decl_handler,
+ interrupt_type_handler, false},
+ {"function_vector", 1, 1, true, false, false,function_vector_handler, NULL,
false},
- {0, 0, 0, 0, 0, 0, 0, false}
+ {0, 0, 0, 0, 0, 0, 0, 0, false}
};
#undef TARGET_COMP_TYPE_ATTRIBUTES
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index b40c53ca189..2e4dfbf352e 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -105,12 +105,12 @@ static bool m32r_attribute_identifier (const_tree);
static const struct attribute_spec m32r_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "interrupt", 0, 0, true, false, false, NULL, false },
- { "model", 1, 1, true, false, false, m32r_handle_model_attribute,
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
+ { "interrupt", 0, 0, true, false, false, NULL, NULL, false },
+ { "model", 1, 1, true, false, false, m32r_handle_model_attribute, NULL,
false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Initialize the GCC target structure. */
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 03f474e1b63..a920f97cfd3 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -324,15 +324,15 @@ static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
static const struct attribute_spec m68k_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "interrupt", 0, 0, true, false, false, m68k_handle_fndecl_attribute,
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
+ { "interrupt", 0, 0, true, false, false, m68k_handle_fndecl_attribute, NULL,
false },
{ "interrupt_handler", 0, 0, true, false, false,
- m68k_handle_fndecl_attribute, false },
+ m68k_handle_fndecl_attribute, NULL, false },
{ "interrupt_thread", 0, 0, true, false, false,
- m68k_handle_fndecl_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ m68k_handle_fndecl_attribute, NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c
index c9d0506afd5..9038294cc88 100644
--- a/gcc/config/mcore/mcore.c
+++ b/gcc/config/mcore/mcore.c
@@ -147,13 +147,13 @@ static bool mcore_legitimate_address_p (machine_mode, rtx, bool,
static const struct attribute_spec mcore_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "dllexport", 0, 0, true, false, false, NULL, false },
- { "dllimport", 0, 0, true, false, false, NULL, false },
- { "naked", 0, 0, true, false, false, mcore_handle_naked_attribute,
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
+ { "dllexport", 0, 0, true, false, false, NULL, NULL, false },
+ { "dllimport", 0, 0, true, false, false, NULL, NULL, false },
+ { "naked", 0, 0, true, false, false, mcore_handle_naked_attribute, NULL,
false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Initialize the GCC target structure. */
diff --git a/gcc/config/mep/mep.c b/gcc/config/mep/mep.c
index 9c4cd860ac2..84e92585a1f 100644
--- a/gcc/config/mep/mep.c
+++ b/gcc/config/mep/mep.c
@@ -167,9 +167,13 @@ static bool mep_function_ok_for_sibcall (tree, tree);
static int unique_bit_in (HOST_WIDE_INT);
static int bit_size_for_clip (HOST_WIDE_INT);
static int bytesize (const_tree, machine_mode);
-static tree mep_validate_based_tiny (tree *, tree, tree, int, bool *);
-static tree mep_validate_near_far (tree *, tree, tree, int, bool *);
-static tree mep_validate_disinterrupt (tree *, tree, tree, int, bool *);
+static tree mep_validate_type_based_tiny (tree *, tree, tree, int, bool *);
+static tree mep_validate_decl_based_tiny (tree *, tree, tree, int, bool *);
+static tree mep_validate_type_near_far (tree *, tree, tree, int, bool *);
+static tree mep_validate_decl_near_far (tree *, tree, tree, int, bool *);
+static tree mep_validate_type_disinterrupt (tree *, tree, tree, int, bool *);
+static tree mep_validate_decl_disinterrupt (tree *, tree, tree, int, bool *);
+static tree mep_validate_type_warning(tree *, tree, tree, int, bool *);
static tree mep_validate_interrupt (tree *, tree, tree, int, bool *);
static tree mep_validate_io_cb (tree *, tree, tree, int, bool *);
static tree mep_validate_vliw (tree *, tree, tree, int, bool *);
@@ -3778,11 +3782,23 @@ mep_asm_output_opcode (FILE *file, const char *ptr)
/* Handle attributes. */
static tree
-mep_validate_based_tiny (tree *node, tree name, tree args,
+mep_validate_type_based_tiny (tree *node, tree name, tree args,
+ int flags ATTRIBUTE_UNUSED, bool *no_add)
+{
+ if (TREE_CODE (*node) != POINTER_TYPE)
+ {
+ warning (0, "%qE attribute only applies to variables", name);
+ *no_add = true;
+ }
+
+ return NULL_TREE;
+}
+
+static tree
+mep_validate_decl_based_tiny (tree *node, tree name, tree args,
int flags ATTRIBUTE_UNUSED, bool *no_add)
{
if (TREE_CODE (*node) != VAR_DECL
- && TREE_CODE (*node) != POINTER_TYPE
&& TREE_CODE (*node) != TYPE_DECL)
{
warning (0, "%qE attribute only applies to variables", name);
@@ -3838,13 +3854,29 @@ mep_multiple_address_regions (tree list, bool check_section_attr)
: TYPE_ATTRIBUTES (TREE_TYPE (decl))
static tree
-mep_validate_near_far (tree *node, tree name, tree args,
+mep_validate_type_near_far (tree *node, tree name, tree args,
+ int flags ATTRIBUTE_UNUSED, bool *no_add)
+{
+ if (TREE_CODE (*node) != METHOD_TYPE && TREE_CODE (*node) != POINTER_TYPE)
+ {
+ warning (0, "%qE attribute only applies to variables and functions",
+ name);
+ *no_add = true;
+ }
+ else if (mep_multiple_address_regions (MEP_ATTRIBUTES (*node), false) > 0)
+ {
+ warning (0, "duplicate address region attribute %qE", name);
+ TYPE_ATTRIBUTES (*node) = NULL_TREE;
+ }
+ return NULL_TREE;
+}
+
+static tree
+mep_validate_decl_near_far (tree *node, tree name, tree args,
int flags ATTRIBUTE_UNUSED, bool *no_add)
{
if (TREE_CODE (*node) != VAR_DECL
&& TREE_CODE (*node) != FUNCTION_DECL
- && TREE_CODE (*node) != METHOD_TYPE
- && TREE_CODE (*node) != POINTER_TYPE
&& TREE_CODE (*node) != TYPE_DECL)
{
warning (0, "%qE attribute only applies to variables and functions",
@@ -3875,11 +3907,24 @@ mep_validate_near_far (tree *node, tree name, tree args,
}
static tree
-mep_validate_disinterrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add)
+mep_validate_type_disinterrupt (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add)
+{
+ if (TREE_CODE (*node) != METHOD_TYPE)
+ {
+ warning (0, "%qE attribute only applies to functions", name);
+ *no_add = true;
+ }
+ return NULL_TREE;
+}
+
+static tree
+mep_validate_decl_disinterrupt (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add)
{
- if (TREE_CODE (*node) != FUNCTION_DECL
- && TREE_CODE (*node) != METHOD_TYPE)
+ if (TREE_CODE (*node) != FUNCTION_DECL)
{
warning (0, "%qE attribute only applies to functions", name);
*no_add = true;
@@ -3888,6 +3933,17 @@ mep_validate_disinterrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
}
static tree
+mep_validate_type_warning (tree *node ATTRIBUTE_UNUSED, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add)
+{
+ warning (0, "%qE attribute only applies to functions", name);
+ *no_add = true;
+ return NULL_TREE;
+}
+
+
+static tree
mep_validate_interrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED, bool *no_add)
{
@@ -3998,19 +4054,26 @@ mep_validate_vliw (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
static const struct attribute_spec mep_attribute_table[11] =
{
- /* name min max decl type func handler
- affects_type_identity */
- { "based", 0, 0, false, false, false, mep_validate_based_tiny, false },
- { "tiny", 0, 0, false, false, false, mep_validate_based_tiny, false },
- { "near", 0, 0, false, false, false, mep_validate_near_far, false },
- { "far", 0, 0, false, false, false, mep_validate_near_far, false },
- { "disinterrupt", 0, 0, false, false, false, mep_validate_disinterrupt,
- false },
- { "interrupt", 0, 0, false, false, false, mep_validate_interrupt, false },
- { "io", 0, 1, false, false, false, mep_validate_io_cb, false },
- { "cb", 0, 1, false, false, false, mep_validate_io_cb, false },
- { "vliw", 0, 0, false, true, false, mep_validate_vliw, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ /* name min max decl type func decl_handler
+ type_handler affects_type_identity */
+ { "based", 0, 0, false, false, false, mep_validate_decl_based_tiny,
+ mep_validate_type_based_tiny, false },
+ { "tiny", 0, 0, false, false, false, mep_validate_decl_based_tiny,
+ mep_validate_type_based_tiny, false },
+ { "near", 0, 0, false, false, false, mep_validate_decl_near_far,
+ mep_validate_type_near_far, false },
+ { "far", 0, 0, false, false, false, mep_validate_decl_near_far,
+ mep_validate_type_near_far, false },
+ { "disinterrupt", 0, 0, false, false, false, mep_validate_decl_disinterrupt,
+ mep_validate_type_disinterrupt, false },
+ { "interrupt", 0, 0, false, false, false, mep_validate_interrupt,
+ mep_validate_type_warning, false },
+ { "io", 0, 1, false, false, false, mep_validate_io_cb,
+ mep_validate_type_warning, false },
+ { "cb", 0, 1, false, false, false, mep_validate_io_cb,
+ mep_validate_type_warning, false },
+ { "vliw", 0, 0, false, true, false, NULL, mep_validate_vliw, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
static bool
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index baff67a89c9..e2bc827d75d 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -212,18 +212,18 @@ int fast_interrupt;
int save_volatiles;
const struct attribute_spec microblaze_attribute_table[] = {
- /* name min_len, max_len, decl_req, type_req, fn_type, req_handler,
- affects_type_identity */
- {"interrupt_handler", 0, 0, true, false, false, NULL,
- false },
+ /* name min_len, max_len, decl_req, type_req, fn_type, decl_handler,
+ type_handler, affects_type_identity */
+ {"interrupt_handler", 0, 0, true, false, false, NULL,
+ NULL, false },
{"break_handler", 0, 0, true, false, false, NULL,
- false },
+ NULL, false },
{"fast_interrupt", 0, 0, true, false, false, NULL,
- false },
+ NULL, false },
{"save_volatiles" , 0, 0, true, false, false, NULL,
- false },
+ NULL, false },
{ NULL, 0, 0, false, false, false, NULL,
- false }
+ NULL, false }
};
static int microblaze_interrupt_function_p (tree);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 9ec2dcb8f86..60df643f077 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -589,28 +589,28 @@ static tree mips_handle_use_shadow_register_set_attr (tree *, tree, tree, int,
/* The value of TARGET_ATTRIBUTE_TABLE. */
static const struct attribute_spec mips_attribute_table[] = {
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- om_diagnostic } */
- { "long_call", 0, 0, false, true, true, NULL, false },
- { "far", 0, 0, false, true, true, NULL, false },
- { "near", 0, 0, false, true, true, NULL, false },
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, om_diagnostic } */
+ { "long_call", 0, 0, false, true, true, NULL, NULL, false },
+ { "far", 0, 0, false, true, true, NULL, NULL, false },
+ { "near", 0, 0, false, true, true, NULL, NULL, false },
/* We would really like to treat "mips16" and "nomips16" as type
attributes, but GCC doesn't provide the hooks we need to support
the right conversion rules. As declaration attributes, they affect
code generation but don't carry other semantics. */
- { "mips16", 0, 0, true, false, false, NULL, false },
- { "nomips16", 0, 0, true, false, false, NULL, false },
- { "micromips", 0, 0, true, false, false, NULL, false },
- { "nomicromips", 0, 0, true, false, false, NULL, false },
- { "nocompression", 0, 0, true, false, false, NULL, false },
+ { "mips16", 0, 0, true, false, false, NULL, NULL, false },
+ { "nomips16", 0, 0, true, false, false, NULL, NULL, false },
+ { "micromips", 0, 0, true, false, false, NULL, NULL, false },
+ { "nomicromips", 0, 0, true, false, false, NULL, NULL, false },
+ { "nocompression", 0, 0, true, false, false, NULL, NULL, false },
/* Allow functions to be specified as interrupt handlers */
{ "interrupt", 0, 1, false, true, true, mips_handle_interrupt_attr,
- false },
+ NULL, false },
{ "use_shadow_register_set", 0, 1, false, true, true,
- mips_handle_use_shadow_register_set_attr, false },
- { "keep_interrupts_masked", 0, 0, false, true, true, NULL, false },
- { "use_debug_exception_return", 0, 0, false, true, true, NULL, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ NULL, mips_handle_use_shadow_register_set_attr, false },
+ { "keep_interrupts_masked", 0, 0, false, true, true, NULL, NULL, false },
+ { "use_debug_exception_return", 0, 0, false, true, true, NULL, NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* A table describing all the processors GCC knows about; see
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 182ca59a1c1..7f8385574ee 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -1984,21 +1984,26 @@ const struct attribute_spec msp430_attribute_table[] =
{
/* Name min_num_args type_req, affects_type_identity
max_num_args, fn_type_req
- decl_req handler. */
- { ATTR_INTR, 0, 1, true, false, false, msp430_attr, false },
- { ATTR_NAKED, 0, 0, true, false, false, msp430_attr, false },
- { ATTR_REENT, 0, 0, true, false, false, msp430_attr, false },
- { ATTR_CRIT, 0, 0, true, false, false, msp430_attr, false },
- { ATTR_WAKEUP, 0, 0, true, false, false, msp430_attr, false },
-
- { ATTR_LOWER, 0, 0, true, false, false, msp430_section_attr, false },
- { ATTR_UPPER, 0, 0, true, false, false, msp430_section_attr, false },
- { ATTR_EITHER, 0, 0, true, false, false, msp430_section_attr, false },
-
- { ATTR_NOINIT, 0, 0, true, false, false, msp430_data_attr, false },
- { ATTR_PERSIST, 0, 0, true, false, false, msp430_data_attr, false },
-
- { NULL, 0, 0, false, false, false, NULL, false }
+ decl_req decl_handler type_handler. */
+ { ATTR_INTR, 0, 1, true, false, false, msp430_attr, NULL, false },
+ { ATTR_NAKED, 0, 0, true, false, false, msp430_attr, NULL, false },
+ { ATTR_REENT, 0, 0, true, false, false, msp430_attr, NULL, false },
+ { ATTR_CRIT, 0, 0, true, false, false, msp430_attr, NULL, false },
+ { ATTR_WAKEUP, 0, 0, true, false, false, msp430_attr, NULL, false },
+
+ { ATTR_LOWER, 0, 0, true, false, false, msp430_section_attr, NULL,
+ false },
+ { ATTR_UPPER, 0, 0, true, false, false, msp430_section_attr, NULL,
+ false },
+ { ATTR_EITHER, 0, 0, true, false, false, msp430_section_attr, NULL,
+ false },
+
+ { ATTR_NOINIT, 0, 0, true, false, false, msp430_data_attr, NULL,
+ false },
+ { ATTR_PERSIST, 0, 0, true, false, false, msp430_data_attr, NULL,
+ false },
+
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
#undef TARGET_ASM_FUNCTION_PROLOGUE
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
index c47c122a817..69ecfb5e447 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -80,33 +80,34 @@ static const char * const nds32_intrinsic_register_names[] =
static const struct attribute_spec nds32_attribute_table[] =
{
/* Syntax: { name, min_len, max_len, decl_required, type_required,
- function_type_required, handler, affects_type_identity } */
+ function_type_required, decl_handler, type_handler,
+ affects_type_identity } */
/* The interrupt vid: [0-63]+ (actual vector number starts from 9 to 72). */
- { "interrupt", 1, 64, false, false, false, NULL, false },
+ { "interrupt", 1, 64, false, false, false, NULL, NULL, false },
/* The exception vid: [1-8]+ (actual vector number starts from 1 to 8). */
- { "exception", 1, 8, false, false, false, NULL, false },
+ { "exception", 1, 8, false, false, false, NULL, NULL, false },
/* Argument is user's interrupt numbers. The vector number is always 0. */
- { "reset", 1, 1, false, false, false, NULL, false },
+ { "reset", 1, 1, false, false, false, NULL, NULL, false },
/* The attributes describing isr nested type. */
- { "nested", 0, 0, false, false, false, NULL, false },
- { "not_nested", 0, 0, false, false, false, NULL, false },
- { "nested_ready", 0, 0, false, false, false, NULL, false },
+ { "nested", 0, 0, false, false, false, NULL, NULL, false },
+ { "not_nested", 0, 0, false, false, false, NULL, NULL, false },
+ { "nested_ready", 0, 0, false, false, false, NULL, NULL, false },
/* The attributes describing isr register save scheme. */
- { "save_all", 0, 0, false, false, false, NULL, false },
- { "partial_save", 0, 0, false, false, false, NULL, false },
+ { "save_all", 0, 0, false, false, false, NULL, NULL, false },
+ { "partial_save", 0, 0, false, false, false, NULL, NULL, false },
/* The attributes used by reset attribute. */
- { "nmi", 1, 1, false, false, false, NULL, false },
- { "warm", 1, 1, false, false, false, NULL, false },
+ { "nmi", 1, 1, false, false, false, NULL, NULL, false },
+ { "warm", 1, 1, false, false, false, NULL, NULL, false },
/* The attribute telling no prologue/epilogue. */
- { "naked", 0, 0, false, false, false, NULL, false },
+ { "naked", 0, 0, false, false, false, NULL, NULL, false },
/* The last attribute spec is set to be NULL. */
- { NULL, 0, 0, false, false, false, NULL, false }
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index 1dadfc57fec..da44be6db37 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -3808,10 +3808,11 @@ nvptx_handle_kernel_attribute (tree *node, tree name, tree ARG_UNUSED (args),
/* Table of valid machine attributes. */
static const struct attribute_spec nvptx_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "kernel", 0, 0, true, false, false, nvptx_handle_kernel_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
+ { "kernel", 0, 0, true, false, false, nvptx_handle_kernel_attribute, NULL,
+ false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Limit vector alignments to BIGGEST_ALIGNMENT. */
diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c
index 13c22539268..04615f54ef2 100644
--- a/gcc/config/rl78/rl78.c
+++ b/gcc/config/rl78/rl78.c
@@ -814,16 +814,16 @@ rl78_handle_saddr_attribute (tree * node,
/* Table of RL78-specific attributes. */
const struct attribute_spec rl78_attribute_table[] =
{
- /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity. */
+ /* Name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity. */
{ "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
- false },
+ NULL, false },
{ "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
- false },
+ NULL, false },
{ "naked", 0, 0, true, false, false, rl78_handle_naked_attribute,
- false },
+ NULL, false },
{ "saddr", 0, 0, true, false, false, rl78_handle_saddr_attribute,
- false },
+ NULL, false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 41f53adc0c3..e335fd7f6fe 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1207,7 +1207,10 @@ static struct machine_function * rs6000_init_machine_status (void);
static int rs6000_ra_ever_killed (void);
static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
-static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
+static tree rs6000_handle_struct_decl_attribute (tree *, tree, tree, int,
+ bool *);
+static tree rs6000_handle_struct_type_attribute (tree *, tree, tree, int,
+ bool *);
static tree rs6000_builtin_vectorized_libmass (combined_fn, tree, tree);
static void rs6000_emit_set_long_const (rtx, HOST_WIDE_INT);
static int rs6000_memory_move_cost (machine_mode, reg_class_t, bool);
@@ -1421,22 +1424,23 @@ static const char alt_reg_names[][8] =
static const struct attribute_spec rs6000_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "altivec", 1, 1, false, true, false, rs6000_handle_altivec_attribute,
- false },
- { "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute,
- false },
- { "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute,
- false },
- { "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute,
- false },
- { "gcc_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute,
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
+ { "altivec", 1, 1, false, true, false, NULL,
+ rs6000_handle_altivec_attribute, false },
+ { "longcall", 0, 0, false, true, true, NULL,
+ rs6000_handle_longcall_attribute, false },
+ { "shortcall", 0, 0, false, true, true, NULL,
+ rs6000_handle_longcall_attribute, false },
+ { "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_decl_attribute,
+ rs6000_handle_struct_type_attribute, false },
+ { "gcc_struct", 0, 0, false, false, false,
+ rs6000_handle_struct_decl_attribute, rs6000_handle_struct_type_attribute,
false },
#ifdef SUBTARGET_ATTRIBUTE_TABLE
SUBTARGET_ATTRIBUTE_TABLE,
#endif
- { NULL, 0, 0, false, false, false, NULL, false }
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
#ifndef TARGET_PROFILE_KERNEL
@@ -30935,9 +30939,7 @@ rs6000_handle_longcall_attribute (tree *node, tree name,
int flags ATTRIBUTE_UNUSED,
bool *no_add_attrs)
{
- if (TREE_CODE (*node) != FUNCTION_TYPE
- && TREE_CODE (*node) != FIELD_DECL
- && TREE_CODE (*node) != TYPE_DECL)
+ if (TREE_CODE (*node) != FUNCTION_TYPE)
{
warning (OPT_Wattributes, "%qE attribute only applies to functions",
name);
@@ -30994,21 +30996,16 @@ rs6000_longcall_ref (rtx call_ref)
#define TARGET_USE_MS_BITFIELD_LAYOUT 0
#endif
-/* Handle a "ms_struct" or "gcc_struct" attribute; arguments as in
+/* Handle a "ms_struct" or "gcc_struct" type attribute; arguments as in
struct attribute_spec.handler. */
+
static tree
-rs6000_handle_struct_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+rs6000_handle_struct_type_attribute (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED,
+ bool *no_add_attrs)
{
- tree *type = NULL;
- if (DECL_P (*node))
- {
- if (TREE_CODE (*node) == TYPE_DECL)
- type = &TREE_TYPE (*node);
- }
- else
- type = node;
+ tree *type = node;
if (!(type && (TREE_CODE (*type) == RECORD_TYPE
|| TREE_CODE (*type) == UNION_TYPE)))
@@ -31030,6 +31027,22 @@ rs6000_handle_struct_attribute (tree *node, tree name,
return NULL_TREE;
}
+/* Handle a "ms_struct" or "gcc_struct" decl attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+rs6000_handle_struct_decl_attribute (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == TYPE_DECL)
+ return rs6000_handle_struct_type_attribute (&TREE_TYPE (*node), name, args,
+ flags, no_add_attrs);
+
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
static bool
rs6000_ms_bitfield_layout_p (const_tree record_type)
{
diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c
index 4cf840c26d1..b97218390c6 100644
--- a/gcc/config/rx/rx.c
+++ b/gcc/config/rx/rx.c
@@ -2729,17 +2729,17 @@ rx_handle_vector_attribute (tree * node,
/* Table of RX specific attributes. */
const struct attribute_spec rx_attribute_table[] =
{
- /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity. */
- { "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
+ /* Name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity. */
+ { "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute, NULL,
false },
- { "interrupt", 0, -1, true, false, false, rx_handle_func_attribute,
+ { "interrupt", 0, -1, true, false, false, rx_handle_func_attribute, NULL,
false },
- { "naked", 0, 0, true, false, false, rx_handle_func_attribute,
+ { "naked", 0, 0, true, false, false, rx_handle_func_attribute, NULL,
false },
{ "vector", 1, -1, true, false, false, rx_handle_vector_attribute,
- false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE. */
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 3be64de3570..64c91c5458e 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -1088,8 +1088,10 @@ s390_handle_vectorbool_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
}
static const struct attribute_spec s390_attribute_table[] = {
- { "hotpatch", 2, 2, true, false, false, s390_handle_hotpatch_attribute, false },
- { "s390_vector_bool", 0, 0, false, true, false, s390_handle_vectorbool_attribute, true },
+ { "hotpatch", 2, 2, true, false, false, s390_handle_hotpatch_attribute, NULL,
+ false },
+ { "s390_vector_bool", 0, 0, false, true, false, NULL,
+ s390_handle_vectorbool_attribute, true },
/* End element. */
{ NULL, 0, 0, false, false, false, NULL, false }
};
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 0b18ce52719..2ce114aa2da 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -338,25 +338,25 @@ static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
static const struct attribute_spec sh_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
{ "interrupt_handler", 0, 0, true, false, false,
- sh_handle_interrupt_handler_attribute, false },
+ sh_handle_interrupt_handler_attribute, NULL, false },
{ "sp_switch", 1, 1, true, false, false,
- sh_handle_sp_switch_attribute, false },
+ sh_handle_sp_switch_attribute, NULL, false },
{ "trap_exit", 1, 1, true, false, false,
- sh_handle_trap_exit_attribute, false },
- { "renesas", 0, 0, false, true, false,
+ sh_handle_trap_exit_attribute, NULL, false },
+ { "renesas", 0, 0, false, true, false, NULL,
sh_handle_renesas_attribute, false },
{ "trapa_handler", 0, 0, true, false, false,
- sh_handle_interrupt_handler_attribute, false },
+ sh_handle_interrupt_handler_attribute, NULL, false },
{ "nosave_low_regs", 0, 0, true, false, false,
- sh_handle_interrupt_handler_attribute, false },
+ sh_handle_interrupt_handler_attribute, NULL, false },
{ "resbank", 0, 0, true, false, false,
- sh_handle_resbank_handler_attribute, false },
+ sh_handle_resbank_handler_attribute, NULL, false },
{ "function_vector", 1, 1, true, false, false,
- sh2a_handle_function_vector_handler_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ sh2a_handle_function_vector_handler_attribute, NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Initialize the GCC target structure. */
diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h
index 5160e1fda18..a4d1dc04446 100644
--- a/gcc/config/sol2.h
+++ b/gcc/config/sol2.h
@@ -381,8 +381,8 @@ along with GCC; see the file COPYING3. If not see
/* #pragma init and #pragma fini are implemented on top of init and
fini attributes. */
#define SOLARIS_ATTRIBUTE_TABLE \
- { "init", 0, 0, true, false, false, NULL, false }, \
- { "fini", 0, 0, true, false, false, NULL, false }
+ { "init", 0, 0, true, false, false, NULL, NULL, false }, \
+ { "fini", 0, 0, true, false, false, NULL, NULL, false }
/* Solaris-specific #pragmas are implemented on top of attributes. Hook in
the bits from config/sol2.c. */
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 71609f27701..a6a712d8d38 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -628,10 +628,10 @@ static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *);
/* Table of valid machine attributes. */
static const struct attribute_spec sparc_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- do_diagnostic } */
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, do_diagnostic } */
SUBTARGET_ATTRIBUTE_TABLE,
- { NULL, 0, 0, false, false, false, NULL, false }
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
#endif
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index 401c295b138..3c5e6f9529b 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -7141,13 +7141,13 @@ spu_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
/* Table of machine attributes. */
static const struct attribute_spec spu_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
{ "naked", 0, 0, true, false, false, spu_handle_fndecl_attribute,
- false },
- { "spu_vector", 0, 0, false, true, false, spu_handle_vector_attribute,
- false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ NULL, false },
+ { "spu_vector", 0, 0, false, true, false, NULL,
+ spu_handle_vector_attribute, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* TARGET overrides. */
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index 50af15bd7cc..69fca158a70 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -2186,15 +2186,15 @@ static tree xstormy16_handle_below100_attribute
static const struct attribute_spec xstormy16_attribute_table[] =
{
- /* name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity. */
- { "interrupt", 0, 0, false, true, true,
- xstormy16_handle_interrupt_attribute , false },
- { "BELOW100", 0, 0, false, false, false,
- xstormy16_handle_below100_attribute, false },
- { "below100", 0, 0, false, false, false,
- xstormy16_handle_below100_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ /* name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity. */
+ { "interrupt", 0, 0, false, true, true, NULL,
+ xstormy16_handle_interrupt_attribute , false },
+ { "BELOW100", 0, 0, true, false, false,
+ xstormy16_handle_below100_attribute, NULL, false },
+ { "below100", 0, 0, true, false, false,
+ xstormy16_handle_below100_attribute, NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Handle an "interrupt" attribute;
@@ -2226,15 +2226,13 @@ xstormy16_handle_below100_attribute (tree *node,
int flags ATTRIBUTE_UNUSED,
bool *no_add_attrs)
{
- if (TREE_CODE (*node) != VAR_DECL
- && TREE_CODE (*node) != POINTER_TYPE
- && TREE_CODE (*node) != TYPE_DECL)
+ if (TREE_CODE (*node) != VAR_DECL)
{
warning (OPT_Wattributes,
"%<__BELOW100__%> attribute only applies to variables");
*no_add_attrs = true;
}
- else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL)
+ else if (args == NULL_TREE)
{
if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node)))
{
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index e0e4215e05f..75651a42035 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -3185,19 +3185,19 @@ v850_adjust_insn_length (rtx_insn *insn, int length)
static const struct attribute_spec v850_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
{ "interrupt_handler", 0, 0, true, false, false,
- v850_handle_interrupt_attribute, false },
+ v850_handle_interrupt_attribute, NULL, false },
{ "interrupt", 0, 0, true, false, false,
- v850_handle_interrupt_attribute, false },
+ v850_handle_interrupt_attribute, NULL, false },
{ "sda", 0, 0, true, false, false,
- v850_handle_data_area_attribute, false },
+ v850_handle_data_area_attribute, NULL, false },
{ "tda", 0, 0, true, false, false,
- v850_handle_data_area_attribute, false },
+ v850_handle_data_area_attribute, NULL, false },
{ "zda", 0, 0, true, false, false,
- v850_handle_data_area_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ v850_handle_data_area_attribute, NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
static void
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 617c5d5111d..a670221d539 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -9950,7 +9950,7 @@ grokdeclarator (const cp_declarator *declarator,
{
/* Apply the c++11 attributes to the type preceding them. */
input_location = declspecs->locations[ds_std_attribute];
- decl_attributes (&type, declspecs->std_attributes, 0);
+ type_attributes (&type, declspecs->std_attributes, 0);
input_location = saved_loc;
}
@@ -9976,7 +9976,7 @@ grokdeclarator (const cp_declarator *declarator,
attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
if (declarator->kind == cdk_array)
attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
- returned_attrs = decl_attributes (&type,
+ returned_attrs = type_attributes (&type,
chainon (returned_attrs, attrs),
attr_flags);
}
@@ -10247,7 +10247,7 @@ grokdeclarator (const cp_declarator *declarator,
The optional attribute-specifier-seq appertains to
the function type. */
- decl_attributes (&type, attrs, 0);
+ type_attributes (&type, attrs, 0);
}
break;
@@ -10420,7 +10420,7 @@ grokdeclarator (const cp_declarator *declarator,
[the optional attribute-specifier-seq (7.6.1) appertains
to the pointer and not to the object pointed to]. */
if (declarator->std_attributes)
- decl_attributes (&type, declarator->std_attributes,
+ type_attributes (&type, declarator->std_attributes,
0);
ctype = NULL_TREE;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 7d68961cd20..e6e0bc85445 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1482,13 +1482,20 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags)
if (TREE_TYPE (*decl) && TYPE_PTRMEMFUNC_P (TREE_TYPE (*decl)))
{
- attributes
- = decl_attributes (decl, attributes, flags | ATTR_FLAG_FUNCTION_NEXT);
- decl_attributes (&TYPE_PTRMEMFUNC_FN_TYPE_RAW (TREE_TYPE (*decl)),
+ if (TYPE_P (*decl))
+ attributes = type_attributes (decl, attributes,
+ flags | ATTR_FLAG_FUNCTION_NEXT);
+ else
+ attributes = decl_attributes (decl, attributes,
+ flags | ATTR_FLAG_FUNCTION_NEXT);
+ type_attributes (&TYPE_PTRMEMFUNC_FN_TYPE_RAW (TREE_TYPE (*decl)),
attributes, flags);
}
else
- decl_attributes (decl, attributes, flags);
+ if (TYPE_P (*decl))
+ type_attributes (decl, attributes, flags);
+ else
+ decl_attributes (decl, attributes, flags);
if (TREE_CODE (*decl) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 2bf37bcabc1..52018c1d2f6 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -42,10 +42,17 @@ static tree count_trees_r (tree *, int *, void *);
static tree verify_stmt_tree_r (tree *, int *, void *);
static tree build_local_temp (tree);
-static tree handle_java_interface_attribute (tree *, tree, tree, int, bool *);
-static tree handle_com_interface_attribute (tree *, tree, tree, int, bool *);
+static tree handle_java_interface_decl_attribute (tree *, tree, tree, int,
+ bool *);
+static tree handle_java_interface_type_attribute (tree *, tree, tree, int,
+ bool *);
+static tree handle_com_interface_decl_attribute (tree *, tree, tree, int,
+ bool *);
+static tree handle_com_interface_type_attribute (tree *, tree, tree, int,
+ bool *);
static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
-static tree handle_abi_tag_attribute (tree *, tree, tree, int, bool *);
+static tree handle_abi_tag_decl_attribute (tree *, tree, tree, int, bool *);
+static tree handle_abi_tag_type_attribute (tree *, tree, tree, int, bool *);
/* If REF is an lvalue, returns the kind of lvalue that REF is.
Otherwise, returns clk_none. */
@@ -3510,31 +3517,43 @@ zero_init_p (const_tree t)
/* Table of valid C++ attributes. */
const struct attribute_spec cxx_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
{ "java_interface", 0, 0, false, false, false,
- handle_java_interface_attribute, false },
+ handle_java_interface_decl_attribute, handle_java_interface_type_attribute,
+ false },
{ "com_interface", 0, 0, false, false, false,
- handle_com_interface_attribute, false },
+ handle_com_interface_decl_attribute, handle_com_interface_type_attribute,
+ false },
{ "init_priority", 1, 1, true, false, false,
- handle_init_priority_attribute, false },
+ handle_init_priority_attribute, NULL, false },
{ "abi_tag", 1, -1, false, false, false,
- handle_abi_tag_attribute, true },
- { NULL, 0, 0, false, false, false, NULL, false }
+ handle_abi_tag_decl_attribute, handle_abi_tag_type_attribute, true },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
-/* Handle a "java_interface" attribute; arguments as in
+
+/* Handle a "java_interface" decl attribute; arguments as in
+ struct attribute_spec.handler. */
+static tree
+handle_java_interface_decl_attribute (tree* /*node*/, tree name, tree /*args*/,
+ int /*flags*/, bool* no_add_attrs)
+{
+ error ("%qE attribute can only be applied to Java class definitions", name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
+/* Handle a "java_interface" type attribute; arguments as in
struct attribute_spec.handler. */
static tree
-handle_java_interface_attribute (tree* node,
- tree name,
- tree /*args*/,
- int flags,
- bool* no_add_attrs)
-{
- if (DECL_P (*node)
- || !CLASS_TYPE_P (*node)
- || !TYPE_FOR_JAVA (*node))
+handle_java_interface_type_attribute (tree* node,
+ tree name,
+ tree /*args*/,
+ int flags,
+ bool* no_add_attrs)
+{
+ if (!CLASS_TYPE_P (*node) || !TYPE_FOR_JAVA (*node))
{
error ("%qE attribute can only be applied to Java class definitions",
name);
@@ -3548,22 +3567,33 @@ handle_java_interface_attribute (tree* node,
return NULL_TREE;
}
-/* Handle a "com_interface" attribute; arguments as in
+/* Handle a "com_interface" decl attribute; arguments as in
struct attribute_spec.handler. */
static tree
-handle_com_interface_attribute (tree* node,
- tree name,
- tree /*args*/,
- int /*flags*/,
- bool* no_add_attrs)
+handle_com_interface_decl_attribute (tree* /*node*/, tree name, tree /*args*/,
+ int /*flags*/, bool* no_add_attrs)
+{
+ warning (OPT_Wattributes, "%qE attribute can only be applied "
+ "to class definitions", name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
+
+/* Handle a "com_interface" type attribute; arguments as in
+ struct attribute_spec.handler. */
+static tree
+handle_com_interface_type_attribute (tree* node,
+ tree name,
+ tree /*args*/,
+ int /*flags*/,
+ bool* no_add_attrs)
{
static int warned;
*no_add_attrs = true;
- if (DECL_P (*node)
- || !CLASS_TYPE_P (*node)
- || *node != TYPE_MAIN_VARIANT (*node))
+ if (!CLASS_TYPE_P (*node) || *node != TYPE_MAIN_VARIANT (*node))
{
warning (OPT_Wattributes, "%qE attribute can only be applied "
"to class definitions", name);
@@ -3745,72 +3775,85 @@ check_abi_tag_args (tree args, tree name)
return true;
}
-/* Handle an "abi_tag" attribute; arguments as in
+/* Handle an "abi_tag" decl attribute; arguments as in
struct attribute_spec.handler. */
static tree
-handle_abi_tag_attribute (tree* node, tree name, tree args,
- int flags, bool* no_add_attrs)
+handle_abi_tag_decl_attribute (tree* node, tree name, tree args,
+ int ARG_UNUSED (flags), bool* no_add_attrs)
{
if (!check_abi_tag_args (args, name))
goto fail;
- if (TYPE_P (*node))
+ if (!VAR_OR_FUNCTION_DECL_P (*node))
{
- if (!OVERLOAD_TYPE_P (*node))
- {
- error ("%qE attribute applied to non-class, non-enum type %qT",
- name, *node);
- goto fail;
- }
- else if (!(flags & (int)ATTR_FLAG_TYPE_IN_PLACE))
- {
- error ("%qE attribute applied to %qT after its definition",
- name, *node);
- goto fail;
- }
- else if (CLASS_TYPE_P (*node)
- && CLASSTYPE_TEMPLATE_INSTANTIATION (*node))
- {
- warning (OPT_Wattributes, "ignoring %qE attribute applied to "
- "template instantiation %qT", name, *node);
- goto fail;
- }
- else if (CLASS_TYPE_P (*node)
- && CLASSTYPE_TEMPLATE_SPECIALIZATION (*node))
- {
- warning (OPT_Wattributes, "ignoring %qE attribute applied to "
- "template specialization %qT", name, *node);
- goto fail;
- }
+ error ("%qE attribute applied to non-function, non-variable %qD",
+ name, *node);
+ goto fail;
+ }
+ else if (DECL_LANGUAGE (*node) == lang_c)
+ {
+ error ("%qE attribute applied to extern \"C\" declaration %qD",
+ name, *node);
+ goto fail;
+ }
- tree attributes = TYPE_ATTRIBUTES (*node);
- tree decl = TYPE_NAME (*node);
+ return NULL_TREE;
- /* Make sure all declarations have the same abi tags. */
- if (DECL_SOURCE_LOCATION (decl) != input_location)
- {
- if (!check_abi_tag_redeclaration (decl,
- lookup_attribute ("abi_tag",
- attributes),
- args))
- goto fail;
- }
+ fail:
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
+/* Handle an "abi_tag" type attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_abi_tag_type_attribute (tree* node, tree name, tree args,
+ int flags, bool* no_add_attrs)
+{
+ tree attributes, decl;
+ if (!check_abi_tag_args (args, name))
+ goto fail;
+
+ if (!OVERLOAD_TYPE_P (*node))
+ {
+ error ("%qE attribute applied to non-class, non-enum type %qT",
+ name, *node);
+ goto fail;
}
- else
+ else if (!(flags & (int)ATTR_FLAG_TYPE_IN_PLACE))
{
- if (!VAR_OR_FUNCTION_DECL_P (*node))
- {
- error ("%qE attribute applied to non-function, non-variable %qD",
- name, *node);
- goto fail;
- }
- else if (DECL_LANGUAGE (*node) == lang_c)
- {
- error ("%qE attribute applied to extern \"C\" declaration %qD",
- name, *node);
- goto fail;
- }
+ error ("%qE attribute applied to %qT after its definition",
+ name, *node);
+ goto fail;
+ }
+ else if (CLASS_TYPE_P (*node)
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (*node))
+ {
+ warning (OPT_Wattributes, "ignoring %qE attribute applied to "
+ "template instantiation %qT", name, *node);
+ goto fail;
+ }
+ else if (CLASS_TYPE_P (*node)
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (*node))
+ {
+ warning (OPT_Wattributes, "ignoring %qE attribute applied to "
+ "template specialization %qT", name, *node);
+ goto fail;
+ }
+
+ attributes = TYPE_ATTRIBUTES (*node);
+ decl = TYPE_NAME (*node);
+
+ /* Make sure all declarations have the same abi tags. */
+ if (DECL_SOURCE_LOCATION (decl) != input_location)
+ {
+ if (!check_abi_tag_redeclaration (decl,
+ lookup_attribute ("abi_tag",
+ attributes),
+ args))
+ goto fail;
}
return NULL_TREE;
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index ab79229cbe9..8bab3ac3914 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -88,13 +88,13 @@ gfc_handle_omp_declare_target_attribute (tree *, tree, tree, int, bool *)
/* Table of valid Fortran attributes. */
static const struct attribute_spec gfc_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
{ "omp declare target", 0, 0, true, false, false,
- gfc_handle_omp_declare_target_attribute, false },
+ gfc_handle_omp_declare_target_attribute, NULL, false },
{ "oacc function", 0, -1, true, false, false,
- gfc_handle_omp_declare_target_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ gfc_handle_omp_declare_target_attribute, NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
#undef LANG_HOOKS_NAME
diff --git a/gcc/java/lang.c b/gcc/java/lang.c
index 1c6dde455e2..1c90f499ea4 100644
--- a/gcc/java/lang.c
+++ b/gcc/java/lang.c
@@ -65,9 +65,8 @@ static tree java_eh_personality (void);
/* Table of machine-independent attributes. */
const struct attribute_spec java_attribute_table[] =
{
- { "nonnull", 0, -1, false, true, true,
- NULL, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ { "nonnull", 0, -1, false, true, true, NULL, NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Used to avoid printing error messages with bogus function
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index ec4db44e277..6a5a5f6d45a 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -59,40 +59,41 @@ static tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
/* Table of machine-independent attributes supported in GIMPLE. */
const struct attribute_spec lto_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- do_diagnostic } */
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, do_diagnostic } */
{ "noreturn", 0, 0, true, false, false,
- handle_noreturn_attribute, false },
+ handle_noreturn_attribute, NULL, false },
{ "leaf", 0, 0, true, false, false,
- handle_leaf_attribute, false },
+ handle_leaf_attribute, NULL, false },
/* The same comments as for noreturn attributes apply to const ones. */
{ "const", 0, 0, true, false, false,
- handle_const_attribute, false },
+ handle_const_attribute, NULL, false },
{ "malloc", 0, 0, true, false, false,
- handle_malloc_attribute, false },
+ handle_malloc_attribute, NULL, false },
{ "pure", 0, 0, true, false, false,
- handle_pure_attribute, false },
+ handle_pure_attribute, NULL, false },
{ "no vops", 0, 0, true, false, false,
- handle_novops_attribute, false },
+ handle_novops_attribute, NULL, false },
{ "nonnull", 0, -1, false, true, true,
- handle_nonnull_attribute, false },
+ NULL, handle_nonnull_attribute, false },
{ "nothrow", 0, 0, true, false, false,
- handle_nothrow_attribute, false },
+ handle_nothrow_attribute, NULL, false },
{ "returns_twice", 0, 0, true, false, false,
- handle_returns_twice_attribute, false },
+ handle_returns_twice_attribute, NULL, false },
{ "sentinel", 0, 1, false, true, true,
- handle_sentinel_attribute, false },
+ NULL, handle_sentinel_attribute, false },
{ "type generic", 0, 0, false, true, true,
- handle_type_generic_attribute, false },
+ NULL, handle_type_generic_attribute, false },
{ "fn spec", 1, 1, false, true, true,
- handle_fnspec_attribute, false },
+ NULL, handle_fnspec_attribute, false },
{ "transaction_pure", 0, 0, false, true, true,
- handle_transaction_pure_attribute, false },
+ NULL, handle_transaction_pure_attribute, false },
/* 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,
- ignore_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ NULL, ignore_attribute,
+ false },
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
/* Give the specifications for the format attributes, used by C and all
@@ -100,13 +101,15 @@ const struct attribute_spec lto_attribute_table[] =
const struct attribute_spec lto_format_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
+ type_handler, affects_type_identity } */
{ "format", 3, 3, false, true, true,
+ NULL,
handle_format_attribute, false },
{ "format_arg", 1, 1, false, true, true,
+ NULL,
handle_format_arg_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ { NULL, 0, 0, false, false, false, NULL, NULL, false }
};
enum built_in_attribute
diff --git a/gcc/testsuite/g++.dg/plugin/attribute_plugin.c b/gcc/testsuite/g++.dg/plugin/attribute_plugin.c
index 8de5f44cbf8..4f52df73e1e 100644
--- a/gcc/testsuite/g++.dg/plugin/attribute_plugin.c
+++ b/gcc/testsuite/g++.dg/plugin/attribute_plugin.c
@@ -26,7 +26,7 @@ handle_user_attribute (tree *node, tree name, tree args,
/* Attribute definition */
static struct attribute_spec user_attr =
- { "user", 1, 1, false, false, false, handle_user_attribute, false };
+ { "user", 1, 1, false, false, false, handle_user_attribute, NULL, false };
/* Plugin callback called during attribute registration */
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 484a5a8bfae..cfe84543c0e 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1835,7 +1835,7 @@ struct attribute_spec {
and from a function return type (which is not itself a function
pointer type) to the function type. */
bool function_type_required;
- /* Function to handle this attribute. NODE points to the node to which
+ /* Functions to handle this attribute. NODE points to the node to which
the attribute is to be applied. If a DECL, it should be modified in
place; if a TYPE, a copy should be created. NAME is the name of the
attribute (possibly with leading or trailing __). ARGS is the TREE_LIST
@@ -1849,7 +1849,9 @@ struct attribute_spec {
otherwise the return value should be NULL_TREE. This pointer may be
NULL if no special handling is required beyond the checks implied
by the rest of this structure. */
- tree (*handler) (tree *node, tree name, tree args,
+ tree (*decl_handler) (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs);
+ tree (*type_handler) (tree *node, tree name, tree args,
int flags, bool *no_add_attrs);
/* Specifies if attribute affects type's identity. */
bool affects_type_identity;
diff --git a/gcc/tree.c b/gcc/tree.c
index 2d9020b5c15..2c200897401 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -6360,42 +6360,16 @@ merge_dllimport_decl_attributes (tree old, tree new_tree)
return a;
}
-/* Handle a "dllimport" or "dllexport" attribute; arguments as in
+/* Handle a "dllimport" or "dllexport" attribute for decls; arguments as in
struct attribute_spec.handler. */
tree
-handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
- bool *no_add_attrs)
+handle_dll_decl_attribute (tree * pnode, tree name, tree args, int flags,
+ bool *no_add_attrs)
{
tree node = *pnode;
bool is_dllimport;
- /* These attributes may apply to structure and union types being created,
- but otherwise should pass to the declaration involved. */
- if (!DECL_P (node))
- {
- if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
- | (int) ATTR_FLAG_ARRAY_NEXT))
- {
- *no_add_attrs = true;
- return tree_cons (name, args, NULL_TREE);
- }
- if (TREE_CODE (node) == RECORD_TYPE
- || TREE_CODE (node) == UNION_TYPE)
- {
- node = TYPE_NAME (node);
- if (!node)
- return NULL_TREE;
- }
- else
- {
- warning (OPT_Wattributes, "%qE attribute ignored",
- name);
- *no_add_attrs = true;
- return NULL_TREE;
- }
- }
-
if (TREE_CODE (node) != FUNCTION_DECL
&& TREE_CODE (node) != VAR_DECL
&& TREE_CODE (node) != TYPE_DECL)
@@ -6497,6 +6471,39 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
return NULL_TREE;
}
+
+/* Handle a "dllimport" or "dllexport" attribute for types; arguments as in
+ struct attribute_spec.handler. */
+
+tree
+handle_dll_type_attribute (tree * pnode, tree name, tree args, int flags,
+ bool *no_add_attrs)
+{
+ tree node = *pnode;
+
+ /* These attributes may apply to structure and union types being created,
+ but otherwise should pass to the declaration involved. */
+ if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
+ | (int) ATTR_FLAG_ARRAY_NEXT))
+ {
+ *no_add_attrs = true;
+ return tree_cons (name, args, NULL_TREE);
+ }
+
+ if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ if (!TYPE_NAME (node))
+ return NULL_TREE;
+
+ return handle_dll_decl_attribute (&TYPE_NAME (node), name, args, flags,
+ no_add_attrs);
+}
+
#endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES */
/* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask
diff --git a/gcc/tree.h b/gcc/tree.h
index 06c25930b44..d953c0d01ca 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4158,7 +4158,8 @@ extern tree merge_attributes (tree, tree);
extern tree merge_dllimport_decl_attributes (tree, tree);
/* Handle a "dllimport" or "dllexport" attribute. */
-extern tree handle_dll_attribute (tree *, tree, tree, int, bool *);
+extern tree handle_dll_decl_attribute (tree *, tree, tree, int, bool *);
+extern tree handle_dll_type_attribute (tree *, tree, tree, int, bool *);
/* Returns true iff unqualified CAND and BASE are equivalent. */