aboutsummaryrefslogtreecommitdiff
path: root/gcc/attribs.c
diff options
context:
space:
mode:
authorNeil Booth <neil@daikokuya.demon.co.uk>2002-04-24 20:41:04 +0000
committerNeil Booth <neil@gcc.gnu.org>2002-04-24 20:41:04 +0000
commit349ae713cb98e06d7be10c6e4913a28f67278528 (patch)
treea282065cb3961f75aca64ff2fdc96c61cce9c686 /gcc/attribs.c
parent3f2019c6efd7324664e5e2d184c7233da3f839a2 (diff)
downloadgcc-349ae713cb98e06d7be10c6e4913a28f67278528.zip
gcc-349ae713cb98e06d7be10c6e4913a28f67278528.tar.gz
gcc-349ae713cb98e06d7be10c6e4913a28f67278528.tar.bz2
attribs.c (c_common_attribute_table): Move table and handlers to c-common.c.
* attribs.c (c_common_attribute_table): Move table and handlers to c-common.c. (format_attribute_table, lang_attribute_table, lang_attribute_common): Remove. (init_attributes): Replace NULL pointers with pointers to the empty table. (handle_packed_attribute, handle_nocommon_attribute, handle_common_attribute, handle_noreturn_attribute, handle_noinline_attribute, handle_always_inline_attribute, handle_used_attribute, handle_unused_attribute, handle_const_attribute, handle_transparent_union_attribute, handle_constructor_attribute, handle_destructor_attribute, handle_mode_attribute, handle_section_attribute, handle_aligned_attribute, handle_weak_attribute, handle_alias_attribute, handle_visibility_attribute, handle_no_instrument_function_attribute, handle_malloc_attribute, handle_no_limit_stack_attribute, handle_pure_attribute, handle_deprecated_attribute, handle_vector_size_attribute, vector_size_helper): Move to c-common.c. * c-common.c (c_common_attribute_table, handle_packed_attribute, handle_nocommon_attribute, handle_common_attribute, handle_noreturn_attribute, handle_noinline_attribute, handle_always_inline_attribute, handle_used_attribute, handle_unused_attribute, handle_const_attribute, handle_transparent_union_attribute, handle_constructor_attribute, handle_destructor_attribute, handle_mode_attribute, handle_section_attribute, handle_aligned_attribute, handle_weak_attribute, handle_alias_attribute, handle_visibility_attribute, handle_no_instrument_function_attribute, handle_malloc_attribute, handle_no_limit_stack_attribute, handle_pure_attribute, handle_deprecated_attribute, handle_vector_size_attribute, vector_size_helper): Move from attribs.c. * c-common.h (c_common_attribute_table, c_common_format_attribute_table): New. * c-lang.c (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Redefine. * langhooks-def.h (LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, LANG_HOOKS_ATTRIBUTE_TABLE): New. (LANG_HOOKS_INITIALIZER): Update. * langhooks.h (struct lang_hooks): 3 new attribute hooks. * target-def.h (TARGET_ATTRIBUTE_TABLE): Default to NULL. * target.h: Update comment. * tree.c (default_target_attribute_table): Remove. * tree.h (default_target_attribute_table, format_attribute_table, lang_attribute_table, lang_attribute_common): Remove. ada: * misc.c (gnat_init): Don't set lang_attribute_common. cp: * cp-lang.c (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, LANG_HOOKS_ATTRIBUTE_TABLE): Redefine. * cp-tree.h (cp_attribute_table): Rename. * decl.c (lang_attribute_table): Remove declaration. (cxx_init_decl_processing): Don't set it. * tree.c (cp_attribute_table): Rename. objc: * objc-lang.c (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Redefine. From-SVN: r52730
Diffstat (limited to 'gcc/attribs.c')
-rw-r--r--gcc/attribs.c1162
1 files changed, 9 insertions, 1153 deletions
diff --git a/gcc/attribs.c b/gcc/attribs.c
index bdd6bd0..e48db85 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -36,157 +36,36 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
static void init_attributes PARAMS ((void));
-/* Table of the tables of attributes (common, format, language, machine)
+/* Table of the tables of attributes (common, language, format, machine)
searched. */
static const struct attribute_spec *attribute_tables[4];
static bool attributes_initialized = false;
-static tree handle_packed_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_nocommon_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_common_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_noreturn_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_noinline_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_always_inline_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_used_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_unused_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_const_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_transparent_union_attribute PARAMS ((tree *, tree, tree,
- int, bool *));
-static tree handle_constructor_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_destructor_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_mode_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_section_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_aligned_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_weak_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_alias_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_visibility_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_no_instrument_function_attribute PARAMS ((tree *, tree,
- tree, int,
- bool *));
-static tree handle_malloc_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_no_limit_stack_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_pure_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_deprecated_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree vector_size_helper PARAMS ((tree, tree));
-
-/* Table of machine-independent attributes common to all C-like languages. */
-static const struct attribute_spec c_common_attribute_table[] =
-{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- { "packed", 0, 0, false, false, false,
- handle_packed_attribute },
- { "nocommon", 0, 0, true, false, false,
- handle_nocommon_attribute },
- { "common", 0, 0, true, false, false,
- handle_common_attribute },
- /* FIXME: logically, noreturn attributes should be listed as
- "false, true, true" and apply to function types. But implementing this
- would require all the places in the compiler that use TREE_THIS_VOLATILE
- on a decl to identify non-returning functions to be located and fixed
- to check the function type instead. */
- { "noreturn", 0, 0, true, false, false,
- handle_noreturn_attribute },
- { "volatile", 0, 0, true, false, false,
- handle_noreturn_attribute },
- { "noinline", 0, 0, true, false, false,
- handle_noinline_attribute },
- { "always_inline", 0, 0, true, false, false,
- handle_always_inline_attribute },
- { "used", 0, 0, true, false, false,
- handle_used_attribute },
- { "unused", 0, 0, false, false, false,
- handle_unused_attribute },
- /* The same comments as for noreturn attributes apply to const ones. */
- { "const", 0, 0, true, false, false,
- handle_const_attribute },
- { "transparent_union", 0, 0, false, false, false,
- handle_transparent_union_attribute },
- { "constructor", 0, 0, true, false, false,
- handle_constructor_attribute },
- { "destructor", 0, 0, true, false, false,
- handle_destructor_attribute },
- { "mode", 1, 1, false, true, false,
- handle_mode_attribute },
- { "section", 1, 1, true, false, false,
- handle_section_attribute },
- { "aligned", 0, 1, false, false, false,
- handle_aligned_attribute },
- { "weak", 0, 0, true, false, false,
- handle_weak_attribute },
- { "alias", 1, 1, true, false, false,
- handle_alias_attribute },
- { "no_instrument_function", 0, 0, true, false, false,
- handle_no_instrument_function_attribute },
- { "malloc", 0, 0, true, false, false,
- handle_malloc_attribute },
- { "no_stack_limit", 0, 0, true, false, false,
- handle_no_limit_stack_attribute },
- { "pure", 0, 0, true, false, false,
- handle_pure_attribute },
- { "deprecated", 0, 0, false, false, false,
- handle_deprecated_attribute },
- { "vector_size", 1, 1, false, true, false,
- handle_vector_size_attribute },
- { "visibility", 1, 1, true, false, false,
- handle_visibility_attribute },
- { NULL, 0, 0, false, false, false, NULL }
-};
-
/* Default empty table of attributes. */
static const struct attribute_spec empty_attribute_table[] =
{
{ NULL, 0, 0, false, false, false, NULL }
};
-/* Table of machine-independent attributes for checking formats, if used. */
-const struct attribute_spec *format_attribute_table = empty_attribute_table;
-
-/* Table of machine-independent attributes for a particular language. */
-const struct attribute_spec *lang_attribute_table = empty_attribute_table;
-
-/* Flag saying whether common language attributes are to be supported. */
-int lang_attribute_common = 1;
-
/* Initialize attribute tables, and make some sanity checks
if --enable-checking. */
static void
init_attributes ()
{
-#ifdef ENABLE_CHECKING
size_t i;
-#endif
- attribute_tables[0]
- = lang_attribute_common ? c_common_attribute_table : empty_attribute_table;
- attribute_tables[1] = lang_attribute_table;
- attribute_tables[2] = format_attribute_table;
+ attribute_tables[0] = lang_hooks.common_attribute_table;
+ attribute_tables[1] = lang_hooks.attribute_table;
+ attribute_tables[2] = lang_hooks.format_attribute_table;
attribute_tables[3] = targetm.attribute_table;
+ /* Translate NULL pointers to pointers to the empty table. */
+ for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
+ if (attribute_tables[i] == NULL)
+ attribute_tables[i] = empty_attribute_table;
+
#ifdef ENABLE_CHECKING
/* Make some sanity checks on the attribute tables. */
for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
@@ -426,1029 +305,6 @@ decl_attributes (node, attributes, flags)
return returned_attrs;
}
-/* Handle a "packed" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_packed_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags;
- bool *no_add_attrs;
-{
- tree *type = NULL;
- if (DECL_P (*node))
- {
- if (TREE_CODE (*node) == TYPE_DECL)
- type = &TREE_TYPE (*node);
- }
- else
- type = node;
-
- if (type)
- {
- if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *type = build_type_copy (*type);
- TYPE_PACKED (*type) = 1;
- }
- else if (TREE_CODE (*node) == FIELD_DECL)
- DECL_PACKED (*node) = 1;
- /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
- used for DECL_REGISTER. It wouldn't mean anything anyway. */
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "nocommon" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_nocommon_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == VAR_DECL)
- DECL_COMMON (*node) = 0;
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "common" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_common_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == VAR_DECL)
- DECL_COMMON (*node) = 1;
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "noreturn" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_noreturn_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree type = TREE_TYPE (*node);
-
- /* See FIXME comment in c_common_attribute_table. */
- if (TREE_CODE (*node) == FUNCTION_DECL)
- TREE_THIS_VOLATILE (*node) = 1;
- else if (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
- TREE_TYPE (*node)
- = build_pointer_type
- (build_type_variant (TREE_TYPE (type),
- TREE_READONLY (TREE_TYPE (type)), 1));
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "noinline" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_noinline_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- DECL_UNINLINABLE (*node) = 1;
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "always_inline" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_always_inline_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- {
- /* Do nothing else, just set the attribute. We'll get at
- it later with lookup_attribute. */
- }
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "used" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_used_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (*node))
- = TREE_USED (*node) = 1;
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "unused" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_unused_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags;
- bool *no_add_attrs;
-{
- if (DECL_P (*node))
- {
- tree decl = *node;
-
- if (TREE_CODE (decl) == PARM_DECL
- || TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == LABEL_DECL
- || TREE_CODE (decl) == TYPE_DECL)
- TREE_USED (decl) = 1;
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- }
- else
- {
- if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *node = build_type_copy (*node);
- TREE_USED (*node) = 1;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "const" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_const_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree type = TREE_TYPE (*node);
-
- /* See FIXME comment on noreturn in c_common_attribute_table. */
- if (TREE_CODE (*node) == FUNCTION_DECL)
- TREE_READONLY (*node) = 1;
- else if (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
- TREE_TYPE (*node)
- = build_pointer_type
- (build_type_variant (TREE_TYPE (type), 1,
- TREE_THIS_VOLATILE (TREE_TYPE (type))));
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "transparent_union" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_transparent_union_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags;
- bool *no_add_attrs;
-{
- tree decl = NULL_TREE;
- tree *type = NULL;
- int is_type = 0;
-
- if (DECL_P (*node))
- {
- decl = *node;
- type = &TREE_TYPE (decl);
- is_type = TREE_CODE (*node) == TYPE_DECL;
- }
- else if (TYPE_P (*node))
- type = node, is_type = 1;
-
- if (is_type
- && TREE_CODE (*type) == UNION_TYPE
- && (decl == 0
- || (TYPE_FIELDS (*type) != 0
- && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))))
- {
- if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *type = build_type_copy (*type);
- TYPE_TRANSPARENT_UNION (*type) = 1;
- }
- else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
- && TREE_CODE (*type) == UNION_TYPE
- && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))
- DECL_TRANSPARENT_UNION (decl) = 1;
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "constructor" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_constructor_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree decl = *node;
- tree type = TREE_TYPE (decl);
-
- if (TREE_CODE (decl) == FUNCTION_DECL
- && TREE_CODE (type) == FUNCTION_TYPE
- && decl_function_context (decl) == 0)
- {
- DECL_STATIC_CONSTRUCTOR (decl) = 1;
- TREE_USED (decl) = 1;
- }
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "destructor" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_destructor_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree decl = *node;
- tree type = TREE_TYPE (decl);
-
- if (TREE_CODE (decl) == FUNCTION_DECL
- && TREE_CODE (type) == FUNCTION_TYPE
- && decl_function_context (decl) == 0)
- {
- DECL_STATIC_DESTRUCTOR (decl) = 1;
- TREE_USED (decl) = 1;
- }
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "mode" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_mode_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree type = *node;
-
- *no_add_attrs = true;
-
- if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- else
- {
- int j;
- const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
- int len = strlen (p);
- enum machine_mode mode = VOIDmode;
- tree typefm;
-
- if (len > 4 && p[0] == '_' && p[1] == '_'
- && p[len - 1] == '_' && p[len - 2] == '_')
- {
- char *newp = (char *) alloca (len - 1);
-
- strcpy (newp, &p[2]);
- newp[len - 4] = '\0';
- p = newp;
- }
-
- /* Change this type to have a type with the specified mode.
- First check for the special modes. */
- if (! strcmp (p, "byte"))
- mode = byte_mode;
- else if (!strcmp (p, "word"))
- mode = word_mode;
- else if (! strcmp (p, "pointer"))
- mode = ptr_mode;
- else
- for (j = 0; j < NUM_MACHINE_MODES; j++)
- if (!strcmp (p, GET_MODE_NAME (j)))
- mode = (enum machine_mode) j;
-
- if (mode == VOIDmode)
- error ("unknown machine mode `%s'", p);
- else if (0 == (typefm = (*lang_hooks.types.type_for_mode)
- (mode, TREE_UNSIGNED (type))))
- error ("no data type for mode `%s'", p);
- else
- *node = typefm;
- /* No need to layout the type here. The caller should do this. */
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "section" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_section_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name ATTRIBUTE_UNUSED;
- tree args;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree decl = *node;
-
- if (targetm.have_named_sections)
- {
- if ((TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL)
- && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
- {
- if (TREE_CODE (decl) == VAR_DECL
- && current_function_decl != NULL_TREE
- && ! TREE_STATIC (decl))
- {
- error_with_decl (decl,
- "section attribute cannot be specified for local variables");
- *no_add_attrs = true;
- }
-
- /* The decl may have already been given a section attribute
- from a previous declaration. Ensure they match. */
- else if (DECL_SECTION_NAME (decl) != NULL_TREE
- && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
- TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
- {
- error_with_decl (*node,
- "section of `%s' conflicts with previous declaration");
- *no_add_attrs = true;
- }
- else
- DECL_SECTION_NAME (decl) = TREE_VALUE (args);
- }
- else
- {
- error_with_decl (*node,
- "section attribute not allowed for `%s'");
- *no_add_attrs = true;
- }
- }
- else
- {
- error_with_decl (*node,
- "section attributes are not supported for this target");
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "aligned" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_aligned_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name ATTRIBUTE_UNUSED;
- tree args;
- int flags;
- bool *no_add_attrs;
-{
- tree decl = NULL_TREE;
- tree *type = NULL;
- int is_type = 0;
- tree align_expr = (args ? TREE_VALUE (args)
- : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
- int i;
-
- if (DECL_P (*node))
- {
- decl = *node;
- type = &TREE_TYPE (decl);
- is_type = TREE_CODE (*node) == TYPE_DECL;
- }
- else if (TYPE_P (*node))
- type = node, is_type = 1;
-
- /* Strip any NOPs of any kind. */
- while (TREE_CODE (align_expr) == NOP_EXPR
- || TREE_CODE (align_expr) == CONVERT_EXPR
- || TREE_CODE (align_expr) == NON_LVALUE_EXPR)
- align_expr = TREE_OPERAND (align_expr, 0);
-
- if (TREE_CODE (align_expr) != INTEGER_CST)
- {
- error ("requested alignment is not a constant");
- *no_add_attrs = true;
- }
- else if ((i = tree_log2 (align_expr)) == -1)
- {
- error ("requested alignment is not a power of 2");
- *no_add_attrs = true;
- }
- else if (i > HOST_BITS_PER_INT - 2)
- {
- error ("requested alignment is too large");
- *no_add_attrs = true;
- }
- else if (is_type)
- {
- /* If we have a TYPE_DECL, then copy the type, so that we
- don't accidentally modify a builtin type. See pushdecl. */
- if (decl && TREE_TYPE (decl) != error_mark_node
- && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
- {
- tree tt = TREE_TYPE (decl);
- *type = build_type_copy (*type);
- DECL_ORIGINAL_TYPE (decl) = tt;
- TYPE_NAME (*type) = decl;
- TREE_USED (*type) = TREE_USED (decl);
- TREE_TYPE (decl) = *type;
- }
- else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *type = build_type_copy (*type);
-
- TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
- TYPE_USER_ALIGN (*type) = 1;
- }
- else if (TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FIELD_DECL)
- {
- error_with_decl (decl,
- "alignment may not be specified for `%s'");
- *no_add_attrs = true;
- }
- else
- {
- DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
- DECL_USER_ALIGN (decl) = 1;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "weak" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_weak_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name ATTRIBUTE_UNUSED;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs ATTRIBUTE_UNUSED;
-{
- declare_weak (*node);
-
- return NULL_TREE;
-}
-
-/* Handle an "alias" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_alias_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree decl = *node;
-
- if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
- || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
- {
- error_with_decl (decl,
- "`%s' defined both normally and as an alias");
- *no_add_attrs = true;
- }
- else if (decl_function_context (decl) == 0)
- {
- tree id;
-
- id = TREE_VALUE (args);
- if (TREE_CODE (id) != STRING_CST)
- {
- error ("alias arg not a string");
- *no_add_attrs = true;
- return NULL_TREE;
- }
- id = get_identifier (TREE_STRING_POINTER (id));
- /* This counts as a use of the object pointed to. */
- TREE_USED (id) = 1;
-
- if (TREE_CODE (decl) == FUNCTION_DECL)
- DECL_INITIAL (decl) = error_mark_node;
- else
- DECL_EXTERNAL (decl) = 0;
- }
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle an "visibility" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_visibility_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree decl = *node;
-
- if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- else
- {
- tree id;
-
- id = TREE_VALUE (args);
- if (TREE_CODE (id) != STRING_CST)
- {
- error ("visibility arg not a string");
- *no_add_attrs = true;
- return NULL_TREE;
- }
- if (strcmp (TREE_STRING_POINTER (id), "hidden")
- && strcmp (TREE_STRING_POINTER (id), "protected")
- && strcmp (TREE_STRING_POINTER (id), "internal"))
- {
- error ("visibility arg must be one of \"hidden\", \"protected\" or \"internal\"");
- *no_add_attrs = true;
- return NULL_TREE;
- }
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "no_instrument_function" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_no_instrument_function_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree decl = *node;
-
- if (TREE_CODE (decl) != FUNCTION_DECL)
- {
- error_with_decl (decl,
- "`%s' attribute applies only to functions",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- else if (DECL_INITIAL (decl))
- {
- error_with_decl (decl,
- "can't set `%s' attribute after definition",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- else
- DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
-
- return NULL_TREE;
-}
-
-/* Handle a "malloc" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_malloc_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- DECL_IS_MALLOC (*node) = 1;
- /* ??? TODO: Support types. */
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "no_limit_stack" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_no_limit_stack_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree decl = *node;
-
- if (TREE_CODE (decl) != FUNCTION_DECL)
- {
- error_with_decl (decl,
- "`%s' attribute applies only to functions",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- else if (DECL_INITIAL (decl))
- {
- error_with_decl (decl,
- "can't set `%s' attribute after definition",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- else
- DECL_NO_LIMIT_STACK (decl) = 1;
-
- return NULL_TREE;
-}
-
-/* Handle a "pure" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_pure_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- DECL_IS_PURE (*node) = 1;
- /* ??? TODO: Support types. */
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "deprecated" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_deprecated_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags;
- bool *no_add_attrs;
-{
- tree type = NULL_TREE;
- int warn = 0;
- const char *what = NULL;
-
- if (DECL_P (*node))
- {
- tree decl = *node;
- type = TREE_TYPE (decl);
-
- if (TREE_CODE (decl) == TYPE_DECL
- || TREE_CODE (decl) == PARM_DECL
- || TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == FIELD_DECL)
- TREE_DEPRECATED (decl) = 1;
- else
- warn = 1;
- }
- else if (TYPE_P (*node))
- {
- if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *node = build_type_copy (*node);
- TREE_DEPRECATED (*node) = 1;
- type = *node;
- }
- else
- warn = 1;
-
- if (warn)
- {
- *no_add_attrs = true;
- if (type && TYPE_NAME (type))
- {
- if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- what = IDENTIFIER_POINTER (TYPE_NAME (*node));
- else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- && DECL_NAME (TYPE_NAME (type)))
- what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
- }
- if (what)
- warning ("`%s' attribute ignored for `%s'",
- IDENTIFIER_POINTER (name), what);
- else
- warning ("`%s' attribute ignored",
- IDENTIFIER_POINTER (name));
- }
-
- return NULL_TREE;
-}
-
-/* Keep a list of vector type nodes we created in handle_vector_size_attribute,
- to prevent us from duplicating type nodes unnecessarily.
- The normal mechanism to prevent duplicates is to use type_hash_canon, but
- since we want to distinguish types that are essentially identical (except
- for their debug representation), we use a local list here. */
-static tree vector_type_node_list = 0;
-
-/* Handle a "vector_size" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_vector_size_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- unsigned HOST_WIDE_INT vecsize, nunits;
- enum machine_mode mode, orig_mode, new_mode;
- tree type = *node, new_type = NULL_TREE;
- tree type_list_node;
-
- *no_add_attrs = true;
-
- if (! host_integerp (TREE_VALUE (args), 1))
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- return NULL_TREE;
- }
-
- /* Get the vector size (in bytes). */
- vecsize = tree_low_cst (TREE_VALUE (args), 1);
-
- /* We need to provide for vector pointers, vector arrays, and
- functions returning vectors. For example:
-
- __attribute__((vector_size(16))) short *foo;
-
- In this case, the mode is SI, but the type being modified is
- HI, so we need to look further. */
-
- while (POINTER_TYPE_P (type)
- || TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
-
- /* Get the mode of the type being modified. */
- orig_mode = TYPE_MODE (type);
-
- if (TREE_CODE (type) == RECORD_TYPE
- || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT
- && GET_MODE_CLASS (orig_mode) != MODE_INT)
- || ! host_integerp (TYPE_SIZE_UNIT (type), 1))
- {
- error ("invalid vector type for attribute `%s'",
- IDENTIFIER_POINTER (name));
- return NULL_TREE;
- }
-
- /* Calculate how many units fit in the vector. */
- nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
-
- /* Find a suitably sized vector. */
- new_mode = VOIDmode;
- for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT
- ? MODE_VECTOR_INT
- : MODE_VECTOR_FLOAT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if (vecsize == GET_MODE_SIZE (mode)
- && nunits == (unsigned HOST_WIDE_INT) GET_MODE_NUNITS (mode))
- {
- new_mode = mode;
- break;
- }
-
- if (new_mode == VOIDmode)
- {
- error ("no vector mode with the size and type specified could be found");
- return NULL_TREE;
- }
-
- for (type_list_node = vector_type_node_list; type_list_node;
- type_list_node = TREE_CHAIN (type_list_node))
- {
- tree other_type = TREE_VALUE (type_list_node);
- tree record = TYPE_DEBUG_REPRESENTATION_TYPE (other_type);
- tree fields = TYPE_FIELDS (record);
- tree field_type = TREE_TYPE (fields);
- tree array_type = TREE_TYPE (field_type);
- if (TREE_CODE (fields) != FIELD_DECL
- || TREE_CODE (field_type) != ARRAY_TYPE)
- abort ();
-
- if (TYPE_MODE (other_type) == mode && type == array_type)
- {
- new_type = other_type;
- break;
- }
- }
-
- if (new_type == NULL_TREE)
- {
- tree index, array, rt, list_node;
-
- new_type = (*lang_hooks.types.type_for_mode) (new_mode,
- TREE_UNSIGNED (type));
-
- if (!new_type)
- {
- error ("no vector mode with the size and type specified could be found");
- return NULL_TREE;
- }
-
- new_type = build_type_copy (new_type);
-
- /* Set the debug information here, because this is the only
- place where we know the underlying type for a vector made
- with vector_size. For debugging purposes we pretend a vector
- is an array within a structure. */
- index = build_int_2 (TYPE_VECTOR_SUBPARTS (new_type) - 1, 0);
- array = build_array_type (type, build_index_type (index));
- rt = make_node (RECORD_TYPE);
-
- TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
- DECL_CONTEXT (TYPE_FIELDS (rt)) = rt;
- layout_type (rt);
- TYPE_DEBUG_REPRESENTATION_TYPE (new_type) = rt;
-
- list_node = build_tree_list (NULL, new_type);
- TREE_CHAIN (list_node) = vector_type_node_list;
- vector_type_node_list = list_node;
- }
-
- /* Build back pointers if needed. */
- *node = vector_size_helper (*node, new_type);
-
- return NULL_TREE;
-}
-
-/* HACK. GROSS. This is absolutely disgusting. I wish there was a
- better way.
-
- If we requested a pointer to a vector, build up the pointers that
- we stripped off while looking for the inner type. Similarly for
- return values from functions.
-
- The argument "type" is the top of the chain, and "bottom" is the
- new type which we will point to. */
-
-static tree
-vector_size_helper (type, bottom)
- tree type, bottom;
-{
- tree inner, outer;
-
- if (POINTER_TYPE_P (type))
- {
- inner = vector_size_helper (TREE_TYPE (type), bottom);
- outer = build_pointer_type (inner);
- }
- else if (TREE_CODE (type) == ARRAY_TYPE)
- {
- inner = vector_size_helper (TREE_TYPE (type), bottom);
- outer = build_array_type (inner, TYPE_VALUES (type));
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- inner = vector_size_helper (TREE_TYPE (type), bottom);
- outer = build_function_type (inner, TYPE_VALUES (type));
- }
- else
- return bottom;
-
- TREE_READONLY (outer) = TREE_READONLY (type);
- TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type);
-
- return outer;
-}
-
/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
lists. SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).