mirror of git://gcc.gnu.org/git/gcc.git
PR c/81544 - attribute noreturn and warn_unused_result on the same function accepted
PR c/81544 - attribute noreturn and warn_unused_result on the same function accepted PR c/81566 - invalid attribute aligned accepted on functions gcc/ada/ChangeLog: PR c/81544 * gcc-interface/utils.c (gnat_internal_attribute_table): Initialize new member of struct attribute_spec. gcc/c/ChangeLog: PR c/81544 * c-decl.c (c_decl_attributes): Look up existing declaration and pass it to decl_attributes. gcc/c-family/ChangeLog: PR c/81544 PR c/81566 * c-attribs.c (attr_aligned_exclusions): New array. (attr_alloc_exclusions, attr_cold_hot_exclusions): Same. (attr_common_exclusions, attr_const_pure_exclusions): Same. (attr_gnu_inline_exclusions, attr_inline_exclusions): Same. (attr_noreturn_exclusions, attr_returns_twice_exclusions): Same. (attr_warn_unused_result_exclusions): Same. (handle_hot_attribute, handle_cold_attribute): Simplify. (handle_const_attribute): Warn on function returning void. (handle_pure_attribute): Same. (handle_aligned_attribute): Diagnose conflicting attribute specifications. * c-warn.c (diagnose_mismatched_attributes): Simplify. gcc/cp/ChangeLog: PR c/81544 * cp-tree.h (decls_match): Add default argument. * decl.c (decls_match): Avoid calling into the target back end and triggering an error. * decl2.c (cplus_decl_attributes): Look up existing declaration and pass it to decl_attributes. * tree.c (cxx_attribute_table): Initialize new member of struct attribute_spec. gcc/fortran/ChangeLog: PR c/81544 * f95-lang.c (gfc_attribute_table): Initialize new member of struct attribute_spec. gcc/lto/ChangeLog: PR c/81544 * lto-lang.c (lto_attribute_table): Initialize new member of struct attribute_spec. gcc/ChangeLog: PR c/81544 * attribs.c (empty_attribute_table): Initialize new member of struct attribute_spec. (decl_attributes): Add argument. Handle mutually exclusive combinations of attributes. (selftests::test_attribute_exclusions): New function. (selftests::attribute_c_tests): Ditto. * attribs.h (decl_attributes): Add default argument. * selftest.h (attribute_c_tests): Declare. * selftest-run-tests.c (selftest::run_tests): Call attribute_c_tests. * tree-core.h (attribute_spec::exclusions, exclude): New type and member. * doc/extend.texi (Common Function Attributes): Update const and pure. gcc/testsuite/ChangeLog: PR c/81544 * c-c++-common/Wattributes-2.c: New test. * c-c++-common/Wattributes.c: New test. * c-c++-common/attributes-3.c: Adjust. * gcc.dg/Wattributes-6.c: New test. * gcc.dg/Wattributes-7.c: New test. * gcc.dg/attr-noinline.c * gcc.dg/pr44964.c: Same. * gcc.dg/torture/pr42363.c: Same. * gcc.dg/tree-ssa/ssa-ccp-2.c: Same. From-SVN: r255469
This commit is contained in:
parent
1d8b0222b1
commit
5d9ae53d70
|
|
@ -1,3 +1,50 @@
|
||||||
|
2017-12-07 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR c/81544
|
||||||
|
* attribs.c (empty_attribute_table): Initialize new member of
|
||||||
|
struct attribute_spec.
|
||||||
|
(decl_attributes): Add argument. Handle mutually exclusive
|
||||||
|
combinations of attributes.
|
||||||
|
(selftests::test_attribute_exclusions): New function.
|
||||||
|
(selftests::attribute_c_tests): Ditto.
|
||||||
|
* attribs.h (decl_attributes): Add default argument.
|
||||||
|
* selftest.h (attribute_c_tests): Declare.
|
||||||
|
* selftest-run-tests.c (selftest::run_tests): Call attribute_c_tests.
|
||||||
|
* tree-core.h (attribute_spec::exclusions, exclude): New type and
|
||||||
|
member.
|
||||||
|
* doc/extend.texi (Common Function Attributes): Update const and pure.
|
||||||
|
* config/alpha/alpha.c (vms_attribute_table): Initialize new member
|
||||||
|
of struct attribute_spec.
|
||||||
|
* config/arc/arc.c (arc_attribute_table): Same.
|
||||||
|
* config/arm/arm.c (arm_attribute_table): Same.
|
||||||
|
* config/avr/avr.c ( avr_attribute_table): Same.
|
||||||
|
* config/bfin/bfin.c (bfin_attribute_table): Same.
|
||||||
|
* config/cr16/cr16.c (cr16_attribute_table): Same.
|
||||||
|
* config/epiphany/epiphany.c (epiphany_attribute_table): Same.
|
||||||
|
* config/h8300/h8300.c (h8300_attribute_table): Same.
|
||||||
|
* config/i386/i386.c (ix86_attribute_table): Same.
|
||||||
|
* config/ia64/ia64.c (ia64_attribute_table): Same.
|
||||||
|
* config/m32c/m32c.c (m32c_attribute_table): Same.
|
||||||
|
* config/m32r/m32r.c (m32r_attribute_table): Same.
|
||||||
|
* config/m68k/m68k.c (m68k_attribute_table): Same.
|
||||||
|
* config/mcore/mcore.c (mcore_attribute_table): Same.
|
||||||
|
* config/microblaze/microblaze.c (microblaze_attribute_table): Same.
|
||||||
|
* config/mips/mips.c (mips_attribute_table): Same.
|
||||||
|
* config/msp430/msp430.c (msp430_attribute_table): Same.
|
||||||
|
* config/nds32/nds32.c (nds32_attribute_table): Same.
|
||||||
|
* config/nvptx/nvptx.c (nvptx_attribute_table): Same.
|
||||||
|
* config/powerpcspe/powerpcspe.c (rs6000_attribute_table): Same.
|
||||||
|
* config/rl78/rl78.c (rl78__attribute_table): Same.
|
||||||
|
* config/rs6000/rs6000.c (rs6000_attribute_table): Same.
|
||||||
|
* onfig/rx/rx.c (rx_attribute_table): Same.
|
||||||
|
* config/s390/s390.c (s390_handle_vectorbool_attribute): Same.
|
||||||
|
* config/sh/sh.c (sh_attribute_table): Same.
|
||||||
|
* config/sparc/sparc.c (sparc_attribute_table): Same.
|
||||||
|
* config/spu/spu.c (spu_attribute_table): Same.
|
||||||
|
* config/stormy16/stormy16.c (xstormy16_attribute_table): Same.
|
||||||
|
* config/v850/v850.c (v850_attribute_table): Same.
|
||||||
|
* config/visium/visium.c (visium_attribute_table): Same.
|
||||||
|
|
||||||
2017-12-07 Tamar Christina <tamar.christina@arm.com>
|
2017-12-07 Tamar Christina <tamar.christina@arm.com>
|
||||||
|
|
||||||
PR target/82641
|
PR target/82641
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
2017-12-07 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR c/81544
|
||||||
|
* gcc-interface/utils.c (gnat_internal_attribute_table): Initialize
|
||||||
|
new member of struct attribute_spec.
|
||||||
|
|
||||||
2017-12-06 Simon Wright <simon@pushface.org>
|
2017-12-06 Simon Wright <simon@pushface.org>
|
||||||
|
|
||||||
PR ada/66205
|
PR ada/66205
|
||||||
|
|
|
||||||
|
|
@ -110,45 +110,47 @@ const struct attribute_spec gnat_internal_attribute_table[] =
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity } */
|
||||||
{ "const", 0, 0, true, false, false, handle_const_attribute,
|
{ "const", 0, 0, true, false, false, handle_const_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "nothrow", 0, 0, true, false, false, handle_nothrow_attribute,
|
{ "nothrow", 0, 0, true, false, false, handle_nothrow_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "pure", 0, 0, true, false, false, handle_pure_attribute,
|
{ "pure", 0, 0, true, false, false, handle_pure_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "no vops", 0, 0, true, false, false, handle_novops_attribute,
|
{ "no vops", 0, 0, true, false, false, handle_novops_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "nonnull", 0, -1, false, true, true, handle_nonnull_attribute,
|
{ "nonnull", 0, -1, false, true, true, handle_nonnull_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "sentinel", 0, 1, false, true, true, handle_sentinel_attribute,
|
{ "sentinel", 0, 1, false, true, true, handle_sentinel_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "noreturn", 0, 0, true, false, false, handle_noreturn_attribute,
|
{ "noreturn", 0, 0, true, false, false, handle_noreturn_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "noinline", 0, 0, true, false, false, handle_noinline_attribute,
|
{ "noinline", 0, 0, true, false, false, handle_noinline_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "noclone", 0, 0, true, false, false, handle_noclone_attribute,
|
{ "noclone", 0, 0, true, false, false, handle_noclone_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "leaf", 0, 0, true, false, false, handle_leaf_attribute,
|
{ "leaf", 0, 0, true, false, false, handle_leaf_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "always_inline",0, 0, true, false, false, handle_always_inline_attribute,
|
{ "always_inline",0, 0, true, false, false, handle_always_inline_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "malloc", 0, 0, true, false, false, handle_malloc_attribute,
|
{ "malloc", 0, 0, true, false, false, handle_malloc_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "type generic", 0, 0, false, true, true, handle_type_generic_attribute,
|
{ "type generic", 0, 0, false, true, true, handle_type_generic_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
|
|
||||||
{ "vector_size", 1, 1, false, true, false, handle_vector_size_attribute,
|
{ "vector_size", 1, 1, false, true, false, handle_vector_size_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "vector_type", 0, 0, false, true, false, handle_vector_type_attribute,
|
{ "vector_type", 0, 0, false, true, false, handle_vector_type_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "may_alias", 0, 0, false, true, false, NULL, false },
|
{ "may_alias", 0, 0, false, true, false, NULL, false, NULL },
|
||||||
|
|
||||||
/* ??? format and format_arg are heavy and not supported, which actually
|
/* ??? format and format_arg are heavy and not supported, which actually
|
||||||
prevents support for stdio builtins, which we however declare as part
|
prevents support for stdio builtins, which we however declare as part
|
||||||
of the common builtins.def contents. */
|
of the common builtins.def contents. */
|
||||||
{ "format", 3, 3, false, true, true, fake_attribute_handler, false },
|
{ "format", 3, 3, false, true, true, fake_attribute_handler, false,
|
||||||
{ "format_arg", 1, 1, false, true, true, fake_attribute_handler, false },
|
NULL },
|
||||||
|
{ "format_arg", 1, 1, false, true, true, fake_attribute_handler, false,
|
||||||
|
NULL },
|
||||||
|
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Associates a GNAT tree node to a GCC tree node. It is used in
|
/* Associates a GNAT tree node to a GCC tree node. It is used in
|
||||||
|
|
|
||||||
277
gcc/attribs.c
277
gcc/attribs.c
|
|
@ -28,6 +28,8 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "stor-layout.h"
|
#include "stor-layout.h"
|
||||||
#include "langhooks.h"
|
#include "langhooks.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "selftest.h"
|
||||||
|
#include "hash-set.h"
|
||||||
|
|
||||||
/* Table of the tables of attributes (common, language, format, machine)
|
/* Table of the tables of attributes (common, language, format, machine)
|
||||||
searched. */
|
searched. */
|
||||||
|
|
@ -94,7 +96,7 @@ static bool attributes_initialized = false;
|
||||||
|
|
||||||
static const struct attribute_spec empty_attribute_table[] =
|
static const struct attribute_spec empty_attribute_table[] =
|
||||||
{
|
{
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Return base name of the attribute. Ie '__attr__' is turned into 'attr'.
|
/* Return base name of the attribute. Ie '__attr__' is turned into 'attr'.
|
||||||
|
|
@ -343,6 +345,97 @@ get_attribute_namespace (const_tree attr)
|
||||||
return get_identifier ("gnu");
|
return get_identifier ("gnu");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check LAST_DECL and NODE of the same symbol for attributes that are
|
||||||
|
recorded in SPEC to be mutually exclusive with ATTRNAME, diagnose
|
||||||
|
them, and return true if any have been found. NODE can be a DECL
|
||||||
|
or a TYPE. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
diag_attr_exclusions (tree last_decl, tree node, tree attrname,
|
||||||
|
const attribute_spec *spec)
|
||||||
|
{
|
||||||
|
const attribute_spec::exclusions *excl = spec->exclude;
|
||||||
|
|
||||||
|
tree_code code = TREE_CODE (node);
|
||||||
|
|
||||||
|
if ((code == FUNCTION_DECL && !excl->function
|
||||||
|
&& (!excl->type || !spec->affects_type_identity))
|
||||||
|
|| (code == VAR_DECL && !excl->variable
|
||||||
|
&& (!excl->type || !spec->affects_type_identity))
|
||||||
|
|| (((code == TYPE_DECL || RECORD_OR_UNION_TYPE_P (node)) && !excl->type)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* True if an attribute that's mutually exclusive with ATTRNAME
|
||||||
|
has been found. */
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
if (last_decl && last_decl != node && TREE_TYPE (last_decl) != node)
|
||||||
|
{
|
||||||
|
/* Check both the last DECL and its type for conflicts with
|
||||||
|
the attribute being added to the current decl or type. */
|
||||||
|
found |= diag_attr_exclusions (last_decl, last_decl, attrname, spec);
|
||||||
|
tree decl_type = TREE_TYPE (last_decl);
|
||||||
|
found |= diag_attr_exclusions (last_decl, decl_type, attrname, spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NODE is either the current DECL to which the attribute is being
|
||||||
|
applied or its TYPE. For the former, consider the attributes on
|
||||||
|
both the DECL and its type. */
|
||||||
|
tree attrs[2];
|
||||||
|
|
||||||
|
if (DECL_P (node))
|
||||||
|
{
|
||||||
|
attrs[0] = DECL_ATTRIBUTES (node);
|
||||||
|
attrs[1] = TYPE_ATTRIBUTES (TREE_TYPE (node));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attrs[0] = TYPE_ATTRIBUTES (node);
|
||||||
|
attrs[1] = NULL_TREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterate over the mutually exclusive attribute names and verify
|
||||||
|
that the symbol doesn't contain it. */
|
||||||
|
for (unsigned i = 0; i != sizeof attrs / sizeof *attrs; ++i)
|
||||||
|
{
|
||||||
|
if (!attrs[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for ( ; excl->name; ++excl)
|
||||||
|
{
|
||||||
|
/* Avoid checking the attribute against itself. */
|
||||||
|
if (is_attribute_p (excl->name, attrname))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!lookup_attribute (excl->name, attrs[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
/* Print a note? */
|
||||||
|
bool note = last_decl != NULL_TREE;
|
||||||
|
|
||||||
|
if (TREE_CODE (node) == FUNCTION_DECL
|
||||||
|
&& DECL_BUILT_IN (node))
|
||||||
|
note &= warning (OPT_Wattributes,
|
||||||
|
"ignoring attribute %qE in declaration of "
|
||||||
|
"a built-in function %qD because it conflicts "
|
||||||
|
"with attribute %qs",
|
||||||
|
attrname, node, excl->name);
|
||||||
|
else
|
||||||
|
note &= warning (OPT_Wattributes,
|
||||||
|
"ignoring attribute %qE because "
|
||||||
|
"it conflicts with attribute %qs",
|
||||||
|
attrname, excl->name);
|
||||||
|
|
||||||
|
if (note)
|
||||||
|
inform (DECL_SOURCE_LOCATION (last_decl),
|
||||||
|
"previous declaration here");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
|
/* 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,
|
which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL,
|
||||||
|
|
@ -354,7 +447,8 @@ get_attribute_namespace (const_tree attr)
|
||||||
a decl attribute to the declaration rather than to its type). */
|
a decl attribute to the declaration rather than to its type). */
|
||||||
|
|
||||||
tree
|
tree
|
||||||
decl_attributes (tree *node, tree attributes, int flags)
|
decl_attributes (tree *node, tree attributes, int flags,
|
||||||
|
tree last_decl /* = NULL_TREE */)
|
||||||
{
|
{
|
||||||
tree a;
|
tree a;
|
||||||
tree returned_attrs = NULL_TREE;
|
tree returned_attrs = NULL_TREE;
|
||||||
|
|
@ -433,6 +527,8 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||||
|
|
||||||
targetm.insert_attributes (*node, &attributes);
|
targetm.insert_attributes (*node, &attributes);
|
||||||
|
|
||||||
|
/* Note that attributes on the same declaration are not necessarily
|
||||||
|
in the same order as in the source. */
|
||||||
for (a = attributes; a; a = TREE_CHAIN (a))
|
for (a = attributes; a; a = TREE_CHAIN (a))
|
||||||
{
|
{
|
||||||
tree ns = get_attribute_namespace (a);
|
tree ns = get_attribute_namespace (a);
|
||||||
|
|
@ -441,7 +537,6 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||||
tree *anode = node;
|
tree *anode = node;
|
||||||
const struct attribute_spec *spec =
|
const struct attribute_spec *spec =
|
||||||
lookup_scoped_attribute_spec (ns, name);
|
lookup_scoped_attribute_spec (ns, name);
|
||||||
bool no_add_attrs = 0;
|
|
||||||
int fn_ptr_quals = 0;
|
int fn_ptr_quals = 0;
|
||||||
tree fn_ptr_tmp = NULL_TREE;
|
tree fn_ptr_tmp = NULL_TREE;
|
||||||
|
|
||||||
|
|
@ -490,7 +585,8 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||||
| (int) ATTR_FLAG_ARRAY_NEXT))
|
| (int) ATTR_FLAG_ARRAY_NEXT))
|
||||||
{
|
{
|
||||||
/* Pass on this attribute to be tried again. */
|
/* Pass on this attribute to be tried again. */
|
||||||
returned_attrs = tree_cons (name, args, returned_attrs);
|
tree attr = tree_cons (name, args, NULL_TREE);
|
||||||
|
returned_attrs = chainon (returned_attrs, attr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -535,7 +631,8 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||||
else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
|
else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
|
||||||
{
|
{
|
||||||
/* Pass on this attribute to be tried again. */
|
/* Pass on this attribute to be tried again. */
|
||||||
returned_attrs = tree_cons (name, args, returned_attrs);
|
tree attr = tree_cons (name, args, NULL_TREE);
|
||||||
|
returned_attrs = chainon (returned_attrs, attr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -557,15 +654,56 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool no_add_attrs = false;
|
||||||
|
|
||||||
if (spec->handler != NULL)
|
if (spec->handler != NULL)
|
||||||
{
|
{
|
||||||
int cxx11_flag =
|
int cxx11_flag =
|
||||||
cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0;
|
cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0;
|
||||||
|
|
||||||
returned_attrs = chainon ((*spec->handler) (anode, name, args,
|
/* Pass in an array of the current declaration followed
|
||||||
flags|cxx11_flag,
|
by the last pushed/merged declaration if one exists.
|
||||||
&no_add_attrs),
|
If the handler changes CUR_AND_LAST_DECL[0] replace
|
||||||
returned_attrs);
|
*ANODE with its value. */
|
||||||
|
tree cur_and_last_decl[] = { *anode, last_decl };
|
||||||
|
tree ret = (spec->handler) (cur_and_last_decl, name, args,
|
||||||
|
flags|cxx11_flag, &no_add_attrs);
|
||||||
|
|
||||||
|
*anode = cur_and_last_decl[0];
|
||||||
|
if (ret == error_mark_node)
|
||||||
|
{
|
||||||
|
warning (OPT_Wattributes, "%qE attribute ignored", name);
|
||||||
|
no_add_attrs = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
returned_attrs = chainon (ret, returned_attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the attribute was successfully handled on its own and is
|
||||||
|
about to be added check for exclusions with other attributes
|
||||||
|
on the current declation as well as the last declaration of
|
||||||
|
the same symbol already processed (if one exists). */
|
||||||
|
bool built_in = flags & ATTR_FLAG_BUILT_IN;
|
||||||
|
if (spec->exclude
|
||||||
|
&& !no_add_attrs
|
||||||
|
&& (flag_checking || !built_in))
|
||||||
|
{
|
||||||
|
/* Always check attributes on user-defined functions.
|
||||||
|
Check them on built-ins only when -fchecking is set.
|
||||||
|
Ignore __builtin_unreachable -- it's both const and
|
||||||
|
noreturn. */
|
||||||
|
|
||||||
|
if (!built_in
|
||||||
|
|| !DECL_P (*anode)
|
||||||
|
|| (DECL_FUNCTION_CODE (*anode) != BUILT_IN_UNREACHABLE
|
||||||
|
&& (DECL_FUNCTION_CODE (*anode)
|
||||||
|
!= BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE)))
|
||||||
|
{
|
||||||
|
bool no_add = diag_attr_exclusions (last_decl, *anode, name, spec);
|
||||||
|
if (!no_add && anode != node)
|
||||||
|
no_add = diag_attr_exclusions (last_decl, *node, name, spec);
|
||||||
|
no_add_attrs |= no_add;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Layout the decl in case anything changed. */
|
/* Layout the decl in case anything changed. */
|
||||||
|
|
@ -1647,3 +1785,124 @@ private_lookup_attribute (const char *attr_name, size_t attr_len, tree list)
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CHECKING_P
|
||||||
|
|
||||||
|
namespace selftest
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Helper types to verify the consistency attribute exclusions. */
|
||||||
|
|
||||||
|
typedef std::pair<const char *, const char *> excl_pair;
|
||||||
|
|
||||||
|
struct excl_hash_traits: typed_noop_remove<excl_pair>
|
||||||
|
{
|
||||||
|
typedef excl_pair value_type;
|
||||||
|
typedef value_type compare_type;
|
||||||
|
|
||||||
|
static hashval_t hash (const value_type &x)
|
||||||
|
{
|
||||||
|
hashval_t h1 = htab_hash_string (x.first);
|
||||||
|
hashval_t h2 = htab_hash_string (x.second);
|
||||||
|
return h1 ^ h2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool equal (const value_type &x, const value_type &y)
|
||||||
|
{
|
||||||
|
return !strcmp (x.first, y.first) && !strcmp (x.second, y.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mark_deleted (value_type &x)
|
||||||
|
{
|
||||||
|
x = value_type (NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mark_empty (value_type &x)
|
||||||
|
{
|
||||||
|
x = value_type ("", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_deleted (const value_type &x)
|
||||||
|
{
|
||||||
|
return !x.first && !x.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_empty (const value_type &x)
|
||||||
|
{
|
||||||
|
return !*x.first && !*x.second;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Self-test to verify that each attribute exclusion is symmetric,
|
||||||
|
meaning that if attribute A is encoded as incompatible with
|
||||||
|
attribute B then the opposite relationship is also encoded.
|
||||||
|
This test also detects most cases of misspelled attribute names
|
||||||
|
in exclusions. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_attribute_exclusions ()
|
||||||
|
{
|
||||||
|
/* Iterate over the array of attribute tables first (with TI0 as
|
||||||
|
the index) and over the array of attribute_spec in each table
|
||||||
|
(with SI0 as the index). */
|
||||||
|
const size_t ntables = ARRAY_SIZE (attribute_tables);
|
||||||
|
|
||||||
|
/* Set of pairs of mutually exclusive attributes. */
|
||||||
|
typedef hash_set<excl_pair, excl_hash_traits> exclusion_set;
|
||||||
|
exclusion_set excl_set;
|
||||||
|
|
||||||
|
for (size_t ti0 = 0; ti0 != ntables; ++ti0)
|
||||||
|
for (size_t s0 = 0; attribute_tables[ti0][s0].name; ++s0)
|
||||||
|
{
|
||||||
|
const attribute_spec::exclusions *excl
|
||||||
|
= attribute_tables[ti0][s0].exclude;
|
||||||
|
|
||||||
|
/* Skip each attribute that doesn't define exclusions. */
|
||||||
|
if (!excl)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char *attr_name = attribute_tables[ti0][s0].name;
|
||||||
|
|
||||||
|
/* Iterate over the set of exclusions for every attribute
|
||||||
|
(with EI0 as the index) adding the exclusions defined
|
||||||
|
for each to the set. */
|
||||||
|
for (size_t ei0 = 0; excl[ei0].name; ++ei0)
|
||||||
|
{
|
||||||
|
const char *excl_name = excl[ei0].name;
|
||||||
|
|
||||||
|
if (!strcmp (attr_name, excl_name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
excl_set.add (excl_pair (attr_name, excl_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Traverse the set of mutually exclusive pairs of attributes
|
||||||
|
and verify that they are symmetric. */
|
||||||
|
for (exclusion_set::iterator it = excl_set.begin ();
|
||||||
|
it != excl_set.end ();
|
||||||
|
++it)
|
||||||
|
{
|
||||||
|
if (!excl_set.contains (excl_pair ((*it).second, (*it).first)))
|
||||||
|
{
|
||||||
|
/* An exclusion for an attribute has been found that
|
||||||
|
doesn't have a corresponding exclusion in the opposite
|
||||||
|
direction. */
|
||||||
|
char desc[120];
|
||||||
|
sprintf (desc, "'%s' attribute exclusion '%s' must be symmetric",
|
||||||
|
(*it).first, (*it).second);
|
||||||
|
fail (SELFTEST_LOCATION, desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
attribute_c_tests ()
|
||||||
|
{
|
||||||
|
test_attribute_exclusions ();
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace selftest */
|
||||||
|
|
||||||
|
#endif /* CHECKING_P */
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ extern void init_attributes (void);
|
||||||
from tree.h. Depending on these flags, some attributes may be
|
from tree.h. Depending on these flags, some attributes may be
|
||||||
returned to be applied at a later stage (for example, to apply
|
returned to be applied at a later stage (for example, to apply
|
||||||
a decl attribute to the declaration rather than to its type). */
|
a decl attribute to the declaration rather than to its type). */
|
||||||
extern tree decl_attributes (tree *, tree, int);
|
extern tree decl_attributes (tree *, tree, int, tree = NULL_TREE);
|
||||||
|
|
||||||
extern bool cxx11_attribute_p (const_tree);
|
extern bool cxx11_attribute_p (const_tree);
|
||||||
extern tree get_attribute_name (const_tree);
|
extern tree get_attribute_name (const_tree);
|
||||||
|
|
|
||||||
|
|
@ -450,16 +450,16 @@ const struct attribute_spec brig_attribute_table[] =
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
do_diagnostic } */
|
do_diagnostic } */
|
||||||
{ "leaf", 0, 0, true, false, false,
|
{ "leaf", 0, 0, true, false, false,
|
||||||
handle_leaf_attribute, false },
|
handle_leaf_attribute, false, NULL },
|
||||||
{ "const", 0, 0, true, false, false,
|
{ "const", 0, 0, true, false, false,
|
||||||
handle_const_attribute, false },
|
handle_const_attribute, false, NULL },
|
||||||
{ "pure", 0, 0, true, false, false,
|
{ "pure", 0, 0, true, false, false,
|
||||||
handle_pure_attribute, false },
|
handle_pure_attribute, false, NULL },
|
||||||
{ "nothrow", 0, 0, true, false, false,
|
{ "nothrow", 0, 0, true, false, false,
|
||||||
handle_nothrow_attribute, false },
|
handle_nothrow_attribute, false, NULL },
|
||||||
{ "returns_twice", 0, 0, true, false, false,
|
{ "returns_twice", 0, 0, true, false, false,
|
||||||
handle_returns_twice_attribute, false },
|
handle_returns_twice_attribute, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Attribute handlers. */
|
/* Attribute handlers. */
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,20 @@
|
||||||
|
2017-12-07 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR c/81544
|
||||||
|
PR c/81566
|
||||||
|
* c-attribs.c (attr_aligned_exclusions): New array.
|
||||||
|
(attr_alloc_exclusions, attr_cold_hot_exclusions): Same.
|
||||||
|
(attr_common_exclusions, attr_const_pure_exclusions): Same.
|
||||||
|
(attr_gnu_inline_exclusions, attr_inline_exclusions): Same.
|
||||||
|
(attr_noreturn_exclusions, attr_returns_twice_exclusions): Same.
|
||||||
|
(attr_warn_unused_result_exclusions): Same.
|
||||||
|
(handle_hot_attribute, handle_cold_attribute): Simplify.
|
||||||
|
(handle_const_attribute): Warn on function returning void.
|
||||||
|
(handle_pure_attribute): Same.
|
||||||
|
(handle_aligned_attribute): Diagnose conflicting attribute
|
||||||
|
specifications.
|
||||||
|
* c-warn.c (diagnose_mismatched_attributes): Simplify.
|
||||||
|
|
||||||
2017-12-06 David Malcolm <dmalcolm@redhat.com>
|
2017-12-06 David Malcolm <dmalcolm@redhat.com>
|
||||||
|
|
||||||
PR c/83236
|
PR c/83236
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,93 @@ static tree handle_fallthrough_attribute (tree *, tree, tree, int, bool *);
|
||||||
static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
|
static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
|
||||||
int, bool *);
|
int, bool *);
|
||||||
|
|
||||||
|
/* Helper to define attribute exclusions. */
|
||||||
|
#define ATTR_EXCL(name, function, type, variable) \
|
||||||
|
{ name, function, type, variable }
|
||||||
|
|
||||||
|
/* Define attributes that are mutually exclusive with one another. */
|
||||||
|
static const struct attribute_spec::exclusions attr_aligned_exclusions[] =
|
||||||
|
{
|
||||||
|
/* Attribute name exclusion applies to:
|
||||||
|
function, type, variable */
|
||||||
|
ATTR_EXCL ("aligned", true, false, false),
|
||||||
|
ATTR_EXCL ("packed", true, false, false),
|
||||||
|
ATTR_EXCL (NULL, false, false, false)
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
|
||||||
|
{
|
||||||
|
ATTR_EXCL ("cold", true, true, true),
|
||||||
|
ATTR_EXCL ("hot", true, true, true),
|
||||||
|
ATTR_EXCL (NULL, false, false, false)
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_spec::exclusions attr_common_exclusions[] =
|
||||||
|
{
|
||||||
|
ATTR_EXCL ("common", true, true, true),
|
||||||
|
ATTR_EXCL ("nocommon", true, true, true),
|
||||||
|
ATTR_EXCL (NULL, false, false, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_spec::exclusions attr_inline_exclusions[] =
|
||||||
|
{
|
||||||
|
ATTR_EXCL ("noinline", true, true, true),
|
||||||
|
ATTR_EXCL (NULL, false, false, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
|
||||||
|
{
|
||||||
|
ATTR_EXCL ("always_inline", true, true, true),
|
||||||
|
ATTR_EXCL ("gnu_inline", true, true, true),
|
||||||
|
ATTR_EXCL (NULL, false, false, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
|
||||||
|
{
|
||||||
|
ATTR_EXCL ("alloc_align", true, true, true),
|
||||||
|
ATTR_EXCL ("alloc_size", true, true, true),
|
||||||
|
ATTR_EXCL ("const", true, true, true),
|
||||||
|
ATTR_EXCL ("malloc", true, true, true),
|
||||||
|
ATTR_EXCL ("pure", true, true, true),
|
||||||
|
ATTR_EXCL ("returns_twice", true, true, true),
|
||||||
|
ATTR_EXCL ("warn_unused_result", true, true, true),
|
||||||
|
ATTR_EXCL (NULL, false, false, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_spec::exclusions
|
||||||
|
attr_warn_unused_result_exclusions[] =
|
||||||
|
{
|
||||||
|
ATTR_EXCL ("noreturn", true, true, true),
|
||||||
|
ATTR_EXCL ("warn_unused_result", true, true, true),
|
||||||
|
ATTR_EXCL (NULL, false, false, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
|
||||||
|
{
|
||||||
|
ATTR_EXCL ("noreturn", true, true, true),
|
||||||
|
ATTR_EXCL (NULL, false, false, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Exclusions that apply to attribute alloc_align, alloc_size, and malloc. */
|
||||||
|
static const struct attribute_spec::exclusions attr_alloc_exclusions[] =
|
||||||
|
{
|
||||||
|
ATTR_EXCL ("const", true, true, true),
|
||||||
|
ATTR_EXCL ("noreturn", true, true, true),
|
||||||
|
ATTR_EXCL ("pure", true, true, true),
|
||||||
|
ATTR_EXCL (NULL, false, false, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
|
||||||
|
{
|
||||||
|
ATTR_EXCL ("const", true, true, true),
|
||||||
|
ATTR_EXCL ("alloc_align", true, true, true),
|
||||||
|
ATTR_EXCL ("alloc_size", true, true, true),
|
||||||
|
ATTR_EXCL ("malloc", true, true, true),
|
||||||
|
ATTR_EXCL ("noreturn", true, true, true),
|
||||||
|
ATTR_EXCL ("pure", true, true, true),
|
||||||
|
ATTR_EXCL (NULL, false, false, false)
|
||||||
|
};
|
||||||
|
|
||||||
/* Table of machine-independent attributes common to all C-like languages.
|
/* Table of machine-independent attributes common to all C-like languages.
|
||||||
|
|
||||||
All attributes referencing arguments should be additionally processed
|
All attributes referencing arguments should be additionally processed
|
||||||
|
|
@ -161,214 +248,233 @@ const struct attribute_spec c_common_attribute_table[] =
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity } */
|
||||||
{ "packed", 0, 0, false, false, false,
|
{ "packed", 0, 0, false, false, false,
|
||||||
handle_packed_attribute , false},
|
handle_packed_attribute, false,
|
||||||
|
attr_aligned_exclusions },
|
||||||
{ "nocommon", 0, 0, true, false, false,
|
{ "nocommon", 0, 0, true, false, false,
|
||||||
handle_nocommon_attribute, false},
|
handle_nocommon_attribute, false,
|
||||||
|
attr_common_exclusions },
|
||||||
{ "common", 0, 0, true, false, false,
|
{ "common", 0, 0, true, false, false,
|
||||||
handle_common_attribute, false },
|
handle_common_attribute, false,
|
||||||
|
attr_common_exclusions },
|
||||||
/* FIXME: logically, noreturn attributes should be listed as
|
/* FIXME: logically, noreturn attributes should be listed as
|
||||||
"false, true, true" and apply to function types. But implementing this
|
"false, true, true" and apply to function types. But implementing this
|
||||||
would require all the places in the compiler that use TREE_THIS_VOLATILE
|
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
|
on a decl to identify non-returning functions to be located and fixed
|
||||||
to check the function type instead. */
|
to check the function type instead. */
|
||||||
{ "noreturn", 0, 0, true, false, false,
|
{ "noreturn", 0, 0, true, false, false,
|
||||||
handle_noreturn_attribute, false },
|
handle_noreturn_attribute, false,
|
||||||
|
attr_noreturn_exclusions },
|
||||||
{ "volatile", 0, 0, true, false, false,
|
{ "volatile", 0, 0, true, false, false,
|
||||||
handle_noreturn_attribute, false },
|
handle_noreturn_attribute, false, NULL },
|
||||||
{ "stack_protect", 0, 0, true, false, false,
|
{ "stack_protect", 0, 0, true, false, false,
|
||||||
handle_stack_protect_attribute, false },
|
handle_stack_protect_attribute, false, NULL },
|
||||||
{ "noinline", 0, 0, true, false, false,
|
{ "noinline", 0, 0, true, false, false,
|
||||||
handle_noinline_attribute, false },
|
handle_noinline_attribute, false,
|
||||||
|
attr_noinline_exclusions },
|
||||||
{ "noclone", 0, 0, true, false, false,
|
{ "noclone", 0, 0, true, false, false,
|
||||||
handle_noclone_attribute, false },
|
handle_noclone_attribute, false, NULL },
|
||||||
{ "no_icf", 0, 0, true, false, false,
|
{ "no_icf", 0, 0, true, false, false,
|
||||||
handle_noicf_attribute, false },
|
handle_noicf_attribute, false, NULL },
|
||||||
{ "noipa", 0, 0, true, false, false,
|
{ "noipa", 0, 0, true, false, false,
|
||||||
handle_noipa_attribute, false },
|
handle_noipa_attribute, false, NULL },
|
||||||
{ "leaf", 0, 0, true, false, false,
|
{ "leaf", 0, 0, true, false, false,
|
||||||
handle_leaf_attribute, false },
|
handle_leaf_attribute, false, NULL },
|
||||||
{ "always_inline", 0, 0, true, false, false,
|
{ "always_inline", 0, 0, true, false, false,
|
||||||
handle_always_inline_attribute, false },
|
handle_always_inline_attribute, false,
|
||||||
|
attr_inline_exclusions },
|
||||||
{ "gnu_inline", 0, 0, true, false, false,
|
{ "gnu_inline", 0, 0, true, false, false,
|
||||||
handle_gnu_inline_attribute, false },
|
handle_gnu_inline_attribute, false,
|
||||||
|
attr_inline_exclusions },
|
||||||
{ "artificial", 0, 0, true, false, false,
|
{ "artificial", 0, 0, true, false, false,
|
||||||
handle_artificial_attribute, false },
|
handle_artificial_attribute, false, NULL },
|
||||||
{ "flatten", 0, 0, true, false, false,
|
{ "flatten", 0, 0, true, false, false,
|
||||||
handle_flatten_attribute, false },
|
handle_flatten_attribute, false, NULL },
|
||||||
{ "used", 0, 0, true, false, false,
|
{ "used", 0, 0, true, false, false,
|
||||||
handle_used_attribute, false },
|
handle_used_attribute, false, NULL },
|
||||||
{ "unused", 0, 0, false, false, false,
|
{ "unused", 0, 0, false, false, false,
|
||||||
handle_unused_attribute, false },
|
handle_unused_attribute, false, NULL },
|
||||||
{ "externally_visible", 0, 0, true, false, false,
|
{ "externally_visible", 0, 0, true, false, false,
|
||||||
handle_externally_visible_attribute, false },
|
handle_externally_visible_attribute, false, NULL },
|
||||||
{ "no_reorder", 0, 0, true, false, false,
|
{ "no_reorder", 0, 0, true, false, false,
|
||||||
handle_no_reorder_attribute, false },
|
handle_no_reorder_attribute, false, NULL },
|
||||||
/* The same comments as for noreturn attributes apply to const ones. */
|
/* The same comments as for noreturn attributes apply to const ones. */
|
||||||
{ "const", 0, 0, true, false, false,
|
{ "const", 0, 0, true, false, false,
|
||||||
handle_const_attribute, false },
|
handle_const_attribute, false,
|
||||||
|
attr_const_pure_exclusions },
|
||||||
{ "scalar_storage_order", 1, 1, false, false, false,
|
{ "scalar_storage_order", 1, 1, false, false, false,
|
||||||
handle_scalar_storage_order_attribute, false },
|
handle_scalar_storage_order_attribute, false, NULL },
|
||||||
{ "transparent_union", 0, 0, false, false, false,
|
{ "transparent_union", 0, 0, false, false, false,
|
||||||
handle_transparent_union_attribute, false },
|
handle_transparent_union_attribute, false, NULL },
|
||||||
{ "constructor", 0, 1, true, false, false,
|
{ "constructor", 0, 1, true, false, false,
|
||||||
handle_constructor_attribute, false },
|
handle_constructor_attribute, false, NULL },
|
||||||
{ "destructor", 0, 1, true, false, false,
|
{ "destructor", 0, 1, true, false, false,
|
||||||
handle_destructor_attribute, false },
|
handle_destructor_attribute, false, NULL },
|
||||||
{ "mode", 1, 1, false, true, false,
|
{ "mode", 1, 1, false, true, false,
|
||||||
handle_mode_attribute, false },
|
handle_mode_attribute, false, NULL },
|
||||||
{ "section", 1, 1, true, false, false,
|
{ "section", 1, 1, true, false, false,
|
||||||
handle_section_attribute, false },
|
handle_section_attribute, false, NULL },
|
||||||
{ "aligned", 0, 1, false, false, false,
|
{ "aligned", 0, 1, false, false, false,
|
||||||
handle_aligned_attribute, false },
|
handle_aligned_attribute, false,
|
||||||
|
attr_aligned_exclusions },
|
||||||
{ "warn_if_not_aligned", 0, 1, false, false, false,
|
{ "warn_if_not_aligned", 0, 1, false, false, false,
|
||||||
handle_warn_if_not_aligned_attribute,
|
handle_warn_if_not_aligned_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "weak", 0, 0, true, false, false,
|
{ "weak", 0, 0, true, false, false,
|
||||||
handle_weak_attribute, false },
|
handle_weak_attribute, false, NULL },
|
||||||
{ "noplt", 0, 0, true, false, false,
|
{ "noplt", 0, 0, true, false, false,
|
||||||
handle_noplt_attribute, false },
|
handle_noplt_attribute, false, NULL },
|
||||||
{ "ifunc", 1, 1, true, false, false,
|
{ "ifunc", 1, 1, true, false, false,
|
||||||
handle_ifunc_attribute, false },
|
handle_ifunc_attribute, false, NULL },
|
||||||
{ "alias", 1, 1, true, false, false,
|
{ "alias", 1, 1, true, false, false,
|
||||||
handle_alias_attribute, false },
|
handle_alias_attribute, false, NULL },
|
||||||
{ "weakref", 0, 1, true, false, false,
|
{ "weakref", 0, 1, true, false, false,
|
||||||
handle_weakref_attribute, false },
|
handle_weakref_attribute, false, NULL },
|
||||||
{ "no_instrument_function", 0, 0, true, false, false,
|
{ "no_instrument_function", 0, 0, true, false, false,
|
||||||
handle_no_instrument_function_attribute,
|
handle_no_instrument_function_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "no_profile_instrument_function", 0, 0, true, false, false,
|
{ "no_profile_instrument_function", 0, 0, true, false, false,
|
||||||
handle_no_profile_instrument_function_attribute,
|
handle_no_profile_instrument_function_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "malloc", 0, 0, true, false, false,
|
{ "malloc", 0, 0, true, false, false,
|
||||||
handle_malloc_attribute, false },
|
handle_malloc_attribute, false,
|
||||||
|
attr_alloc_exclusions },
|
||||||
{ "returns_twice", 0, 0, true, false, false,
|
{ "returns_twice", 0, 0, true, false, false,
|
||||||
handle_returns_twice_attribute, false },
|
handle_returns_twice_attribute, false,
|
||||||
|
attr_returns_twice_exclusions },
|
||||||
{ "no_stack_limit", 0, 0, true, false, false,
|
{ "no_stack_limit", 0, 0, true, false, false,
|
||||||
handle_no_limit_stack_attribute, false },
|
handle_no_limit_stack_attribute, false, NULL },
|
||||||
{ "pure", 0, 0, true, false, false,
|
{ "pure", 0, 0, true, false, false,
|
||||||
handle_pure_attribute, false },
|
handle_pure_attribute, false,
|
||||||
|
attr_const_pure_exclusions },
|
||||||
{ "transaction_callable", 0, 0, false, true, false,
|
{ "transaction_callable", 0, 0, false, true, false,
|
||||||
handle_tm_attribute, false },
|
handle_tm_attribute, false, NULL },
|
||||||
{ "transaction_unsafe", 0, 0, false, true, false,
|
{ "transaction_unsafe", 0, 0, false, true, false,
|
||||||
handle_tm_attribute, true },
|
handle_tm_attribute, true, NULL },
|
||||||
{ "transaction_safe", 0, 0, false, true, false,
|
{ "transaction_safe", 0, 0, false, true, false,
|
||||||
handle_tm_attribute, true },
|
handle_tm_attribute, true, NULL },
|
||||||
{ "transaction_safe_dynamic", 0, 0, true, false, false,
|
{ "transaction_safe_dynamic", 0, 0, true, false, false,
|
||||||
handle_tm_attribute, false },
|
handle_tm_attribute, false, NULL },
|
||||||
{ "transaction_may_cancel_outer", 0, 0, false, true, false,
|
{ "transaction_may_cancel_outer", 0, 0, false, true, false,
|
||||||
handle_tm_attribute, false },
|
handle_tm_attribute, false, NULL },
|
||||||
/* ??? These two attributes didn't make the transition from the
|
/* ??? These two attributes didn't make the transition from the
|
||||||
Intel language document to the multi-vendor language document. */
|
Intel language document to the multi-vendor language document. */
|
||||||
{ "transaction_pure", 0, 0, false, true, false,
|
{ "transaction_pure", 0, 0, false, true, false,
|
||||||
handle_tm_attribute, false },
|
handle_tm_attribute, false, NULL },
|
||||||
{ "transaction_wrap", 1, 1, true, false, false,
|
{ "transaction_wrap", 1, 1, true, false, false,
|
||||||
handle_tm_wrap_attribute, false },
|
handle_tm_wrap_attribute, false, NULL },
|
||||||
/* For internal use (marking of builtins) only. The name contains space
|
/* For internal use (marking of builtins) only. The name contains space
|
||||||
to prevent its usage in source code. */
|
to prevent its usage in source code. */
|
||||||
{ "no vops", 0, 0, true, false, false,
|
{ "no vops", 0, 0, true, false, false,
|
||||||
handle_novops_attribute, false },
|
handle_novops_attribute, false, NULL },
|
||||||
{ "deprecated", 0, 1, false, false, false,
|
{ "deprecated", 0, 1, false, false, false,
|
||||||
handle_deprecated_attribute, false },
|
handle_deprecated_attribute, false, NULL },
|
||||||
{ "vector_size", 1, 1, false, true, false,
|
{ "vector_size", 1, 1, false, true, false,
|
||||||
handle_vector_size_attribute, true },
|
handle_vector_size_attribute, true, NULL },
|
||||||
{ "visibility", 1, 1, false, false, false,
|
{ "visibility", 1, 1, false, false, false,
|
||||||
handle_visibility_attribute, false },
|
handle_visibility_attribute, false, NULL },
|
||||||
{ "tls_model", 1, 1, true, false, false,
|
{ "tls_model", 1, 1, true, false, false,
|
||||||
handle_tls_model_attribute, false },
|
handle_tls_model_attribute, false, NULL },
|
||||||
{ "nonnull", 0, -1, false, true, true,
|
{ "nonnull", 0, -1, false, true, true,
|
||||||
handle_nonnull_attribute, false },
|
handle_nonnull_attribute, false, NULL },
|
||||||
{ "nonstring", 0, 0, true, false, false,
|
{ "nonstring", 0, 0, true, false, false,
|
||||||
handle_nonstring_attribute, false },
|
handle_nonstring_attribute, false, NULL },
|
||||||
{ "nothrow", 0, 0, true, false, false,
|
{ "nothrow", 0, 0, true, false, false,
|
||||||
handle_nothrow_attribute, false },
|
handle_nothrow_attribute, false, NULL },
|
||||||
{ "may_alias", 0, 0, false, true, false, NULL, false },
|
{ "may_alias", 0, 0, false, true, false, NULL, false, NULL },
|
||||||
{ "cleanup", 1, 1, true, false, false,
|
{ "cleanup", 1, 1, true, false, false,
|
||||||
handle_cleanup_attribute, false },
|
handle_cleanup_attribute, false, NULL },
|
||||||
{ "warn_unused_result", 0, 0, false, true, true,
|
{ "warn_unused_result", 0, 0, false, true, true,
|
||||||
handle_warn_unused_result_attribute, false },
|
handle_warn_unused_result_attribute, false,
|
||||||
|
attr_warn_unused_result_exclusions },
|
||||||
{ "sentinel", 0, 1, false, true, true,
|
{ "sentinel", 0, 1, false, true, true,
|
||||||
handle_sentinel_attribute, false },
|
handle_sentinel_attribute, false, NULL },
|
||||||
/* For internal use (marking of builtins) only. The name contains space
|
/* For internal use (marking of builtins) only. The name contains space
|
||||||
to prevent its usage in source code. */
|
to prevent its usage in source code. */
|
||||||
{ "type generic", 0, 0, false, true, true,
|
{ "type generic", 0, 0, false, true, true,
|
||||||
handle_type_generic_attribute, false },
|
handle_type_generic_attribute, false, NULL },
|
||||||
{ "alloc_size", 1, 2, false, true, true,
|
{ "alloc_size", 1, 2, false, true, true,
|
||||||
handle_alloc_size_attribute, false },
|
handle_alloc_size_attribute, false,
|
||||||
|
attr_alloc_exclusions },
|
||||||
{ "cold", 0, 0, true, false, false,
|
{ "cold", 0, 0, true, false, false,
|
||||||
handle_cold_attribute, false },
|
handle_cold_attribute, false,
|
||||||
|
attr_cold_hot_exclusions },
|
||||||
{ "hot", 0, 0, true, false, false,
|
{ "hot", 0, 0, true, false, false,
|
||||||
handle_hot_attribute, false },
|
handle_hot_attribute, false,
|
||||||
|
attr_cold_hot_exclusions },
|
||||||
{ "no_address_safety_analysis",
|
{ "no_address_safety_analysis",
|
||||||
0, 0, true, false, false,
|
0, 0, true, false, false,
|
||||||
handle_no_address_safety_analysis_attribute,
|
handle_no_address_safety_analysis_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "no_sanitize", 1, 1, true, false, false,
|
{ "no_sanitize", 1, 1, true, false, false,
|
||||||
handle_no_sanitize_attribute,
|
handle_no_sanitize_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "no_sanitize_address", 0, 0, true, false, false,
|
{ "no_sanitize_address", 0, 0, true, false, false,
|
||||||
handle_no_sanitize_address_attribute,
|
handle_no_sanitize_address_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "no_sanitize_thread", 0, 0, true, false, false,
|
{ "no_sanitize_thread", 0, 0, true, false, false,
|
||||||
handle_no_sanitize_thread_attribute,
|
handle_no_sanitize_thread_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "no_sanitize_undefined", 0, 0, true, false, false,
|
{ "no_sanitize_undefined", 0, 0, true, false, false,
|
||||||
handle_no_sanitize_undefined_attribute,
|
handle_no_sanitize_undefined_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "asan odr indicator", 0, 0, true, false, false,
|
{ "asan odr indicator", 0, 0, true, false, false,
|
||||||
handle_asan_odr_indicator_attribute,
|
handle_asan_odr_indicator_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "warning", 1, 1, true, false, false,
|
{ "warning", 1, 1, true, false, false,
|
||||||
handle_error_attribute, false },
|
handle_error_attribute, false, NULL },
|
||||||
{ "error", 1, 1, true, false, false,
|
{ "error", 1, 1, true, false, false,
|
||||||
handle_error_attribute, false },
|
handle_error_attribute, false, NULL },
|
||||||
{ "target", 1, -1, true, false, false,
|
{ "target", 1, -1, true, false, false,
|
||||||
handle_target_attribute, false },
|
handle_target_attribute, false, NULL },
|
||||||
{ "target_clones", 1, -1, true, false, false,
|
{ "target_clones", 1, -1, true, false, false,
|
||||||
handle_target_clones_attribute, false },
|
handle_target_clones_attribute, false, NULL },
|
||||||
{ "optimize", 1, -1, true, false, false,
|
{ "optimize", 1, -1, true, false, false,
|
||||||
handle_optimize_attribute, false },
|
handle_optimize_attribute, false, NULL },
|
||||||
/* For internal use only. The leading '*' both prevents its usage in
|
/* For internal use only. The leading '*' both prevents its usage in
|
||||||
source code and signals that it may be overridden by machine tables. */
|
source code and signals that it may be overridden by machine tables. */
|
||||||
{ "*tm regparm", 0, 0, false, true, true,
|
{ "*tm regparm", 0, 0, false, true, true,
|
||||||
ignore_attribute, false },
|
ignore_attribute, false, NULL },
|
||||||
{ "no_split_stack", 0, 0, true, false, false,
|
{ "no_split_stack", 0, 0, true, false, false,
|
||||||
handle_no_split_stack_attribute, false },
|
handle_no_split_stack_attribute, false, NULL },
|
||||||
/* For internal use (marking of builtins and runtime functions) only.
|
/* For internal use (marking of builtins and runtime functions) only.
|
||||||
The name contains space to prevent its usage in source code. */
|
The name contains space to prevent its usage in source code. */
|
||||||
{ "fn spec", 1, 1, false, true, true,
|
{ "fn spec", 1, 1, false, true, true,
|
||||||
handle_fnspec_attribute, false },
|
handle_fnspec_attribute, false, NULL },
|
||||||
{ "warn_unused", 0, 0, false, false, false,
|
{ "warn_unused", 0, 0, false, false, false,
|
||||||
handle_warn_unused_attribute, false },
|
handle_warn_unused_attribute, false, NULL },
|
||||||
{ "returns_nonnull", 0, 0, false, true, true,
|
{ "returns_nonnull", 0, 0, false, true, true,
|
||||||
handle_returns_nonnull_attribute, false },
|
handle_returns_nonnull_attribute, false, NULL },
|
||||||
{ "omp declare simd", 0, -1, true, false, false,
|
{ "omp declare simd", 0, -1, true, false, false,
|
||||||
handle_omp_declare_simd_attribute, false },
|
handle_omp_declare_simd_attribute, false, NULL },
|
||||||
|
{ "cilk simd function", 0, -1, true, false, false,
|
||||||
|
handle_omp_declare_simd_attribute, false, NULL },
|
||||||
{ "simd", 0, 1, true, false, false,
|
{ "simd", 0, 1, true, false, false,
|
||||||
handle_simd_attribute, false },
|
handle_simd_attribute, false, NULL },
|
||||||
{ "omp declare target", 0, 0, true, false, false,
|
{ "omp declare target", 0, 0, true, false, false,
|
||||||
handle_omp_declare_target_attribute, false },
|
handle_omp_declare_target_attribute, false, NULL },
|
||||||
{ "omp declare target link", 0, 0, true, false, false,
|
{ "omp declare target link", 0, 0, true, false, false,
|
||||||
handle_omp_declare_target_attribute, false },
|
handle_omp_declare_target_attribute, false, NULL },
|
||||||
{ "alloc_align", 1, 1, false, true, true,
|
{ "alloc_align", 1, 1, false, true, true,
|
||||||
handle_alloc_align_attribute, false },
|
handle_alloc_align_attribute, false,
|
||||||
|
attr_alloc_exclusions },
|
||||||
{ "assume_aligned", 1, 2, false, true, true,
|
{ "assume_aligned", 1, 2, false, true, true,
|
||||||
handle_assume_aligned_attribute, false },
|
handle_assume_aligned_attribute, false, NULL },
|
||||||
{ "designated_init", 0, 0, false, true, false,
|
{ "designated_init", 0, 0, false, true, false,
|
||||||
handle_designated_init_attribute, false },
|
handle_designated_init_attribute, false, NULL },
|
||||||
{ "bnd_variable_size", 0, 0, true, false, false,
|
{ "bnd_variable_size", 0, 0, true, false, false,
|
||||||
handle_bnd_variable_size_attribute, false },
|
handle_bnd_variable_size_attribute, false, NULL },
|
||||||
{ "bnd_legacy", 0, 0, true, false, false,
|
{ "bnd_legacy", 0, 0, true, false, false,
|
||||||
handle_bnd_legacy, false },
|
handle_bnd_legacy, false, NULL },
|
||||||
{ "bnd_instrument", 0, 0, true, false, false,
|
{ "bnd_instrument", 0, 0, true, false, false,
|
||||||
handle_bnd_instrument, false },
|
handle_bnd_instrument, false, NULL },
|
||||||
{ "fallthrough", 0, 0, false, false, false,
|
{ "fallthrough", 0, 0, false, false, false,
|
||||||
handle_fallthrough_attribute, false },
|
handle_fallthrough_attribute, false, NULL },
|
||||||
{ "patchable_function_entry", 1, 2, true, false, false,
|
{ "patchable_function_entry", 1, 2, true, false, false,
|
||||||
handle_patchable_function_entry_attribute,
|
handle_patchable_function_entry_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "nocf_check", 0, 0, false, true, true,
|
{ "nocf_check", 0, 0, false, true, true,
|
||||||
handle_nocf_check_attribute, true },
|
handle_nocf_check_attribute, true, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Give the specifications for the format attributes, used by C and all
|
/* Give the specifications for the format attributes, used by C and all
|
||||||
|
|
@ -383,10 +489,10 @@ const struct attribute_spec c_common_format_attribute_table[] =
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity } */
|
||||||
{ "format", 3, 3, false, true, true,
|
{ "format", 3, 3, false, true, true,
|
||||||
handle_format_attribute, false },
|
handle_format_attribute, false, NULL },
|
||||||
{ "format_arg", 1, 1, false, true, true,
|
{ "format_arg", 1, 1, false, true, true,
|
||||||
handle_format_arg_attribute, false },
|
handle_format_arg_attribute, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Returns TRUE iff the attribute indicated by ATTR_ID takes a plain
|
/* Returns TRUE iff the attribute indicated by ATTR_ID takes a plain
|
||||||
|
|
@ -524,14 +630,7 @@ handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
||||||
if (TREE_CODE (*node) == FUNCTION_DECL
|
if (TREE_CODE (*node) == FUNCTION_DECL
|
||||||
|| TREE_CODE (*node) == LABEL_DECL)
|
|| TREE_CODE (*node) == LABEL_DECL)
|
||||||
{
|
{
|
||||||
if (lookup_attribute ("cold", DECL_ATTRIBUTES (*node)) != NULL)
|
/* Attribute hot processing is done later with lookup_attribute. */
|
||||||
{
|
|
||||||
warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
|
|
||||||
"with attribute %qs", name, "cold");
|
|
||||||
*no_add_attrs = true;
|
|
||||||
}
|
|
||||||
/* Most of the rest of the hot processing is done later with
|
|
||||||
lookup_attribute. */
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -552,14 +651,7 @@ handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
||||||
if (TREE_CODE (*node) == FUNCTION_DECL
|
if (TREE_CODE (*node) == FUNCTION_DECL
|
||||||
|| TREE_CODE (*node) == LABEL_DECL)
|
|| TREE_CODE (*node) == LABEL_DECL)
|
||||||
{
|
{
|
||||||
if (lookup_attribute ("hot", DECL_ATTRIBUTES (*node)) != NULL)
|
/* Attribute cold processing is done later with lookup_attribute. */
|
||||||
{
|
|
||||||
warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
|
|
||||||
"with attribute %qs", name, "hot");
|
|
||||||
*no_add_attrs = true;
|
|
||||||
}
|
|
||||||
/* Most of the rest of the cold processing is done later with
|
|
||||||
lookup_attribute. */
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1086,7 +1178,7 @@ handle_no_reorder_attribute (tree *pnode,
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
||||||
int ARG_UNUSED (flags), bool *no_add_attrs)
|
int flags, bool *no_add_attrs)
|
||||||
{
|
{
|
||||||
tree type = TREE_TYPE (*node);
|
tree type = TREE_TYPE (*node);
|
||||||
|
|
||||||
|
|
@ -1107,6 +1199,14 @@ handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
||||||
*no_add_attrs = true;
|
*no_add_attrs = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* void __builtin_unreachable(void) is const. Accept other such
|
||||||
|
built-ins but warn on user-defined functions that return void. */
|
||||||
|
if (!(flags & ATTR_FLAG_BUILT_IN)
|
||||||
|
&& TREE_CODE (*node) == FUNCTION_DECL
|
||||||
|
&& VOID_TYPE_P (TREE_TYPE (type)))
|
||||||
|
warning (OPT_Wattributes, "%qE attribute on function "
|
||||||
|
"returning %<void%>", name);
|
||||||
|
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1689,15 +1789,19 @@ check_cxx_fundamental_alignment_constraints (tree node,
|
||||||
handle_aligned_attribute. */
|
handle_aligned_attribute. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
common_handle_aligned_attribute (tree *node, tree args, int flags,
|
common_handle_aligned_attribute (tree *node, tree name, tree args, int flags,
|
||||||
bool *no_add_attrs,
|
bool *no_add_attrs,
|
||||||
bool warn_if_not_aligned_p)
|
bool warn_if_not_aligned_p)
|
||||||
{
|
{
|
||||||
tree decl = NULL_TREE;
|
tree decl = NULL_TREE;
|
||||||
tree *type = NULL;
|
tree *type = NULL;
|
||||||
int is_type = 0;
|
bool is_type = false;
|
||||||
tree align_expr;
|
tree align_expr;
|
||||||
int i;
|
|
||||||
|
/* The last (already pushed) declaration with all validated attributes
|
||||||
|
merged in or the current about-to-be-pushed one if one hasn't been
|
||||||
|
yet. */
|
||||||
|
tree last_decl = node[1] ? node[1] : *node;
|
||||||
|
|
||||||
if (args)
|
if (args)
|
||||||
{
|
{
|
||||||
|
|
@ -1716,10 +1820,21 @@ common_handle_aligned_attribute (tree *node, tree args, int flags,
|
||||||
is_type = TREE_CODE (*node) == TYPE_DECL;
|
is_type = TREE_CODE (*node) == TYPE_DECL;
|
||||||
}
|
}
|
||||||
else if (TYPE_P (*node))
|
else if (TYPE_P (*node))
|
||||||
type = node, is_type = 1;
|
type = node, is_type = true;
|
||||||
|
|
||||||
if ((i = check_user_alignment (align_expr, true)) == -1
|
/* Log2 of specified alignment. */
|
||||||
|| !check_cxx_fundamental_alignment_constraints (*node, i, flags))
|
int pow2align = check_user_alignment (align_expr, true);
|
||||||
|
|
||||||
|
/* The alignment in bits corresponding to the specified alignment. */
|
||||||
|
unsigned bitalign = (1U << pow2align) * BITS_PER_UNIT;
|
||||||
|
|
||||||
|
/* The alignment of the current declaration and that of the last
|
||||||
|
pushed declaration, determined on demand below. */
|
||||||
|
unsigned curalign = 0;
|
||||||
|
unsigned lastalign = 0;
|
||||||
|
|
||||||
|
if (pow2align == -1
|
||||||
|
|| !check_cxx_fundamental_alignment_constraints (*node, pow2align, flags))
|
||||||
*no_add_attrs = true;
|
*no_add_attrs = true;
|
||||||
else if (is_type)
|
else if (is_type)
|
||||||
{
|
{
|
||||||
|
|
@ -1742,12 +1857,12 @@ common_handle_aligned_attribute (tree *node, tree args, int flags,
|
||||||
|
|
||||||
if (warn_if_not_aligned_p)
|
if (warn_if_not_aligned_p)
|
||||||
{
|
{
|
||||||
SET_TYPE_WARN_IF_NOT_ALIGN (*type, (1U << i) * BITS_PER_UNIT);
|
SET_TYPE_WARN_IF_NOT_ALIGN (*type, bitalign);
|
||||||
warn_if_not_aligned_p = false;
|
warn_if_not_aligned_p = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SET_TYPE_ALIGN (*type, (1U << i) * BITS_PER_UNIT);
|
SET_TYPE_ALIGN (*type, bitalign);
|
||||||
TYPE_USER_ALIGN (*type) = 1;
|
TYPE_USER_ALIGN (*type) = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1757,8 +1872,34 @@ common_handle_aligned_attribute (tree *node, tree args, int flags,
|
||||||
error ("alignment may not be specified for %q+D", decl);
|
error ("alignment may not be specified for %q+D", decl);
|
||||||
*no_add_attrs = true;
|
*no_add_attrs = true;
|
||||||
}
|
}
|
||||||
|
else if (TREE_CODE (decl) == FUNCTION_DECL
|
||||||
|
&& ((curalign = DECL_ALIGN (decl)) > bitalign
|
||||||
|
|| ((lastalign = DECL_ALIGN (last_decl)) > bitalign)))
|
||||||
|
{
|
||||||
|
/* Either a prior attribute on the same declaration or one
|
||||||
|
on a prior declaration of the same function specifies
|
||||||
|
stricter alignment than this attribute. */
|
||||||
|
bool note = lastalign != 0;
|
||||||
|
if (lastalign)
|
||||||
|
curalign = lastalign;
|
||||||
|
|
||||||
|
curalign /= BITS_PER_UNIT;
|
||||||
|
bitalign /= BITS_PER_UNIT;
|
||||||
|
|
||||||
|
if (DECL_USER_ALIGN (decl) || DECL_USER_ALIGN (last_decl))
|
||||||
|
warning (OPT_Wattributes,
|
||||||
|
"ignoring attribute %<%E (%u)%> because it conflicts with "
|
||||||
|
"attribute %<%E (%u)%>", name, bitalign, name, curalign);
|
||||||
|
else
|
||||||
|
error ("alignment for %q+D must be at least %d", decl, curalign);
|
||||||
|
|
||||||
|
if (note)
|
||||||
|
inform (DECL_SOURCE_LOCATION (last_decl), "previous declaration here");
|
||||||
|
|
||||||
|
*no_add_attrs = true;
|
||||||
|
}
|
||||||
else if (DECL_USER_ALIGN (decl)
|
else if (DECL_USER_ALIGN (decl)
|
||||||
&& DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
|
&& DECL_ALIGN (decl) > bitalign)
|
||||||
/* C++-11 [dcl.align/4]:
|
/* C++-11 [dcl.align/4]:
|
||||||
|
|
||||||
When multiple alignment-specifiers are specified for an
|
When multiple alignment-specifiers are specified for an
|
||||||
|
|
@ -1770,7 +1911,7 @@ common_handle_aligned_attribute (tree *node, tree args, int flags,
|
||||||
*no_add_attrs = true;
|
*no_add_attrs = true;
|
||||||
else if (!warn_if_not_aligned_p
|
else if (!warn_if_not_aligned_p
|
||||||
&& TREE_CODE (decl) == FUNCTION_DECL
|
&& TREE_CODE (decl) == FUNCTION_DECL
|
||||||
&& DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
|
&& DECL_ALIGN (decl) > bitalign)
|
||||||
{
|
{
|
||||||
/* Don't warn function alignment here if warn_if_not_aligned_p is
|
/* Don't warn function alignment here if warn_if_not_aligned_p is
|
||||||
true. It will be warned later. */
|
true. It will be warned later. */
|
||||||
|
|
@ -1789,13 +1930,13 @@ common_handle_aligned_attribute (tree *node, tree args, int flags,
|
||||||
{
|
{
|
||||||
if (TREE_CODE (decl) == FIELD_DECL && !DECL_C_BIT_FIELD (decl))
|
if (TREE_CODE (decl) == FIELD_DECL && !DECL_C_BIT_FIELD (decl))
|
||||||
{
|
{
|
||||||
SET_DECL_WARN_IF_NOT_ALIGN (decl, (1U << i) * BITS_PER_UNIT);
|
SET_DECL_WARN_IF_NOT_ALIGN (decl, bitalign);
|
||||||
warn_if_not_aligned_p = false;
|
warn_if_not_aligned_p = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SET_DECL_ALIGN (decl, (1U << i) * BITS_PER_UNIT);
|
SET_DECL_ALIGN (decl, bitalign);
|
||||||
DECL_USER_ALIGN (decl) = 1;
|
DECL_USER_ALIGN (decl) = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1814,10 +1955,10 @@ common_handle_aligned_attribute (tree *node, tree args, int flags,
|
||||||
struct attribute_spec.handler. */
|
struct attribute_spec.handler. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
|
handle_aligned_attribute (tree *node, tree name, tree args,
|
||||||
int flags, bool *no_add_attrs)
|
int flags, bool *no_add_attrs)
|
||||||
{
|
{
|
||||||
return common_handle_aligned_attribute (node, args, flags,
|
return common_handle_aligned_attribute (node, name, args, flags,
|
||||||
no_add_attrs, false);
|
no_add_attrs, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1825,11 +1966,11 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
|
||||||
struct attribute_spec.handler. */
|
struct attribute_spec.handler. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
handle_warn_if_not_aligned_attribute (tree *node, tree ARG_UNUSED (name),
|
handle_warn_if_not_aligned_attribute (tree *node, tree name,
|
||||||
tree args, int flags,
|
tree args, int flags,
|
||||||
bool *no_add_attrs)
|
bool *no_add_attrs)
|
||||||
{
|
{
|
||||||
return common_handle_aligned_attribute (node, args, flags,
|
return common_handle_aligned_attribute (node, name, args, flags,
|
||||||
no_add_attrs, true);
|
no_add_attrs, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2538,8 +2679,15 @@ handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
||||||
int ARG_UNUSED (flags), bool *no_add_attrs)
|
int ARG_UNUSED (flags), bool *no_add_attrs)
|
||||||
{
|
{
|
||||||
if (TREE_CODE (*node) == FUNCTION_DECL)
|
if (TREE_CODE (*node) == FUNCTION_DECL)
|
||||||
DECL_PURE_P (*node) = 1;
|
{
|
||||||
/* ??? TODO: Support types. */
|
tree type = TREE_TYPE (*node);
|
||||||
|
if (VOID_TYPE_P (TREE_TYPE (type)))
|
||||||
|
warning (OPT_Wattributes, "%qE attribute on function "
|
||||||
|
"returning %<void%>", name);
|
||||||
|
|
||||||
|
DECL_PURE_P (*node) = 1;
|
||||||
|
/* ??? TODO: Support types. */
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
warning (OPT_Wattributes, "%qE attribute ignored", name);
|
warning (OPT_Wattributes, "%qE attribute ignored", name);
|
||||||
|
|
|
||||||
|
|
@ -2230,36 +2230,19 @@ diagnose_mismatched_attributes (tree olddecl, tree newdecl)
|
||||||
newdecl);
|
newdecl);
|
||||||
|
|
||||||
/* Diagnose inline __attribute__ ((noinline)) which is silly. */
|
/* Diagnose inline __attribute__ ((noinline)) which is silly. */
|
||||||
|
const char *noinline = "noinline";
|
||||||
|
|
||||||
if (DECL_DECLARED_INLINE_P (newdecl)
|
if (DECL_DECLARED_INLINE_P (newdecl)
|
||||||
&& DECL_UNINLINABLE (olddecl)
|
&& DECL_UNINLINABLE (olddecl)
|
||||||
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
|
&& lookup_attribute (noinline, DECL_ATTRIBUTES (olddecl)))
|
||||||
warned |= warning (OPT_Wattributes, "inline declaration of %qD follows "
|
warned |= warning (OPT_Wattributes, "inline declaration of %qD follows "
|
||||||
"declaration with attribute noinline", newdecl);
|
"declaration with attribute %qs", newdecl, noinline);
|
||||||
else if (DECL_DECLARED_INLINE_P (olddecl)
|
else if (DECL_DECLARED_INLINE_P (olddecl)
|
||||||
&& DECL_UNINLINABLE (newdecl)
|
&& DECL_UNINLINABLE (newdecl)
|
||||||
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
|
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
|
||||||
warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute "
|
warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute "
|
||||||
"noinline follows inline declaration ", newdecl);
|
"%qs follows inline declaration ", newdecl, noinline);
|
||||||
else if (lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))
|
|
||||||
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (olddecl)))
|
|
||||||
warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute "
|
|
||||||
"%qs follows declaration with attribute %qs",
|
|
||||||
newdecl, "noinline", "always_inline");
|
|
||||||
else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (newdecl))
|
|
||||||
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
|
|
||||||
warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute "
|
|
||||||
"%qs follows declaration with attribute %qs",
|
|
||||||
newdecl, "always_inline", "noinline");
|
|
||||||
else if (lookup_attribute ("cold", DECL_ATTRIBUTES (newdecl))
|
|
||||||
&& lookup_attribute ("hot", DECL_ATTRIBUTES (olddecl)))
|
|
||||||
warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute "
|
|
||||||
"%qs follows declaration with attribute %qs",
|
|
||||||
newdecl, "cold", "hot");
|
|
||||||
else if (lookup_attribute ("hot", DECL_ATTRIBUTES (newdecl))
|
|
||||||
&& lookup_attribute ("cold", DECL_ATTRIBUTES (olddecl)))
|
|
||||||
warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute "
|
|
||||||
"%qs follows declaration with attribute %qs",
|
|
||||||
newdecl, "hot", "cold");
|
|
||||||
return warned;
|
return warned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
2017-12-07 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR c/81544
|
||||||
|
* c-decl.c (c_decl_attributes): Look up existing declaration and
|
||||||
|
pass it to decl_attributes.
|
||||||
|
|
||||||
2017-12-06 David Malcolm <dmalcolm@redhat.com>
|
2017-12-06 David Malcolm <dmalcolm@redhat.com>
|
||||||
|
|
||||||
PR c/83236
|
PR c/83236
|
||||||
|
|
|
||||||
|
|
@ -4632,7 +4632,16 @@ c_decl_attributes (tree *node, tree attributes, int flags)
|
||||||
attributes = tree_cons (get_identifier ("omp declare target"),
|
attributes = tree_cons (get_identifier ("omp declare target"),
|
||||||
NULL_TREE, attributes);
|
NULL_TREE, attributes);
|
||||||
}
|
}
|
||||||
return decl_attributes (node, attributes, flags);
|
|
||||||
|
/* Look up the current declaration with all the attributes merged
|
||||||
|
so far so that attributes on the current declaration that's
|
||||||
|
about to be pushed that conflict with the former can be detected,
|
||||||
|
diagnosed, and rejected as appropriate. */
|
||||||
|
tree last_decl = lookup_name (DECL_NAME (*node));
|
||||||
|
if (!last_decl)
|
||||||
|
last_decl = lookup_name_in_scope (DECL_NAME (*node), external_scope);
|
||||||
|
|
||||||
|
return decl_attributes (node, attributes, flags, last_decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7506,9 +7506,10 @@ common_object_handler (tree *node, tree name ATTRIBUTE_UNUSED,
|
||||||
static const struct attribute_spec vms_attribute_table[] =
|
static const struct attribute_spec vms_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ COMMON_OBJECT, 0, 1, true, false, false, common_object_handler, false },
|
{ COMMON_OBJECT, 0, 1, true, false, false, common_object_handler, false,
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
NULL },
|
||||||
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -219,21 +219,23 @@ const struct attribute_spec arc_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity } */
|
||||||
{ "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute, true },
|
{ "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute,
|
||||||
|
true, NULL },
|
||||||
/* Function calls made to this symbol must be done indirectly, because
|
/* 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
|
it may lie outside of the 21/25 bit addressing range of a normal function
|
||||||
call. */
|
call. */
|
||||||
{ "long_call", 0, 0, false, true, true, NULL, false },
|
{ "long_call", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
/* Whereas these functions are always known to reside within the 25 bit
|
/* Whereas these functions are always known to reside within the 25 bit
|
||||||
addressing range of unconditionalized bl. */
|
addressing range of unconditionalized bl. */
|
||||||
{ "medium_call", 0, 0, false, true, true, NULL, false },
|
{ "medium_call", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
/* And these functions are always known to reside within the 21 bit
|
/* And these functions are always known to reside within the 21 bit
|
||||||
addressing range of blcc. */
|
addressing range of blcc. */
|
||||||
{ "short_call", 0, 0, false, true, true, NULL, false },
|
{ "short_call", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
/* Function which are not having the prologue and epilogue generated
|
/* Function which are not having the prologue and epilogue generated
|
||||||
by the compiler. */
|
by the compiler. */
|
||||||
{ "naked", 0, 0, true, false, false, arc_handle_fndecl_attribute, false },
|
{ "naked", 0, 0, true, false, false, arc_handle_fndecl_attribute, false,
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
NULL },
|
||||||
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
static int arc_comp_type_attributes (const_tree, const_tree);
|
static int arc_comp_type_attributes (const_tree, const_tree);
|
||||||
static void arc_file_start (void);
|
static void arc_file_start (void);
|
||||||
|
|
|
||||||
|
|
@ -323,24 +323,24 @@ static HOST_WIDE_INT arm_constant_alignment (const_tree, HOST_WIDE_INT);
|
||||||
static const struct attribute_spec arm_attribute_table[] =
|
static const struct attribute_spec arm_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
/* Function calls made to this symbol must be done indirectly, because
|
/* 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
|
it may lie outside of the 26 bit addressing range of a normal function
|
||||||
call. */
|
call. */
|
||||||
{ "long_call", 0, 0, false, true, true, NULL, false },
|
{ "long_call", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
/* Whereas these functions are always known to reside within the 26 bit
|
/* Whereas these functions are always known to reside within the 26 bit
|
||||||
addressing range. */
|
addressing range. */
|
||||||
{ "short_call", 0, 0, false, true, true, NULL, false },
|
{ "short_call", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
/* Specify the procedure call conventions for a function. */
|
/* Specify the procedure call conventions for a function. */
|
||||||
{ "pcs", 1, 1, false, true, true, arm_handle_pcs_attribute,
|
{ "pcs", 1, 1, false, true, true, arm_handle_pcs_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
/* Interrupt Service Routines have special prologue and epilogue requirements. */
|
/* Interrupt Service Routines have special prologue and epilogue requirements. */
|
||||||
{ "isr", 0, 1, false, false, false, arm_handle_isr_attribute,
|
{ "isr", 0, 1, false, false, false, arm_handle_isr_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute,
|
{ "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "naked", 0, 0, true, false, false, arm_handle_fndecl_attribute,
|
{ "naked", 0, 0, true, false, false, arm_handle_fndecl_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
#ifdef ARM_PE
|
#ifdef ARM_PE
|
||||||
/* ARM/PE has three new attributes:
|
/* ARM/PE has three new attributes:
|
||||||
interfacearm - ?
|
interfacearm - ?
|
||||||
|
|
@ -351,22 +351,24 @@ static const struct attribute_spec arm_attribute_table[] =
|
||||||
them with spaces. We do NOT support this. Instead, use __declspec
|
them with spaces. We do NOT support this. Instead, use __declspec
|
||||||
multiple times.
|
multiple times.
|
||||||
*/
|
*/
|
||||||
{ "dllimport", 0, 0, true, false, false, NULL, false },
|
{ "dllimport", 0, 0, true, false, false, NULL, false, NULL },
|
||||||
{ "dllexport", 0, 0, true, false, false, NULL, false },
|
{ "dllexport", 0, 0, true, false, false, NULL, false, NULL },
|
||||||
{ "interfacearm", 0, 0, true, false, false, arm_handle_fndecl_attribute,
|
{ "interfacearm", 0, 0, true, false, false, arm_handle_fndecl_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
#elif TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
#elif TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
||||||
{ "dllimport", 0, 0, false, false, false, handle_dll_attribute, false },
|
{ "dllimport", 0, 0, false, false, false, handle_dll_attribute, false,
|
||||||
{ "dllexport", 0, 0, false, false, false, handle_dll_attribute, false },
|
NULL },
|
||||||
|
{ "dllexport", 0, 0, false, false, false, handle_dll_attribute, false,
|
||||||
|
NULL },
|
||||||
{ "notshared", 0, 0, false, true, false, arm_handle_notshared_attribute,
|
{ "notshared", 0, 0, false, true, false, arm_handle_notshared_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
#endif
|
#endif
|
||||||
/* ARMv8-M Security Extensions support. */
|
/* ARMv8-M Security Extensions support. */
|
||||||
{ "cmse_nonsecure_entry", 0, 0, true, false, false,
|
{ "cmse_nonsecure_entry", 0, 0, true, false, false,
|
||||||
arm_handle_cmse_nonsecure_entry, false },
|
arm_handle_cmse_nonsecure_entry, false, NULL },
|
||||||
{ "cmse_nonsecure_call", 0, 0, true, false, false,
|
{ "cmse_nonsecure_call", 0, 0, true, false, false,
|
||||||
arm_handle_cmse_nonsecure_call, true },
|
arm_handle_cmse_nonsecure_call, true, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Initialize the GCC target structure. */
|
/* Initialize the GCC target structure. */
|
||||||
|
|
|
||||||
|
|
@ -9877,28 +9877,28 @@ avr_attribute_table[] =
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity } */
|
||||||
{ "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute,
|
{ "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute,
|
{ "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute,
|
{ "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "no_gccisr", 0, 0, true, false, false, avr_handle_fndecl_attribute,
|
{ "no_gccisr", 0, 0, true, false, false, avr_handle_fndecl_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "naked", 0, 0, false, true, true, avr_handle_fntype_attribute,
|
{ "naked", 0, 0, false, true, true, avr_handle_fntype_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute,
|
{ "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute,
|
{ "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "io", 0, 1, true, false, false, avr_handle_addr_attribute,
|
{ "io", 0, 1, true, false, false, avr_handle_addr_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "io_low", 0, 1, true, false, false, avr_handle_addr_attribute,
|
{ "io_low", 0, 1, true, false, false, avr_handle_addr_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "address", 1, 1, true, false, false, avr_handle_addr_attribute,
|
{ "address", 1, 1, true, false, false, avr_handle_addr_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "absdata", 0, 0, true, false, false, avr_handle_absdata_attribute,
|
{ "absdata", 0, 0, true, false, false, avr_handle_absdata_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4906,29 +4906,30 @@ bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
|
||||||
static const struct attribute_spec bfin_attribute_table[] =
|
static const struct attribute_spec bfin_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "interrupt_handler", 0, 0, false, true, true, handle_int_attribute,
|
{ "interrupt_handler", 0, 0, false, true, true, handle_int_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "exception_handler", 0, 0, false, true, true, handle_int_attribute,
|
{ "exception_handler", 0, 0, false, true, true, handle_int_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "nmi_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 },
|
NULL },
|
||||||
{ "kspisusp", 0, 0, false, true, true, NULL, false },
|
{ "nesting", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
{ "saveall", 0, 0, false, true, true, NULL, false },
|
{ "kspisusp", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
|
{ "saveall", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
{ "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
|
{ "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
|
{ "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute,
|
{ "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
|
{ "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "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,
|
||||||
false },
|
false, NULL },
|
||||||
{ "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,
|
||||||
false },
|
false, NULL },
|
||||||
{ "l2", 0, 0, true, false, false, bfin_handle_l2_attribute, false },
|
{ "l2", 0, 0, true, false, false, bfin_handle_l2_attribute, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
|
/* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
|
||||||
|
|
|
||||||
|
|
@ -207,9 +207,9 @@ static void cr16_print_operand_address (FILE *, machine_mode, rtx);
|
||||||
static const struct attribute_spec cr16_attribute_table[] = {
|
static const struct attribute_spec cr16_attribute_table[] = {
|
||||||
/* ISRs have special prologue and epilogue requirements. */
|
/* ISRs have special prologue and epilogue requirements. */
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity }. */
|
affects_type_identity, exclusions }. */
|
||||||
{"interrupt", 0, 0, false, true, true, NULL, false},
|
{"interrupt", 0, 0, false, true, true, NULL, false, NULL},
|
||||||
{NULL, 0, 0, false, false, false, NULL, false}
|
{NULL, 0, 0, false, false, false, NULL, false, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
|
/* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
|
||||||
|
|
|
||||||
|
|
@ -460,13 +460,14 @@ epiphany_init_reg_tables (void)
|
||||||
|
|
||||||
static const struct attribute_spec epiphany_attribute_table[] =
|
static const struct attribute_spec epiphany_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
{ "interrupt", 0, 9, true, false, false, epiphany_handle_interrupt_attribute, true },
|
affects_type_identity, exclusions } */
|
||||||
{ "forwarder_section", 1, 1, true, false, false, epiphany_handle_forwarder_attribute, false },
|
{ "interrupt", 0, 9, true, false, false, epiphany_handle_interrupt_attribute, true, NULL },
|
||||||
{ "long_call", 0, 0, false, true, true, NULL, false },
|
{ "forwarder_section", 1, 1, true, false, false, epiphany_handle_forwarder_attribute, false, NULL },
|
||||||
{ "short_call", 0, 0, false, true, true, NULL, false },
|
{ "long_call", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
{ "disinterrupt", 0, 0, false, true, true, NULL, true },
|
{ "short_call", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ "disinterrupt", 0, 0, false, true, true, NULL, true, NULL },
|
||||||
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Handle an "interrupt" attribute; arguments as in
|
/* Handle an "interrupt" attribute; arguments as in
|
||||||
|
|
|
||||||
|
|
@ -5425,22 +5425,22 @@ h8300_insert_attributes (tree node, tree *attributes)
|
||||||
static const struct attribute_spec h8300_attribute_table[] =
|
static const struct attribute_spec h8300_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "interrupt_handler", 0, 0, true, false, false,
|
{ "interrupt_handler", 0, 0, true, false, false,
|
||||||
h8300_handle_fndecl_attribute, false },
|
h8300_handle_fndecl_attribute, false, NULL },
|
||||||
{ "saveall", 0, 0, true, false, false,
|
{ "saveall", 0, 0, true, false, false,
|
||||||
h8300_handle_fndecl_attribute, false },
|
h8300_handle_fndecl_attribute, false, NULL },
|
||||||
{ "OS_Task", 0, 0, true, false, false,
|
{ "OS_Task", 0, 0, true, false, false,
|
||||||
h8300_handle_fndecl_attribute, false },
|
h8300_handle_fndecl_attribute, false, NULL },
|
||||||
{ "monitor", 0, 0, true, false, false,
|
{ "monitor", 0, 0, true, false, false,
|
||||||
h8300_handle_fndecl_attribute, false },
|
h8300_handle_fndecl_attribute, false, NULL },
|
||||||
{ "function_vector", 0, 0, true, false, false,
|
{ "function_vector", 0, 0, true, false, false,
|
||||||
h8300_handle_fndecl_attribute, false },
|
h8300_handle_fndecl_attribute, false, NULL },
|
||||||
{ "eightbit_data", 0, 0, true, false, false,
|
{ "eightbit_data", 0, 0, true, false, false,
|
||||||
h8300_handle_eightbit_data_attribute, false },
|
h8300_handle_eightbit_data_attribute, false, NULL },
|
||||||
{ "tiny_data", 0, 0, true, false, false,
|
{ "tiny_data", 0, 0, true, false, false,
|
||||||
h8300_handle_tiny_data_attribute, false },
|
h8300_handle_tiny_data_attribute, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44693,69 +44693,71 @@ ix86_expand_round_sse4 (rtx op0, rtx op1)
|
||||||
static const struct attribute_spec ix86_attribute_table[] =
|
static const struct attribute_spec ix86_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
/* Stdcall attribute says callee is responsible for popping arguments
|
/* Stdcall attribute says callee is responsible for popping arguments
|
||||||
if they are not variable. */
|
if they are not variable. */
|
||||||
{ "stdcall", 0, 0, false, true, true, ix86_handle_cconv_attribute,
|
{ "stdcall", 0, 0, false, true, true, ix86_handle_cconv_attribute,
|
||||||
true },
|
true, NULL },
|
||||||
/* Fastcall attribute says callee is responsible for popping arguments
|
/* Fastcall attribute says callee is responsible for popping arguments
|
||||||
if they are not variable. */
|
if they are not variable. */
|
||||||
{ "fastcall", 0, 0, false, true, true, ix86_handle_cconv_attribute,
|
{ "fastcall", 0, 0, false, true, true, ix86_handle_cconv_attribute,
|
||||||
true },
|
true, NULL },
|
||||||
/* Thiscall attribute says callee is responsible for popping arguments
|
/* Thiscall attribute says callee is responsible for popping arguments
|
||||||
if they are not variable. */
|
if they are not variable. */
|
||||||
{ "thiscall", 0, 0, false, true, true, ix86_handle_cconv_attribute,
|
{ "thiscall", 0, 0, false, true, true, ix86_handle_cconv_attribute,
|
||||||
true },
|
true, NULL },
|
||||||
/* Cdecl attribute says the callee is a normal C declaration */
|
/* 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, ix86_handle_cconv_attribute,
|
||||||
true },
|
true, NULL },
|
||||||
/* Regparm attribute specifies how many integer arguments are to be
|
/* Regparm attribute specifies how many integer arguments are to be
|
||||||
passed in registers. */
|
passed in registers. */
|
||||||
{ "regparm", 1, 1, false, true, true, ix86_handle_cconv_attribute,
|
{ "regparm", 1, 1, false, true, true, ix86_handle_cconv_attribute,
|
||||||
true },
|
true, NULL },
|
||||||
/* Sseregparm attribute says we are using x86_64 calling conventions
|
/* Sseregparm attribute says we are using x86_64 calling conventions
|
||||||
for FP arguments. */
|
for FP arguments. */
|
||||||
{ "sseregparm", 0, 0, false, true, true, ix86_handle_cconv_attribute,
|
{ "sseregparm", 0, 0, false, true, true, ix86_handle_cconv_attribute,
|
||||||
true },
|
true, NULL },
|
||||||
/* The transactional memory builtins are implicitly regparm or fastcall
|
/* The transactional memory builtins are implicitly regparm or fastcall
|
||||||
depending on the ABI. Override the generic do-nothing attribute that
|
depending on the ABI. Override the generic do-nothing attribute that
|
||||||
these builtins were declared with. */
|
these builtins were declared with. */
|
||||||
{ "*tm regparm", 0, 0, false, true, true, ix86_handle_tm_regparm_attribute,
|
{ "*tm regparm", 0, 0, false, true, true, ix86_handle_tm_regparm_attribute,
|
||||||
true },
|
true, NULL },
|
||||||
/* force_align_arg_pointer says this function realigns the stack at entry. */
|
/* force_align_arg_pointer says this function realigns the stack at entry. */
|
||||||
{ (const char *)&ix86_force_align_arg_pointer_string, 0, 0,
|
{ (const char *)&ix86_force_align_arg_pointer_string, 0, 0,
|
||||||
false, true, true, ix86_handle_force_align_arg_pointer_attribute, false },
|
false, true, true, ix86_handle_force_align_arg_pointer_attribute, false,
|
||||||
|
NULL },
|
||||||
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
||||||
{ "dllimport", 0, 0, false, false, false, handle_dll_attribute, false },
|
{ "dllimport", 0, 0, false, false, false, handle_dll_attribute, false, NULL },
|
||||||
{ "dllexport", 0, 0, false, false, false, handle_dll_attribute, false },
|
{ "dllexport", 0, 0, false, false, false, handle_dll_attribute, false, NULL },
|
||||||
{ "shared", 0, 0, true, false, false, ix86_handle_shared_attribute,
|
{ "shared", 0, 0, true, false, false, ix86_handle_shared_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
#endif
|
#endif
|
||||||
{ "ms_struct", 0, 0, false, false, false, ix86_handle_struct_attribute,
|
{ "ms_struct", 0, 0, false, false, false, ix86_handle_struct_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "gcc_struct", 0, 0, false, false, false, ix86_handle_struct_attribute,
|
{ "gcc_struct", 0, 0, false, false, false, ix86_handle_struct_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
#ifdef SUBTARGET_ATTRIBUTE_TABLE
|
#ifdef SUBTARGET_ATTRIBUTE_TABLE
|
||||||
SUBTARGET_ATTRIBUTE_TABLE,
|
SUBTARGET_ATTRIBUTE_TABLE,
|
||||||
#endif
|
#endif
|
||||||
/* ms_abi and sysv_abi calling convention function attributes. */
|
/* ms_abi and sysv_abi calling convention function attributes. */
|
||||||
{ "ms_abi", 0, 0, false, true, true, ix86_handle_abi_attribute, true },
|
{ "ms_abi", 0, 0, false, true, true, ix86_handle_abi_attribute, true, NULL },
|
||||||
{ "sysv_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 va_list", 0, 0, false, false, false, NULL, false },
|
NULL },
|
||||||
{ "sysv_abi va_list", 0, 0, false, false, false, NULL, false },
|
{ "ms_abi va_list", 0, 0, false, false, false, NULL, false, NULL },
|
||||||
|
{ "sysv_abi va_list", 0, 0, false, false, false, NULL, false, NULL },
|
||||||
{ "ms_hook_prologue", 0, 0, true, false, false, ix86_handle_fndecl_attribute,
|
{ "ms_hook_prologue", 0, 0, true, false, false, ix86_handle_fndecl_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "callee_pop_aggregate_return", 1, 1, false, true, true,
|
{ "callee_pop_aggregate_return", 1, 1, false, true, true,
|
||||||
ix86_handle_callee_pop_aggregate_return, true },
|
ix86_handle_callee_pop_aggregate_return, true, NULL },
|
||||||
{ "interrupt", 0, 0, false, true, true,
|
{ "interrupt", 0, 0, false, true, true,
|
||||||
ix86_handle_interrupt_attribute, false },
|
ix86_handle_interrupt_attribute, false, NULL },
|
||||||
{ "no_caller_saved_registers", 0, 0, false, true, true,
|
{ "no_caller_saved_registers", 0, 0, false, true, true,
|
||||||
ix86_handle_no_caller_saved_registers_attribute, false },
|
ix86_handle_no_caller_saved_registers_attribute, false, NULL },
|
||||||
{ "naked", 0, 0, true, false, false,
|
{ "naked", 0, 0, true, false, false,
|
||||||
ix86_handle_fndecl_attribute, false },
|
ix86_handle_fndecl_attribute, false, NULL },
|
||||||
|
|
||||||
/* End element. */
|
/* End element. */
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Implement targetm.vectorize.builtin_vectorization_cost. */
|
/* Implement targetm.vectorize.builtin_vectorization_cost. */
|
||||||
|
|
|
||||||
|
|
@ -360,17 +360,17 @@ static bool ia64_expand_vec_perm_const_1 (struct expand_vec_perm_d *d);
|
||||||
static const struct attribute_spec ia64_attribute_table[] =
|
static const struct attribute_spec ia64_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "syscall_linkage", 0, 0, false, true, true, NULL, false },
|
{ "syscall_linkage", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
{ "model", 1, 1, true, false, false, ia64_handle_model_attribute,
|
{ "model", 1, 1, true, false, false, ia64_handle_model_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
#if TARGET_ABI_OPEN_VMS
|
#if TARGET_ABI_OPEN_VMS
|
||||||
{ "common_object", 1, 1, true, false, false,
|
{ "common_object", 1, 1, true, false, false,
|
||||||
ia64_vms_common_object_attribute, false },
|
ia64_vms_common_object_attribute, false, NULL },
|
||||||
#endif
|
#endif
|
||||||
{ "version_id", 1, 1, true, false, false,
|
{ "version_id", 1, 1, true, false, false,
|
||||||
ia64_handle_version_id_attribute, false },
|
ia64_handle_version_id_attribute, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Initialize the GCC target structure. */
|
/* Initialize the GCC target structure. */
|
||||||
|
|
|
||||||
|
|
@ -3000,12 +3000,14 @@ current_function_special_page_vector (rtx x)
|
||||||
#undef TARGET_ATTRIBUTE_TABLE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_ATTRIBUTE_TABLE m32c_attribute_table
|
#define TARGET_ATTRIBUTE_TABLE m32c_attribute_table
|
||||||
static const struct attribute_spec m32c_attribute_table[] = {
|
static const struct attribute_spec m32c_attribute_table[] = {
|
||||||
{"interrupt", 0, 0, false, false, false, interrupt_handler, false},
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
{"bank_switch", 0, 0, false, false, false, interrupt_handler, false},
|
affects_type_identity, exclusions } */
|
||||||
{"fast_interrupt", 0, 0, false, false, false, interrupt_handler, false},
|
{"interrupt", 0, 0, false, false, false, interrupt_handler, false, NULL},
|
||||||
|
{"bank_switch", 0, 0, false, false, false, interrupt_handler, false, NULL},
|
||||||
|
{"fast_interrupt", 0, 0, false, false, false, interrupt_handler, false, NULL},
|
||||||
{"function_vector", 1, 1, true, false, false, function_vector_handler,
|
{"function_vector", 1, 1, true, false, false, function_vector_handler,
|
||||||
false},
|
false, NULL},
|
||||||
{0, 0, 0, 0, 0, 0, 0, false}
|
{0, 0, 0, 0, 0, 0, 0, false, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef TARGET_COMP_TYPE_ATTRIBUTES
|
#undef TARGET_COMP_TYPE_ATTRIBUTES
|
||||||
|
|
|
||||||
|
|
@ -111,11 +111,11 @@ static HOST_WIDE_INT m32r_starting_frame_offset (void);
|
||||||
static const struct attribute_spec m32r_attribute_table[] =
|
static const struct attribute_spec m32r_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "interrupt", 0, 0, true, false, false, NULL, false },
|
{ "interrupt", 0, 0, true, false, false, NULL, false, NULL },
|
||||||
{ "model", 1, 1, true, false, false, m32r_handle_model_attribute,
|
{ "model", 1, 1, true, false, false, m32r_handle_model_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Initialize the GCC target structure. */
|
/* Initialize the GCC target structure. */
|
||||||
|
|
|
||||||
|
|
@ -348,14 +348,14 @@ static bool m68k_modes_tieable_p (machine_mode, machine_mode);
|
||||||
static const struct attribute_spec m68k_attribute_table[] =
|
static const struct attribute_spec m68k_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "interrupt", 0, 0, true, false, false, m68k_handle_fndecl_attribute,
|
{ "interrupt", 0, 0, true, false, false, m68k_handle_fndecl_attribute,
|
||||||
false },
|
false },
|
||||||
{ "interrupt_handler", 0, 0, true, false, false,
|
{ "interrupt_handler", 0, 0, true, false, false,
|
||||||
m68k_handle_fndecl_attribute, false },
|
m68k_handle_fndecl_attribute, false, NULL },
|
||||||
{ "interrupt_thread", 0, 0, true, false, false,
|
{ "interrupt_thread", 0, 0, true, false, false,
|
||||||
m68k_handle_fndecl_attribute, false },
|
m68k_handle_fndecl_attribute, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||||
|
|
|
||||||
|
|
@ -152,12 +152,12 @@ static bool mcore_modes_tieable_p (machine_mode, machine_mode);
|
||||||
static const struct attribute_spec mcore_attribute_table[] =
|
static const struct attribute_spec mcore_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "dllexport", 0, 0, true, false, false, NULL, false },
|
{ "dllexport", 0, 0, true, false, false, NULL, false, NULL },
|
||||||
{ "dllimport", 0, 0, true, false, false, NULL, false },
|
{ "dllimport", 0, 0, true, false, false, NULL, false, NULL },
|
||||||
{ "naked", 0, 0, true, false, false, mcore_handle_naked_attribute,
|
{ "naked", 0, 0, true, false, false, mcore_handle_naked_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Initialize the GCC target structure. */
|
/* Initialize the GCC target structure. */
|
||||||
|
|
|
||||||
|
|
@ -216,17 +216,17 @@ int save_volatiles;
|
||||||
|
|
||||||
const struct attribute_spec microblaze_attribute_table[] = {
|
const struct attribute_spec microblaze_attribute_table[] = {
|
||||||
/* name min_len, max_len, decl_req, type_req, fn_type, req_handler,
|
/* name min_len, max_len, decl_req, type_req, fn_type, req_handler,
|
||||||
affects_type_identity */
|
affects_type_identity, exclusions */
|
||||||
{"interrupt_handler", 0, 0, true, false, false, NULL,
|
{"interrupt_handler", 0, 0, true, false, false, NULL,
|
||||||
false },
|
false, NULL },
|
||||||
{"break_handler", 0, 0, true, false, false, NULL,
|
{"break_handler", 0, 0, true, false, false, NULL,
|
||||||
false },
|
false, NULL },
|
||||||
{"fast_interrupt", 0, 0, true, false, false, NULL,
|
{"fast_interrupt", 0, 0, true, false, false, NULL,
|
||||||
false },
|
false, NULL },
|
||||||
{"save_volatiles" , 0, 0, true, false, false, NULL,
|
{"save_volatiles" , 0, 0, true, false, false, NULL,
|
||||||
false },
|
false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL,
|
{ NULL, 0, 0, false, false, false, NULL,
|
||||||
false }
|
false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int microblaze_interrupt_function_p (tree);
|
static int microblaze_interrupt_function_p (tree);
|
||||||
|
|
|
||||||
|
|
@ -597,27 +597,27 @@ static tree mips_handle_use_shadow_register_set_attr (tree *, tree, tree, int,
|
||||||
static const struct attribute_spec mips_attribute_table[] = {
|
static const struct attribute_spec mips_attribute_table[] = {
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
om_diagnostic } */
|
om_diagnostic } */
|
||||||
{ "long_call", 0, 0, false, true, true, NULL, false },
|
{ "long_call", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
{ "short_call", 0, 0, false, true, true, NULL, false },
|
{ "short_call", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
{ "far", 0, 0, false, true, true, NULL, false },
|
{ "far", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
{ "near", 0, 0, false, true, true, NULL, false },
|
{ "near", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
/* We would really like to treat "mips16" and "nomips16" as type
|
/* We would really like to treat "mips16" and "nomips16" as type
|
||||||
attributes, but GCC doesn't provide the hooks we need to support
|
attributes, but GCC doesn't provide the hooks we need to support
|
||||||
the right conversion rules. As declaration attributes, they affect
|
the right conversion rules. As declaration attributes, they affect
|
||||||
code generation but don't carry other semantics. */
|
code generation but don't carry other semantics. */
|
||||||
{ "mips16", 0, 0, true, false, false, NULL, false },
|
{ "mips16", 0, 0, true, false, false, NULL, false, NULL },
|
||||||
{ "nomips16", 0, 0, true, false, false, NULL, false },
|
{ "nomips16", 0, 0, true, false, false, NULL, false, NULL },
|
||||||
{ "micromips", 0, 0, true, false, false, NULL, false },
|
{ "micromips", 0, 0, true, false, false, NULL, false, NULL },
|
||||||
{ "nomicromips", 0, 0, true, false, false, NULL, false },
|
{ "nomicromips", 0, 0, true, false, false, NULL, false, NULL },
|
||||||
{ "nocompression", 0, 0, true, false, false, NULL, false },
|
{ "nocompression", 0, 0, true, false, false, NULL, false, NULL },
|
||||||
/* Allow functions to be specified as interrupt handlers */
|
/* Allow functions to be specified as interrupt handlers */
|
||||||
{ "interrupt", 0, 1, false, true, true, mips_handle_interrupt_attr,
|
{ "interrupt", 0, 1, false, true, true, mips_handle_interrupt_attr,
|
||||||
false },
|
false, NULL },
|
||||||
{ "use_shadow_register_set", 0, 1, false, true, true,
|
{ "use_shadow_register_set", 0, 1, false, true, true,
|
||||||
mips_handle_use_shadow_register_set_attr, false },
|
mips_handle_use_shadow_register_set_attr, false, NULL },
|
||||||
{ "keep_interrupts_masked", 0, 0, false, true, true, NULL, false },
|
{ "keep_interrupts_masked", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
{ "use_debug_exception_return", 0, 0, false, true, true, NULL, false },
|
{ "use_debug_exception_return", 0, 0, false, true, true, NULL, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A table describing all the processors GCC knows about; see
|
/* A table describing all the processors GCC knows about; see
|
||||||
|
|
|
||||||
|
|
@ -2052,20 +2052,25 @@ const struct attribute_spec msp430_attribute_table[] =
|
||||||
/* Name min_num_args type_req, affects_type_identity
|
/* Name min_num_args type_req, affects_type_identity
|
||||||
max_num_args, fn_type_req
|
max_num_args, fn_type_req
|
||||||
decl_req handler. */
|
decl_req handler. */
|
||||||
{ ATTR_INTR, 0, 1, true, false, false, msp430_attr, false },
|
{ ATTR_INTR, 0, 1, true, false, false, msp430_attr, false, NULL },
|
||||||
{ ATTR_NAKED, 0, 0, true, false, false, msp430_attr, false },
|
{ ATTR_NAKED, 0, 0, true, false, false, msp430_attr, false, NULL },
|
||||||
{ ATTR_REENT, 0, 0, true, false, false, msp430_attr, false },
|
{ ATTR_REENT, 0, 0, true, false, false, msp430_attr, false, NULL },
|
||||||
{ ATTR_CRIT, 0, 0, true, false, false, msp430_attr, false },
|
{ ATTR_CRIT, 0, 0, true, false, false, msp430_attr, false, NULL },
|
||||||
{ ATTR_WAKEUP, 0, 0, true, false, false, msp430_attr, false },
|
{ ATTR_WAKEUP, 0, 0, true, false, false, msp430_attr, false, NULL },
|
||||||
|
|
||||||
{ ATTR_LOWER, 0, 0, true, false, false, msp430_section_attr, false },
|
{ ATTR_LOWER, 0, 0, true, false, false, msp430_section_attr, false,
|
||||||
{ ATTR_UPPER, 0, 0, true, false, false, msp430_section_attr, false },
|
NULL },
|
||||||
{ ATTR_EITHER, 0, 0, true, false, false, msp430_section_attr, false },
|
{ ATTR_UPPER, 0, 0, true, false, false, msp430_section_attr, false,
|
||||||
|
NULL },
|
||||||
|
{ ATTR_EITHER, 0, 0, true, false, false, msp430_section_attr, false,
|
||||||
|
NULL },
|
||||||
|
|
||||||
{ ATTR_NOINIT, 0, 0, true, false, false, msp430_data_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 },
|
||||||
|
{ ATTR_PERSIST, 0, 0, true, false, false, msp430_data_attr, false,
|
||||||
|
NULL },
|
||||||
|
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
||||||
|
|
|
||||||
|
|
@ -86,30 +86,30 @@ static const struct attribute_spec nds32_attribute_table[] =
|
||||||
function_type_required, handler, affects_type_identity } */
|
function_type_required, handler, affects_type_identity } */
|
||||||
|
|
||||||
/* The interrupt vid: [0-63]+ (actual vector number starts from 9 to 72). */
|
/* 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, false, NULL },
|
||||||
/* The exception vid: [1-8]+ (actual vector number starts from 1 to 8). */
|
/* 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, false, NULL },
|
||||||
/* Argument is user's interrupt numbers. The vector number is always 0. */
|
/* 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, false, NULL },
|
||||||
|
|
||||||
/* The attributes describing isr nested type. */
|
/* The attributes describing isr nested type. */
|
||||||
{ "nested", 0, 0, false, false, false, NULL, false },
|
{ "nested", 0, 0, false, false, false, NULL, false, NULL },
|
||||||
{ "not_nested", 0, 0, false, false, false, NULL, false },
|
{ "not_nested", 0, 0, false, false, false, NULL, false, NULL },
|
||||||
{ "nested_ready", 0, 0, false, false, false, NULL, false },
|
{ "nested_ready", 0, 0, false, false, false, NULL, false, NULL },
|
||||||
|
|
||||||
/* The attributes describing isr register save scheme. */
|
/* The attributes describing isr register save scheme. */
|
||||||
{ "save_all", 0, 0, false, false, false, NULL, false },
|
{ "save_all", 0, 0, false, false, false, NULL, false, NULL },
|
||||||
{ "partial_save", 0, 0, false, false, false, NULL, false },
|
{ "partial_save", 0, 0, false, false, false, NULL, false, NULL },
|
||||||
|
|
||||||
/* The attributes used by reset attribute. */
|
/* The attributes used by reset attribute. */
|
||||||
{ "nmi", 1, 1, false, false, false, NULL, false },
|
{ "nmi", 1, 1, false, false, false, NULL, false, NULL },
|
||||||
{ "warm", 1, 1, false, false, false, NULL, false },
|
{ "warm", 1, 1, false, false, false, NULL, false, NULL },
|
||||||
|
|
||||||
/* The attribute telling no prologue/epilogue. */
|
/* The attribute telling no prologue/epilogue. */
|
||||||
{ "naked", 0, 0, false, false, false, NULL, false },
|
{ "naked", 0, 0, false, false, false, NULL, false, NULL },
|
||||||
|
|
||||||
/* The last attribute spec is set to be NULL. */
|
/* The last attribute spec is set to be NULL. */
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4458,10 +4458,12 @@ nvptx_handle_shared_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
||||||
static const struct attribute_spec nvptx_attribute_table[] =
|
static const struct attribute_spec nvptx_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "kernel", 0, 0, true, false, false, nvptx_handle_kernel_attribute, false },
|
{ "kernel", 0, 0, true, false, false, nvptx_handle_kernel_attribute, false,
|
||||||
{ "shared", 0, 0, true, false, false, nvptx_handle_shared_attribute, false },
|
NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ "shared", 0, 0, true, false, false, nvptx_handle_shared_attribute, false,
|
||||||
|
NULL },
|
||||||
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Limit vector alignments to BIGGEST_ALIGNMENT. */
|
/* Limit vector alignments to BIGGEST_ALIGNMENT. */
|
||||||
|
|
|
||||||
|
|
@ -1534,21 +1534,21 @@ static const char alt_reg_names[][8] =
|
||||||
static const struct attribute_spec rs6000_attribute_table[] =
|
static const struct attribute_spec rs6000_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "altivec", 1, 1, false, true, false, rs6000_handle_altivec_attribute,
|
{ "altivec", 1, 1, false, true, false, rs6000_handle_altivec_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute,
|
{ "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute,
|
{ "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute,
|
{ "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "gcc_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute,
|
{ "gcc_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
#ifdef SUBTARGET_ATTRIBUTE_TABLE
|
#ifdef SUBTARGET_ATTRIBUTE_TABLE
|
||||||
SUBTARGET_ATTRIBUTE_TABLE,
|
SUBTARGET_ATTRIBUTE_TABLE,
|
||||||
#endif
|
#endif
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef TARGET_PROFILE_KERNEL
|
#ifndef TARGET_PROFILE_KERNEL
|
||||||
|
|
|
||||||
|
|
@ -860,14 +860,14 @@ const struct attribute_spec rl78_attribute_table[] =
|
||||||
/* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity. */
|
affects_type_identity. */
|
||||||
{ "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
|
{ "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
|
{ "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "naked", 0, 0, true, false, false, rl78_handle_naked_attribute,
|
{ "naked", 0, 0, true, false, false, rl78_handle_naked_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "saddr", 0, 0, true, false, false, rl78_handle_saddr_attribute,
|
{ "saddr", 0, 0, true, false, false, rl78_handle_saddr_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1518,21 +1518,21 @@ static const char alt_reg_names[][8] =
|
||||||
static const struct attribute_spec rs6000_attribute_table[] =
|
static const struct attribute_spec rs6000_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "altivec", 1, 1, false, true, false, rs6000_handle_altivec_attribute,
|
{ "altivec", 1, 1, false, true, false, rs6000_handle_altivec_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute,
|
{ "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute,
|
{ "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute,
|
{ "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "gcc_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute,
|
{ "gcc_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
#ifdef SUBTARGET_ATTRIBUTE_TABLE
|
#ifdef SUBTARGET_ATTRIBUTE_TABLE
|
||||||
SUBTARGET_ATTRIBUTE_TABLE,
|
SUBTARGET_ATTRIBUTE_TABLE,
|
||||||
#endif
|
#endif
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef TARGET_PROFILE_KERNEL
|
#ifndef TARGET_PROFILE_KERNEL
|
||||||
|
|
|
||||||
|
|
@ -2732,16 +2732,16 @@ rx_handle_vector_attribute (tree * node,
|
||||||
const struct attribute_spec rx_attribute_table[] =
|
const struct attribute_spec rx_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity. */
|
affects_type_identity, exclusions. */
|
||||||
{ "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
|
{ "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "interrupt", 0, -1, true, false, false, rx_handle_func_attribute,
|
{ "interrupt", 0, -1, true, false, false, rx_handle_func_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "naked", 0, 0, true, false, false, rx_handle_func_attribute,
|
{ "naked", 0, 0, true, false, false, rx_handle_func_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "vector", 1, -1, true, false, false, rx_handle_vector_attribute,
|
{ "vector", 1, -1, true, false, false, rx_handle_vector_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE. */
|
/* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE. */
|
||||||
|
|
|
||||||
|
|
@ -1178,10 +1178,12 @@ s390_handle_vectorbool_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct attribute_spec s390_attribute_table[] = {
|
static const struct attribute_spec s390_attribute_table[] = {
|
||||||
{ "hotpatch", 2, 2, true, false, false, s390_handle_hotpatch_attribute, false },
|
{ "hotpatch", 2, 2, true, false, false,
|
||||||
{ "s390_vector_bool", 0, 0, false, true, false, s390_handle_vectorbool_attribute, true },
|
s390_handle_hotpatch_attribute, false, NULL },
|
||||||
|
{ "s390_vector_bool", 0, 0, false, true, false,
|
||||||
|
s390_handle_vectorbool_attribute, true, NULL },
|
||||||
/* End element. */
|
/* End element. */
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Return the alignment for LABEL. We default to the -falign-labels
|
/* Return the alignment for LABEL. We default to the -falign-labels
|
||||||
|
|
|
||||||
|
|
@ -330,24 +330,24 @@ static bool sh_can_change_mode_class (machine_mode, machine_mode, reg_class_t);
|
||||||
static const struct attribute_spec sh_attribute_table[] =
|
static const struct attribute_spec sh_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "interrupt_handler", 0, 0, true, false, false,
|
{ "interrupt_handler", 0, 0, true, false, false,
|
||||||
sh_handle_interrupt_handler_attribute, false },
|
sh_handle_interrupt_handler_attribute, false, NULL },
|
||||||
{ "sp_switch", 1, 1, true, false, false,
|
{ "sp_switch", 1, 1, true, false, false,
|
||||||
sh_handle_sp_switch_attribute, false },
|
sh_handle_sp_switch_attribute, false, NULL },
|
||||||
{ "trap_exit", 1, 1, true, false, false,
|
{ "trap_exit", 1, 1, true, false, false,
|
||||||
sh_handle_trap_exit_attribute, false },
|
sh_handle_trap_exit_attribute, false, NULL },
|
||||||
{ "renesas", 0, 0, false, true, false,
|
{ "renesas", 0, 0, false, true, false,
|
||||||
sh_handle_renesas_attribute, false },
|
sh_handle_renesas_attribute, false, NULL },
|
||||||
{ "trapa_handler", 0, 0, true, false, false,
|
{ "trapa_handler", 0, 0, true, false, false,
|
||||||
sh_handle_interrupt_handler_attribute, false },
|
sh_handle_interrupt_handler_attribute, false, NULL },
|
||||||
{ "nosave_low_regs", 0, 0, true, false, false,
|
{ "nosave_low_regs", 0, 0, true, false, false,
|
||||||
sh_handle_interrupt_handler_attribute, false },
|
sh_handle_interrupt_handler_attribute, false, NULL },
|
||||||
{ "resbank", 0, 0, true, false, false,
|
{ "resbank", 0, 0, true, false, false,
|
||||||
sh_handle_resbank_handler_attribute, false },
|
sh_handle_resbank_handler_attribute, false, NULL },
|
||||||
{ "function_vector", 1, 1, true, false, false,
|
{ "function_vector", 1, 1, true, false, false,
|
||||||
sh2a_handle_function_vector_handler_attribute, false },
|
sh2a_handle_function_vector_handler_attribute, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Initialize the GCC target structure. */
|
/* Initialize the GCC target structure. */
|
||||||
|
|
|
||||||
|
|
@ -691,9 +691,9 @@ static HOST_WIDE_INT sparc_constant_alignment (const_tree, HOST_WIDE_INT);
|
||||||
static const struct attribute_spec sparc_attribute_table[] =
|
static const struct attribute_spec sparc_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
do_diagnostic } */
|
do_diagnostic, exclusions } */
|
||||||
SUBTARGET_ATTRIBUTE_TABLE,
|
SUBTARGET_ATTRIBUTE_TABLE,
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7215,12 +7215,12 @@ spu_constant_alignment (const_tree, HOST_WIDE_INT align)
|
||||||
static const struct attribute_spec spu_attribute_table[] =
|
static const struct attribute_spec spu_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "naked", 0, 0, true, false, false, spu_handle_fndecl_attribute,
|
{ "naked", 0, 0, true, false, false, spu_handle_fndecl_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "spu_vector", 0, 0, false, true, false, spu_handle_vector_attribute,
|
{ "spu_vector", 0, 0, false, true, false, spu_handle_vector_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TARGET overrides. */
|
/* TARGET overrides. */
|
||||||
|
|
|
||||||
|
|
@ -2190,14 +2190,14 @@ static tree xstormy16_handle_below100_attribute
|
||||||
static const struct attribute_spec xstormy16_attribute_table[] =
|
static const struct attribute_spec xstormy16_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity. */
|
affects_type_identity, exclusions. */
|
||||||
{ "interrupt", 0, 0, false, true, true,
|
{ "interrupt", 0, 0, false, true, true,
|
||||||
xstormy16_handle_interrupt_attribute , false },
|
xstormy16_handle_interrupt_attribute , false, NULL },
|
||||||
{ "BELOW100", 0, 0, false, false, false,
|
{ "BELOW100", 0, 0, false, false, false,
|
||||||
xstormy16_handle_below100_attribute, false },
|
xstormy16_handle_below100_attribute, false, NULL },
|
||||||
{ "below100", 0, 0, false, false, false,
|
{ "below100", 0, 0, false, false, false,
|
||||||
xstormy16_handle_below100_attribute, false },
|
xstormy16_handle_below100_attribute, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Handle an "interrupt" attribute;
|
/* Handle an "interrupt" attribute;
|
||||||
|
|
|
||||||
|
|
@ -3188,18 +3188,18 @@ v850_adjust_insn_length (rtx_insn *insn, int length)
|
||||||
static const struct attribute_spec v850_attribute_table[] =
|
static const struct attribute_spec v850_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "interrupt_handler", 0, 0, true, false, false,
|
{ "interrupt_handler", 0, 0, true, false, false,
|
||||||
v850_handle_interrupt_attribute, false },
|
v850_handle_interrupt_attribute, false, NULL },
|
||||||
{ "interrupt", 0, 0, true, false, false,
|
{ "interrupt", 0, 0, true, false, false,
|
||||||
v850_handle_interrupt_attribute, false },
|
v850_handle_interrupt_attribute, false, NULL },
|
||||||
{ "sda", 0, 0, true, false, false,
|
{ "sda", 0, 0, true, false, false,
|
||||||
v850_handle_data_area_attribute, false },
|
v850_handle_data_area_attribute, false, NULL },
|
||||||
{ "tda", 0, 0, true, false, false,
|
{ "tda", 0, 0, true, false, false,
|
||||||
v850_handle_data_area_attribute, false },
|
v850_handle_data_area_attribute, false, NULL },
|
||||||
{ "zda", 0, 0, true, false, false,
|
{ "zda", 0, 0, true, false, false,
|
||||||
v850_handle_data_area_attribute, false },
|
v850_handle_data_area_attribute, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -146,9 +146,10 @@ static inline bool current_function_has_lr_slot (void);
|
||||||
static const struct attribute_spec visium_attribute_table[] =
|
static const struct attribute_spec visium_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{"interrupt", 0, 0, true, false, false, visium_handle_interrupt_attr, false},
|
{"interrupt", 0, 0, true, false, false, visium_handle_interrupt_attr, false,
|
||||||
{NULL, 0, 0, false, false, false, NULL, false}
|
NULL},
|
||||||
|
{NULL, 0, 0, false, false, false, NULL, false, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct machine_function *visium_init_machine_status (void);
|
static struct machine_function *visium_init_machine_status (void);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,14 @@
|
||||||
|
2017-12-07 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR c/81544
|
||||||
|
* cp-tree.h (decls_match): Add default argument.
|
||||||
|
* decl.c (decls_match): Avoid calling into the target back end
|
||||||
|
and triggering an error.
|
||||||
|
* decl2.c (cplus_decl_attributes): Look up existing declaration and
|
||||||
|
pass it to decl_attributes.
|
||||||
|
* tree.c (cxx_attribute_table): Initialize new member of struct
|
||||||
|
attribute_spec.
|
||||||
|
|
||||||
2017-12-06 Jakub Jelinek <jakub@redhat.com>
|
2017-12-06 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR c++/80259
|
PR c++/80259
|
||||||
|
|
|
||||||
|
|
@ -6116,7 +6116,7 @@ extern void note_break_stmt (void);
|
||||||
extern bool note_iteration_stmt_body_start (void);
|
extern bool note_iteration_stmt_body_start (void);
|
||||||
extern void note_iteration_stmt_body_end (bool);
|
extern void note_iteration_stmt_body_end (bool);
|
||||||
extern tree make_lambda_name (void);
|
extern tree make_lambda_name (void);
|
||||||
extern int decls_match (tree, tree);
|
extern int decls_match (tree, tree, bool = true);
|
||||||
extern bool maybe_version_functions (tree, tree);
|
extern bool maybe_version_functions (tree, tree);
|
||||||
extern tree duplicate_decls (tree, tree, bool);
|
extern tree duplicate_decls (tree, tree, bool);
|
||||||
extern tree declare_local_label (tree);
|
extern tree declare_local_label (tree);
|
||||||
|
|
|
||||||
|
|
@ -992,7 +992,7 @@ push_local_name (tree decl)
|
||||||
`const int&'. */
|
`const int&'. */
|
||||||
|
|
||||||
int
|
int
|
||||||
decls_match (tree newdecl, tree olddecl)
|
decls_match (tree newdecl, tree olddecl, bool record_versions /* = true */)
|
||||||
{
|
{
|
||||||
int types_match;
|
int types_match;
|
||||||
|
|
||||||
|
|
@ -1087,6 +1087,7 @@ decls_match (tree newdecl, tree olddecl)
|
||||||
if (types_match
|
if (types_match
|
||||||
&& !DECL_EXTERN_C_P (newdecl)
|
&& !DECL_EXTERN_C_P (newdecl)
|
||||||
&& !DECL_EXTERN_C_P (olddecl)
|
&& !DECL_EXTERN_C_P (olddecl)
|
||||||
|
&& record_versions
|
||||||
&& maybe_version_functions (newdecl, olddecl))
|
&& maybe_version_functions (newdecl, olddecl))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1482,7 +1482,31 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags)
|
||||||
attributes, flags);
|
attributes, flags);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
decl_attributes (decl, attributes, flags);
|
{
|
||||||
|
tree last_decl = (DECL_P (*decl) && DECL_NAME (*decl)
|
||||||
|
? lookup_name (DECL_NAME (*decl)) : NULL_TREE);
|
||||||
|
|
||||||
|
if (last_decl && TREE_CODE (last_decl) == OVERLOAD)
|
||||||
|
for (ovl_iterator iter (last_decl, true); ; ++iter)
|
||||||
|
{
|
||||||
|
if (!iter)
|
||||||
|
{
|
||||||
|
last_decl = NULL_TREE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TREE_CODE (*iter) == OVERLOAD)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (decls_match (*decl, *iter, /*record_decls=*/false))
|
||||||
|
{
|
||||||
|
last_decl = *iter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decl_attributes (decl, attributes, flags, last_decl);
|
||||||
|
}
|
||||||
|
|
||||||
if (TREE_CODE (*decl) == TYPE_DECL)
|
if (TREE_CODE (*decl) == TYPE_DECL)
|
||||||
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
|
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
|
||||||
|
|
|
||||||
|
|
@ -4330,24 +4330,24 @@ handle_nodiscard_attribute (tree *node, tree name, tree /*args*/,
|
||||||
const struct attribute_spec cxx_attribute_table[] =
|
const struct attribute_spec cxx_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "init_priority", 1, 1, true, false, false,
|
{ "init_priority", 1, 1, true, false, false,
|
||||||
handle_init_priority_attribute, false },
|
handle_init_priority_attribute, false, NULL },
|
||||||
{ "abi_tag", 1, -1, false, false, false,
|
{ "abi_tag", 1, -1, false, false, false,
|
||||||
handle_abi_tag_attribute, true },
|
handle_abi_tag_attribute, true, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Table of C++ standard attributes. */
|
/* Table of C++ standard attributes. */
|
||||||
const struct attribute_spec std_attribute_table[] =
|
const struct attribute_spec std_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "maybe_unused", 0, 0, false, false, false,
|
{ "maybe_unused", 0, 0, false, false, false,
|
||||||
handle_unused_attribute, false },
|
handle_unused_attribute, false, NULL },
|
||||||
{ "nodiscard", 0, 0, false, false, false,
|
{ "nodiscard", 0, 0, false, false, false,
|
||||||
handle_nodiscard_attribute, false },
|
handle_nodiscard_attribute, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Handle an "init_priority" attribute; arguments as in
|
/* Handle an "init_priority" attribute; arguments as in
|
||||||
|
|
|
||||||
|
|
@ -2493,9 +2493,14 @@ are automatically detected and this attribute is ignored.
|
||||||
@cindex @code{const} function attribute
|
@cindex @code{const} function attribute
|
||||||
@cindex functions that have no side effects
|
@cindex functions that have no side effects
|
||||||
Many functions do not examine any values except their arguments, and
|
Many functions do not examine any values except their arguments, and
|
||||||
have no effects except the return value. Basically this is just slightly
|
have no effects except to return a value. Calls to such functions lend
|
||||||
more strict class than the @code{pure} attribute below, since function is not
|
themselves to optimization such as common subexpression elimination.
|
||||||
allowed to read global memory.
|
The @code{const} attribute imposes greater restrictions on a function's
|
||||||
|
definition than the similar @code{pure} attribute below because it prohibits
|
||||||
|
the function from reading global variables. Consequently, the presence of
|
||||||
|
the attribute on a function declarations allows GCC to emit more efficient
|
||||||
|
code for some calls to the function. Decorating the same function with
|
||||||
|
both the @code{const} and the @code{pure} attribute is diagnnosed.
|
||||||
|
|
||||||
@cindex pointer arguments
|
@cindex pointer arguments
|
||||||
Note that a function that has pointer arguments and examines the data
|
Note that a function that has pointer arguments and examines the data
|
||||||
|
|
@ -3190,7 +3195,7 @@ to prevent recursion.
|
||||||
@cindex functions that have no side effects
|
@cindex functions that have no side effects
|
||||||
Many functions have no effects except the return value and their
|
Many functions have no effects except the return value and their
|
||||||
return value depends only on the parameters and/or global variables.
|
return value depends only on the parameters and/or global variables.
|
||||||
Such a function can be subject
|
Calls to such functions can be subject
|
||||||
to common subexpression elimination and loop optimization just as an
|
to common subexpression elimination and loop optimization just as an
|
||||||
arithmetic operator would be. These functions should be declared
|
arithmetic operator would be. These functions should be declared
|
||||||
with the attribute @code{pure}. For example,
|
with the attribute @code{pure}. For example,
|
||||||
|
|
@ -3208,6 +3213,11 @@ Interesting non-pure functions are functions with infinite loops or those
|
||||||
depending on volatile memory or other system resource, that may change between
|
depending on volatile memory or other system resource, that may change between
|
||||||
two consecutive calls (such as @code{feof} in a multithreading environment).
|
two consecutive calls (such as @code{feof} in a multithreading environment).
|
||||||
|
|
||||||
|
The @code{pure} attribute imposes similar but looser restrictions on
|
||||||
|
a function's defintion than the @code{const} attribute: it allows the
|
||||||
|
function to read global variables. Decorating the same function with
|
||||||
|
both the @code{pure} and the @code{const} attribute is diagnosed.
|
||||||
|
|
||||||
@item returns_nonnull
|
@item returns_nonnull
|
||||||
@cindex @code{returns_nonnull} function attribute
|
@cindex @code{returns_nonnull} function attribute
|
||||||
The @code{returns_nonnull} attribute specifies that the function
|
The @code{returns_nonnull} attribute specifies that the function
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
2017-12-07 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR c/81544
|
||||||
|
* f95-lang.c (gfc_attribute_table): Initialize new member of struct
|
||||||
|
attribute_spec.
|
||||||
|
|
||||||
2017-12-03 Thomas Koenig <tkoenig@gcc.gnu.org>
|
2017-12-03 Thomas Koenig <tkoenig@gcc.gnu.org>
|
||||||
|
|
||||||
PR fortran/36313
|
PR fortran/36313
|
||||||
|
|
|
||||||
|
|
@ -92,12 +92,12 @@ static const struct attribute_spec gfc_attribute_table[] =
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity } */
|
||||||
{ "omp declare target", 0, 0, true, false, false,
|
{ "omp declare target", 0, 0, true, false, false,
|
||||||
gfc_handle_omp_declare_target_attribute, false },
|
gfc_handle_omp_declare_target_attribute, false, NULL },
|
||||||
{ "omp declare target link", 0, 0, true, false, false,
|
{ "omp declare target link", 0, 0, true, false, false,
|
||||||
gfc_handle_omp_declare_target_attribute, false },
|
gfc_handle_omp_declare_target_attribute, false, NULL },
|
||||||
{ "oacc function", 0, -1, true, false, false,
|
{ "oacc function", 0, -1, true, false, false,
|
||||||
gfc_handle_omp_declare_target_attribute, false },
|
gfc_handle_omp_declare_target_attribute, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef LANG_HOOKS_NAME
|
#undef LANG_HOOKS_NAME
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
2017-12-07 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR c/81544
|
||||||
|
* lto-lang.c (lto_attribute_table): Initialize new member of struct
|
||||||
|
attribute_spec.
|
||||||
|
|
||||||
2017-11-30 Jakub Jelinek <jakub@redhat.com>
|
2017-11-30 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
* lto.c (create_subid_section_table): Use ; instead of ;;.
|
* lto.c (create_subid_section_table): Use ; instead of ;;.
|
||||||
|
|
|
||||||
|
|
@ -57,46 +57,82 @@ static tree handle_format_attribute (tree *, tree, tree, int, bool *);
|
||||||
static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
|
static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
|
||||||
static tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
|
static tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
|
||||||
|
|
||||||
|
/* Helper to define attribute exclusions. */
|
||||||
|
#define ATTR_EXCL(name, function, type, variable) \
|
||||||
|
{ name, function, type, variable }
|
||||||
|
|
||||||
|
/* Define attributes that are mutually exclusive with one another. */
|
||||||
|
static const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
|
||||||
|
{
|
||||||
|
ATTR_EXCL ("noreturn", true, true, true),
|
||||||
|
ATTR_EXCL ("alloc_align", true, true, true),
|
||||||
|
ATTR_EXCL ("alloc_size", true, true, true),
|
||||||
|
ATTR_EXCL ("const", true, true, true),
|
||||||
|
ATTR_EXCL ("malloc", true, true, true),
|
||||||
|
ATTR_EXCL ("pure", true, true, true),
|
||||||
|
ATTR_EXCL ("returns_twice", true, true, true),
|
||||||
|
ATTR_EXCL ("warn_unused_result", true, true, true),
|
||||||
|
ATTR_EXCL (NULL, false, false, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
|
||||||
|
{
|
||||||
|
ATTR_EXCL ("noreturn", true, true, true),
|
||||||
|
ATTR_EXCL (NULL, false, false, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
|
||||||
|
{
|
||||||
|
ATTR_EXCL ("const", true, true, true),
|
||||||
|
ATTR_EXCL ("noreturn", true, true, true),
|
||||||
|
ATTR_EXCL ("pure", true, true, true),
|
||||||
|
ATTR_EXCL (NULL, false, false, false)
|
||||||
|
};
|
||||||
|
|
||||||
/* Table of machine-independent attributes supported in GIMPLE. */
|
/* Table of machine-independent attributes supported in GIMPLE. */
|
||||||
const struct attribute_spec lto_attribute_table[] =
|
const struct attribute_spec lto_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
do_diagnostic } */
|
do_diagnostic, exclusions } */
|
||||||
{ "noreturn", 0, 0, true, false, false,
|
{ "noreturn", 0, 0, true, false, false,
|
||||||
handle_noreturn_attribute, false },
|
handle_noreturn_attribute, false,
|
||||||
|
attr_noreturn_exclusions },
|
||||||
{ "leaf", 0, 0, true, false, false,
|
{ "leaf", 0, 0, true, false, false,
|
||||||
handle_leaf_attribute, false },
|
handle_leaf_attribute, false, NULL },
|
||||||
/* The same comments as for noreturn attributes apply to const ones. */
|
/* The same comments as for noreturn attributes apply to const ones. */
|
||||||
{ "const", 0, 0, true, false, false,
|
{ "const", 0, 0, true, false, false,
|
||||||
handle_const_attribute, false },
|
handle_const_attribute, false,
|
||||||
|
attr_const_pure_exclusions },
|
||||||
{ "malloc", 0, 0, true, false, false,
|
{ "malloc", 0, 0, true, false, false,
|
||||||
handle_malloc_attribute, false },
|
handle_malloc_attribute, false, NULL },
|
||||||
{ "pure", 0, 0, true, false, false,
|
{ "pure", 0, 0, true, false, false,
|
||||||
handle_pure_attribute, false },
|
handle_pure_attribute, false,
|
||||||
|
attr_const_pure_exclusions },
|
||||||
{ "no vops", 0, 0, true, false, false,
|
{ "no vops", 0, 0, true, false, false,
|
||||||
handle_novops_attribute, false },
|
handle_novops_attribute, false, NULL },
|
||||||
{ "nonnull", 0, -1, false, true, true,
|
{ "nonnull", 0, -1, false, true, true,
|
||||||
handle_nonnull_attribute, false },
|
handle_nonnull_attribute, false, NULL },
|
||||||
{ "nothrow", 0, 0, true, false, false,
|
{ "nothrow", 0, 0, true, false, false,
|
||||||
handle_nothrow_attribute, false },
|
handle_nothrow_attribute, false, NULL },
|
||||||
{ "patchable_function_entry", 1, 2, true, false, false,
|
{ "patchable_function_entry", 1, 2, true, false, false,
|
||||||
handle_patchable_function_entry_attribute,
|
handle_patchable_function_entry_attribute,
|
||||||
false },
|
false, NULL },
|
||||||
{ "returns_twice", 0, 0, true, false, false,
|
{ "returns_twice", 0, 0, true, false, false,
|
||||||
handle_returns_twice_attribute, false },
|
handle_returns_twice_attribute, false,
|
||||||
|
attr_returns_twice_exclusions },
|
||||||
{ "sentinel", 0, 1, false, true, true,
|
{ "sentinel", 0, 1, false, true, true,
|
||||||
handle_sentinel_attribute, false },
|
handle_sentinel_attribute, false, NULL },
|
||||||
{ "type generic", 0, 0, false, true, true,
|
{ "type generic", 0, 0, false, true, true,
|
||||||
handle_type_generic_attribute, false },
|
handle_type_generic_attribute, false, NULL },
|
||||||
{ "fn spec", 1, 1, false, true, true,
|
{ "fn spec", 1, 1, false, true, true,
|
||||||
handle_fnspec_attribute, false },
|
handle_fnspec_attribute, false, NULL },
|
||||||
{ "transaction_pure", 0, 0, false, true, true,
|
{ "transaction_pure", 0, 0, false, true, true,
|
||||||
handle_transaction_pure_attribute, false },
|
handle_transaction_pure_attribute, false, NULL },
|
||||||
/* For internal use only. The leading '*' both prevents its usage in
|
/* For internal use only. The leading '*' both prevents its usage in
|
||||||
source code and signals that it may be overridden by machine tables. */
|
source code and signals that it may be overridden by machine tables. */
|
||||||
{ "*tm regparm", 0, 0, false, true, true,
|
{ "*tm regparm", 0, 0, false, true, true,
|
||||||
ignore_attribute, false },
|
ignore_attribute, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Give the specifications for the format attributes, used by C and all
|
/* Give the specifications for the format attributes, used by C and all
|
||||||
|
|
@ -105,12 +141,12 @@ const struct attribute_spec lto_attribute_table[] =
|
||||||
const struct attribute_spec lto_format_attribute_table[] =
|
const struct attribute_spec lto_format_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
|
||||||
affects_type_identity } */
|
affects_type_identity, exclusions } */
|
||||||
{ "format", 3, 3, false, true, true,
|
{ "format", 3, 3, false, true, true,
|
||||||
handle_format_attribute, false },
|
handle_format_attribute, false, NULL },
|
||||||
{ "format_arg", 1, 1, false, true, true,
|
{ "format_arg", 1, 1, false, true, true,
|
||||||
handle_format_arg_attribute, false },
|
handle_format_arg_attribute, false, NULL },
|
||||||
{ NULL, 0, 0, false, false, false, NULL, false }
|
{ NULL, 0, 0, false, false, false, NULL, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
enum built_in_attribute
|
enum built_in_attribute
|
||||||
|
|
@ -264,6 +300,10 @@ handle_const_attribute (tree *node, tree ARG_UNUSED (name),
|
||||||
tree ARG_UNUSED (args), int ARG_UNUSED (flags),
|
tree ARG_UNUSED (args), int ARG_UNUSED (flags),
|
||||||
bool * ARG_UNUSED (no_add_attrs))
|
bool * ARG_UNUSED (no_add_attrs))
|
||||||
{
|
{
|
||||||
|
if (TREE_CODE (*node) != FUNCTION_DECL
|
||||||
|
|| !DECL_BUILT_IN (*node))
|
||||||
|
inform (UNKNOWN_LOCATION, "%s:%s: %E: %E", __FILE__, __func__, *node, name);
|
||||||
|
|
||||||
tree type = TREE_TYPE (*node);
|
tree type = TREE_TYPE (*node);
|
||||||
|
|
||||||
/* See FIXME comment on noreturn in c_common_attribute_table. */
|
/* See FIXME comment on noreturn in c_common_attribute_table. */
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "langhooks.h"
|
#include "langhooks.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "stringpool.h"
|
||||||
|
#include "attribs.h"
|
||||||
|
|
||||||
/* This function needed to be split out from selftest.c as it references
|
/* This function needed to be split out from selftest.c as it references
|
||||||
tests from the whole source tree, and so is within
|
tests from the whole source tree, and so is within
|
||||||
|
|
@ -85,6 +87,7 @@ selftest::run_tests ()
|
||||||
spellcheck_c_tests ();
|
spellcheck_c_tests ();
|
||||||
spellcheck_tree_c_tests ();
|
spellcheck_tree_c_tests ();
|
||||||
tree_cfg_c_tests ();
|
tree_cfg_c_tests ();
|
||||||
|
attribute_c_tests ();
|
||||||
|
|
||||||
/* This one relies on most of the above. */
|
/* This one relies on most of the above. */
|
||||||
function_tests_c_tests ();
|
function_tests_c_tests ();
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,7 @@ extern const char *path_to_selftest_files;
|
||||||
|
|
||||||
/* Declarations for specific families of tests (by source file), in
|
/* Declarations for specific families of tests (by source file), in
|
||||||
alphabetical order. */
|
alphabetical order. */
|
||||||
|
extern void attribute_c_tests ();
|
||||||
extern void bitmap_c_tests ();
|
extern void bitmap_c_tests ();
|
||||||
extern void sbitmap_c_tests ();
|
extern void sbitmap_c_tests ();
|
||||||
extern void diagnostic_c_tests ();
|
extern void diagnostic_c_tests ();
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,16 @@
|
||||||
|
2017-12-07 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR c/81544
|
||||||
|
* c-c++-common/Wattributes-2.c: New test.
|
||||||
|
* c-c++-common/Wattributes.c: New test.
|
||||||
|
* c-c++-common/attributes-3.c: Adjust.
|
||||||
|
* gcc.dg/Wattributes-6.c: New test.
|
||||||
|
* gcc.dg/Wattributes-7.c: New test.
|
||||||
|
* gcc.dg/attr-noinline.c
|
||||||
|
* gcc.dg/pr44964.c: Same.
|
||||||
|
* gcc.dg/torture/pr42363.c: Same.
|
||||||
|
* gcc.dg/tree-ssa/ssa-ccp-2.c: Same.
|
||||||
|
|
||||||
2017-12-07 Tamar Christina <tamar.christina@arm.com>
|
2017-12-07 Tamar Christina <tamar.christina@arm.com>
|
||||||
|
|
||||||
PR target/82641
|
PR target/82641
|
||||||
|
|
|
||||||
|
|
@ -12,16 +12,16 @@ extern __attribute__((noinline)) int fn1 (void); /* { dg-message "previous decla
|
||||||
extern inline int fn1 (void); /* { dg-warning "inline declaration of" } */
|
extern inline int fn1 (void); /* { dg-warning "inline declaration of" } */
|
||||||
|
|
||||||
extern inline int fn2 (void); /* { dg-message "previous declaration" } */
|
extern inline int fn2 (void); /* { dg-message "previous declaration" } */
|
||||||
extern __attribute__((noinline)) int fn2 (void); /* { dg-warning "attribute noinline follows inline declaration" } */
|
extern __attribute__((noinline)) int fn2 (void); /* { dg-warning "attribute .noinline. follows inline declaration" } */
|
||||||
|
|
||||||
extern __attribute__((always_inline)) int fn3 (void); /* { dg-message "previous declaration" } */
|
extern __attribute__((always_inline)) int fn3 (void); /* { dg-message "previous declaration" } */
|
||||||
extern __attribute__((noinline)) int fn3 (void); /* { dg-warning "attribute .noinline. follows declaration with attribute .always_inline." } */
|
extern __attribute__((noinline)) int fn3 (void); /* { dg-warning "attribute .noinline." } */
|
||||||
|
|
||||||
extern __attribute__((noinline)) int fn4 (void); /* { dg-message "previous declaration" } */
|
extern __attribute__((noinline)) int fn4 (void); /* { dg-message "previous declaration" } */
|
||||||
extern __attribute__((always_inline)) int fn4 (void); /* { dg-warning "attribute .always_inline. follows declaration with attribute .noinline." } */
|
extern __attribute__((always_inline)) int fn4 (void); /* { dg-warning "attribute .always_inline." } */
|
||||||
|
|
||||||
extern __attribute__((hot)) int fn5 (void); /* { dg-message "previous declaration" } */
|
extern __attribute__((hot)) int fn5 (void); /* { dg-message "previous declaration" } */
|
||||||
extern __attribute__((cold)) int fn5 (void); /* { dg-warning "attribute .cold. follows declaration with attribute .hot." } */
|
extern __attribute__((cold)) int fn5 (void); /* { dg-warning "attribute .cold." } */
|
||||||
|
|
||||||
extern __attribute__((cold)) int fn6 (void); /* { dg-message "previous declaration" } */
|
extern __attribute__((cold)) int fn6 (void); /* { dg-message "previous declaration" } */
|
||||||
extern __attribute__((hot)) int fn6 (void); /* { dg-warning "attribute .hot. follows declaration with attribute .cold." } */
|
extern __attribute__((hot)) int fn6 (void); /* { dg-warning "attribute .hot." } */
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ static void function_declaration_both_after(void) {t();}
|
||||||
|
|
||||||
static void function_declaration_noinline_before(void) __attribute__((__noinline__)); /* { dg-message "note: previous declaration" } */
|
static void function_declaration_noinline_before(void) __attribute__((__noinline__)); /* { dg-message "note: previous declaration" } */
|
||||||
|
|
||||||
static inline void function_declaration_noinline_before(void) {t();} /* { dg-warning "follows declaration with attribute noinline" } */
|
static inline void function_declaration_noinline_before(void) {t();} /* { dg-warning "follows declaration with attribute .noinline." } */
|
||||||
|
|
||||||
static inline void function_declaration_noinline_after(void) {t();} /* { dg-message "note: previous definition" } */
|
static inline void function_declaration_noinline_after(void) {t();} /* { dg-message "note: previous definition" } */
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ static void function_declaration_inline_noinline_after(void) __attribute__((__no
|
||||||
|
|
||||||
static void function_declaration_noinline_inline_before(void) __attribute__((__noinline__)); /* { dg-message "note: previous declaration" } */
|
static void function_declaration_noinline_inline_before(void) __attribute__((__noinline__)); /* { dg-message "note: previous declaration" } */
|
||||||
|
|
||||||
static inline void function_declaration_noinline_inline_before(void); /* { dg-warning "follows declaration with attribute noinline" } */
|
static inline void function_declaration_noinline_inline_before(void); /* { dg-warning "follows declaration with attribute .noinline." } */
|
||||||
|
|
||||||
static void function_declaration_noinline_inline_before(void) {t();}
|
static void function_declaration_noinline_inline_before(void) {t();}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
/* { dg-options "-fkeep-inline-functions -O" } */
|
/* { dg-options "-fkeep-inline-functions -O" } */
|
||||||
|
|
||||||
static inline __attribute__ ((const))
|
static inline __attribute__ ((const))
|
||||||
void baz (int i)
|
int baz (int i)
|
||||||
{
|
{
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __attribute__ ((always_inline))
|
static __attribute__ ((always_inline))
|
||||||
|
|
|
||||||
|
|
@ -46,16 +46,18 @@ int bizr (void)
|
||||||
return i + 1;
|
return i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This might be regarded as pure and folded, rather than inlined.
|
/* This might be regarded as pure and folded, rather than inlined,
|
||||||
It's pure evil. */
|
but because it's pure evil it's diagnosed and the noreturn attribute
|
||||||
|
is dropped. The const attribute is dropped as well because it's
|
||||||
|
mutually exclusive with pure. */
|
||||||
static int __attribute__ ((pure, const, noreturn))
|
static int __attribute__ ((pure, const, noreturn))
|
||||||
barf (void)
|
barf (void) {
|
||||||
{
|
/* { dg-warning "ignoring attribute .const." "const" { target *-*-* } .-1 } */
|
||||||
|
/* { dg-warning "ignoring attribute .noreturn." "noreturn" { target *-*-* } .-2 } */
|
||||||
} /* { dg-warning "does return" } */
|
} /* { dg-warning "does return" } */
|
||||||
|
|
||||||
static int __attribute__ ((pure, const))
|
static int __attribute__ ((pure, const))
|
||||||
bark (void)
|
bark (void) { /* { dg-warning "ignoring attribute .const." } */
|
||||||
{
|
|
||||||
barf ();
|
barf ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,17 +113,18 @@ int test9 (int *intarr)
|
||||||
|
|
||||||
int test99 (int *intarr)
|
int test99 (int *intarr)
|
||||||
{
|
{
|
||||||
extern int foo9 (int) __attribute__ ((pure));
|
extern int foo99 (int) __attribute__ ((pure));
|
||||||
int h, v;
|
int h, v;
|
||||||
g9 = 9;
|
g9 = 9;
|
||||||
h = foo9 (g9);
|
h = foo99 (g9);
|
||||||
v = g9;
|
v = g9;
|
||||||
if (v != 9)
|
if (v != 9)
|
||||||
link_error ();
|
link_error ();
|
||||||
return g9;
|
return g9;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int foo99 (int);
|
/* foo9 is const because of its declaration in test9. */
|
||||||
|
extern int foo9 (int);
|
||||||
|
|
||||||
int test999 (int *arr)
|
int test999 (int *arr)
|
||||||
{
|
{
|
||||||
|
|
@ -134,10 +135,12 @@ int test999 (int *arr)
|
||||||
v1 = g9;
|
v1 = g9;
|
||||||
if (v1 != 9)
|
if (v1 != 9)
|
||||||
link_error ();
|
link_error ();
|
||||||
l = foo99 (l);
|
l = foo9 (l);
|
||||||
return v1 + l;
|
return v1 + l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* foo99 is pure because of its declaration in test99. */
|
||||||
|
extern int foo9 (int);
|
||||||
|
|
||||||
int test9999 (void)
|
int test9999 (void)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1938,6 +1938,20 @@ struct attribute_spec {
|
||||||
int flags, bool *no_add_attrs);
|
int flags, bool *no_add_attrs);
|
||||||
/* Specifies if attribute affects type's identity. */
|
/* Specifies if attribute affects type's identity. */
|
||||||
bool affects_type_identity;
|
bool affects_type_identity;
|
||||||
|
|
||||||
|
/* Specifies the name of an attribute that's mutually exclusive with
|
||||||
|
this one, and whether the relationship applies to the function,
|
||||||
|
variable, or type form of the attribute. */
|
||||||
|
struct exclusions {
|
||||||
|
const char *name;
|
||||||
|
bool function;
|
||||||
|
bool variable;
|
||||||
|
bool type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* An array of attribute exclusions describing names of other attributes
|
||||||
|
that this attribute is mutually exclusive with. */
|
||||||
|
const exclusions *exclude;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* These functions allow a front-end to perform a manual layout of a
|
/* These functions allow a front-end to perform a manual layout of a
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
2017-12-07 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR c/81544
|
||||||
|
* include/ext/mt_allocator.h (_M_destroy_thread_key): Remove
|
||||||
|
attribute const.
|
||||||
|
|
||||||
2017-12-05 Jason Merrill <jason@redhat.com>
|
2017-12-05 Jason Merrill <jason@redhat.com>
|
||||||
Jonathan Wakely <jwakely@redhat.com>
|
Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX GLIBCXX_ABI Deprecated
|
// XXX GLIBCXX_ABI Deprecated
|
||||||
_GLIBCXX_CONST void
|
void
|
||||||
_M_destroy_thread_key(void*) throw ();
|
_M_destroy_thread_key(void*) throw ();
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue