@@ -86,62 +86,20 @@ tree gnat_raise_decls[(int) LAST_REASON_CODE + 1];
tree gnat_raise_decls_ext[(int) LAST_REASON_CODE + 1];
/* Forward declarations for handlers of attributes. */
-static tree handle_const_attribute (tree *, tree, tree, int, bool *);
-static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
-static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
-static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
-static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
-static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
-static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
-static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
-static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
-static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
static tree handle_vector_size_attribute (tree *, tree, tree, int, bool *);
static tree handle_vector_type_attribute (tree *, tree, tree, int, bool *);
-/* Fake handler for attributes we don't properly support, typically because
- they'd require dragging a lot of the common-c front-end circuitry. */
-static tree fake_attribute_handler (tree *, tree, tree, int, bool *);
-
-/* Table of machine-independent internal attributes for Ada. We support
- this minimal set of attributes to accommodate the needs of builtins. */
+/* Table of machine-independent internal attributes for Ada. */
const struct attribute_spec gnat_internal_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
affects_type_identity } */
- { "const", 0, 0, true, false, false, handle_const_attribute,
- false },
- { "nothrow", 0, 0, true, false, false, handle_nothrow_attribute,
- false },
- { "pure", 0, 0, true, false, false, handle_pure_attribute,
- false },
- { "no vops", 0, 0, true, false, false, handle_novops_attribute,
- false },
- { "nonnull", 0, -1, false, true, true, handle_nonnull_attribute,
- false },
- { "sentinel", 0, 1, false, true, true, handle_sentinel_attribute,
- false },
- { "noreturn", 0, 0, true, false, false, handle_noreturn_attribute,
- false },
- { "leaf", 0, 0, true, false, false, handle_leaf_attribute,
- false },
- { "malloc", 0, 0, true, false, false, handle_malloc_attribute,
- false },
- { "type generic", 0, 0, false, true, true, handle_type_generic_attribute,
- false },
-
{ "vector_size", 1, 1, false, true, false, handle_vector_size_attribute,
false },
{ "vector_type", 0, 0, false, true, false, handle_vector_type_attribute,
false },
{ "may_alias", 0, 0, false, true, false, NULL, false },
- /* ??? format and format_arg are heavy and not supported, which actually
- prevents support for stdio builtins, which we however declare as part
- of the common builtins.def contents. */
- { "format", 3, 3, false, true, true, fake_attribute_handler, false },
- { "format_arg", 1, 1, false, true, true, fake_attribute_handler, false },
-
{ NULL, 0, 0, false, false, false, NULL, false }
};
@@ -6115,303 +6073,6 @@ install_builtin_attributes (void)
#undef DEF_ATTR_TREE_LIST
}
-/* Handle a "const" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_const_attribute (tree *node, tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool *no_add_attrs)
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- TREE_READONLY (*node) = 1;
- else
- *no_add_attrs = true;
-
- return NULL_TREE;
-}
-
-/* Handle a "nothrow" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool *no_add_attrs)
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- TREE_NOTHROW (*node) = 1;
- else
- *no_add_attrs = true;
-
- return NULL_TREE;
-}
-
-/* Handle a "pure" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
- int ARG_UNUSED (flags), bool *no_add_attrs)
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- DECL_PURE_P (*node) = 1;
- /* ??? TODO: Support types. */
- else
- {
- warning (OPT_Wattributes, "%qs attribute ignored",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "no vops" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool *ARG_UNUSED (no_add_attrs))
-{
- gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
- DECL_IS_NOVOPS (*node) = 1;
- return NULL_TREE;
-}
-
-/* Helper for nonnull attribute handling; fetch the operand number
- from the attribute argument list. */
-
-static bool
-get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
-{
- /* Verify the arg number is a constant. */
- if (TREE_CODE (arg_num_expr) != INTEGER_CST
- || TREE_INT_CST_HIGH (arg_num_expr) != 0)
- return false;
-
- *valp = TREE_INT_CST_LOW (arg_num_expr);
- return true;
-}
-
-/* Handle the "nonnull" attribute. */
-static tree
-handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
- tree args, int ARG_UNUSED (flags),
- bool *no_add_attrs)
-{
- tree type = *node;
- unsigned HOST_WIDE_INT attr_arg_num;
-
- /* If no arguments are specified, all pointer arguments should be
- non-null. Verify a full prototype is given so that the arguments
- will have the correct types when we actually check them later. */
- if (!args)
- {
- if (!prototype_p (type))
- {
- error ("nonnull attribute without arguments on a non-prototype");
- *no_add_attrs = true;
- }
- return NULL_TREE;
- }
-
- /* Argument list specified. Verify that each argument number references
- a pointer argument. */
- for (attr_arg_num = 1; args; args = TREE_CHAIN (args))
- {
- unsigned HOST_WIDE_INT arg_num = 0, ck_num;
-
- if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
- {
- error ("nonnull argument has invalid operand number (argument %lu)",
- (unsigned long) attr_arg_num);
- *no_add_attrs = true;
- return NULL_TREE;
- }
-
- if (prototype_p (type))
- {
- function_args_iterator iter;
- tree argument;
-
- function_args_iter_init (&iter, type);
- for (ck_num = 1; ; ck_num++, function_args_iter_next (&iter))
- {
- argument = function_args_iter_cond (&iter);
- if (!argument || ck_num == arg_num)
- break;
- }
-
- if (!argument
- || TREE_CODE (argument) == VOID_TYPE)
- {
- error ("nonnull argument with out-of-range operand number "
- "(argument %lu, operand %lu)",
- (unsigned long) attr_arg_num, (unsigned long) arg_num);
- *no_add_attrs = true;
- return NULL_TREE;
- }
-
- if (TREE_CODE (argument) != POINTER_TYPE)
- {
- error ("nonnull argument references non-pointer operand "
- "(argument %lu, operand %lu)",
- (unsigned long) attr_arg_num, (unsigned long) arg_num);
- *no_add_attrs = true;
- return NULL_TREE;
- }
- }
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "sentinel" attribute. */
-
-static tree
-handle_sentinel_attribute (tree *node, tree name, tree args,
- int ARG_UNUSED (flags), bool *no_add_attrs)
-{
- if (!prototype_p (*node))
- {
- warning (OPT_Wattributes,
- "%qs attribute requires prototypes with named arguments",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- else
- {
- if (!stdarg_p (*node))
- {
- warning (OPT_Wattributes,
- "%qs attribute only applies to variadic functions",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- }
-
- if (args)
- {
- tree position = TREE_VALUE (args);
-
- if (TREE_CODE (position) != INTEGER_CST)
- {
- warning (0, "requested position is not an integer constant");
- *no_add_attrs = true;
- }
- else
- {
- if (tree_int_cst_lt (position, integer_zero_node))
- {
- warning (0, "requested position is less than zero");
- *no_add_attrs = true;
- }
- }
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "noreturn" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
- int ARG_UNUSED (flags), 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),
- TYPE_READONLY (TREE_TYPE (type)), 1));
- else
- {
- warning (OPT_Wattributes, "%qs attribute ignored",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "leaf" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_leaf_attribute (tree *node, tree name,
- tree ARG_UNUSED (args),
- int ARG_UNUSED (flags), bool *no_add_attrs)
-{
- if (TREE_CODE (*node) != FUNCTION_DECL)
- {
- warning (OPT_Wattributes, "%qE attribute ignored", name);
- *no_add_attrs = true;
- }
- if (!TREE_PUBLIC (*node))
- {
- warning (OPT_Wattributes, "%qE attribute has no effect", name);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "malloc" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
- int ARG_UNUSED (flags), bool *no_add_attrs)
-{
- if (TREE_CODE (*node) == FUNCTION_DECL
- && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
- DECL_IS_MALLOC (*node) = 1;
- else
- {
- warning (OPT_Wattributes, "%qs attribute ignored",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Fake handler for attributes we don't properly support. */
-
-tree
-fake_attribute_handler (tree * ARG_UNUSED (node),
- tree ARG_UNUSED (name),
- tree ARG_UNUSED (args),
- int ARG_UNUSED (flags),
- bool * ARG_UNUSED (no_add_attrs))
-{
- return NULL_TREE;
-}
-
-/* Handle a "type_generic" attribute. */
-
-static tree
-handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool * ARG_UNUSED (no_add_attrs))
-{
- /* Ensure we have a function type. */
- gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
-
- /* Ensure we have a variadic function. */
- gcc_assert (!prototype_p (*node) || stdarg_p (*node));
-
- return NULL_TREE;
-}
-
/* Handle a "vector_size" attribute; arguments as in
struct attribute_spec.handler. */
@@ -71,14 +71,6 @@ static tree java_eh_personality (void);
# define TARGET_OBJECT_SUFFIX ".o"
#endif
-/* Table of machine-independent attributes. */
-const struct attribute_spec java_attribute_table[] =
-{
- { "nonnull", 0, -1, false, true, true,
- NULL, false },
- { NULL, 0, 0, false, false, false, NULL, false }
-};
-
/* Used to avoid printing error messages with bogus function
prototypes. Starts out false. */
static bool inhibit_error_function_printing;
@@ -164,9 +156,6 @@ struct GTY(()) language_function {
#undef LANG_HOOKS_SET_DECL_ASSEMBLER_NAME
#define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME java_mangle_decl
-#undef LANG_HOOKS_ATTRIBUTE_TABLE
-#define LANG_HOOKS_ATTRIBUTE_TABLE java_attribute_table
-
#undef LANG_HOOKS_EH_PERSONALITY
#define LANG_HOOKS_EH_PERSONALITY java_eh_personality
@@ -61,6 +61,10 @@ extern HOST_WIDE_INT lhd_to_target_charset (HOST_WIDE_INT);
extern tree lhd_expr_to_decl (tree, bool *, bool *);
extern tree lhd_builtin_function (tree);
+/* Declarations of default attribute table hooks. */
+extern const struct attribute_spec *lhd_common_attribute_table;
+extern const struct attribute_spec *lhd_format_attribute_table;
+
/* Declarations of default tree inlining hooks. */
extern void lhd_initialize_diagnostics (diagnostic_context *);
extern void lhd_init_options (unsigned int,
@@ -121,8 +125,8 @@ extern bool lhd_omp_mappable_type (tree);
/* Attribute hooks. */
#define LANG_HOOKS_ATTRIBUTE_TABLE NULL
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE NULL
-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE NULL
+#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE lhd_common_attribute_table
+#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE lhd_format_attribute_table
/* Tree inlining hooks. */
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P \
@@ -41,6 +41,21 @@ along with GCC; see the file COPYING3. If not see
#include "timevar.h"
#include "output.h"
+static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
+static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
+static tree handle_const_attribute (tree *, tree, tree, int, bool *);
+static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
+static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
+static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
+static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
+static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
+static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
+static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
+static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
+static tree ignore_attribute (tree *, tree, tree, int, bool *);
+
/* Do nothing; in many cases the default hook. */
void
@@ -678,3 +693,420 @@ lhd_end_section (void)
saved_section = NULL;
}
}
+
+
+/* Table of machine-independent attributes supported in GIMPLE.
+ We support this minimal set of attributes to accommodate the
+ needs of builtins.*/
+const struct attribute_spec lhd_common_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+ do_diagnostic } */
+ /* See FIXME comment on noreturn in c_common_attribute_table. */
+/*{ "noreturn", 0, 0, true, false, false,
+ handle_noreturn_attribute, false },*/
+/*{ "leaf", 0, 0, true, false, false,
+ handle_leaf_attribute, false },*/
+ /* The same comments as for noreturn attributes apply to const ones. */
+/*{ "const", 0, 0, true, false, false,
+ handle_const_attribute, false },*/
+/*{ "malloc", 0, 0, true, false, false,
+ handle_malloc_attribute, false },*/
+/*{ "pure", 0, 0, true, false, false,
+ handle_pure_attribute, false },*/
+/*{ "no vops", 0, 0, true, false, false,
+ handle_novops_attribute, false },*/
+/*{ "nonnull", 0, -1, false, true, true,
+ handle_nonnull_attribute, false },*/
+/*{ "nothrow", 0, 0, true, false, false,
+ handle_nothrow_attribute, false },*/
+ { "returns_twice", 0, 0, true, false, false,
+ handle_returns_twice_attribute, false },
+/*{ "sentinel", 0, 1, false, true, true,
+ handle_sentinel_attribute, false },*/
+/*{ "type generic", 0, 0, false, true, true,
+ handle_type_generic_attribute, false },*/
+ { "fn spec", 1, 1, false, true, true,
+ handle_fnspec_attribute, false },
+ { "transaction_pure", 0, 0, false, true, true,
+ handle_transaction_pure_attribute, false },
+ /* For internal use only. The leading '*' both prevents its usage in
+ source code and signals that it may be overridden by machine tables. */
+ { "*tm regparm", 0, 0, false, true, true,
+ ignore_attribute, false },
+ { NULL, 0, 0, false, false, false, NULL, false }
+};
+
+/* Give the specifications for the format attributes, used by C and all
+ descendants. */
+
+const struct attribute_spec lhd_format_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+ affects_type_identity } */
+ { "format", 3, 3, false, true, true,
+ ignore_attribute, false },
+ { "format_arg", 1, 1, false, true, true,
+ ignore_attribute, false },
+ { NULL, 0, 0, false, false, false, NULL, false }
+};
+
+/* Attribute handlers. */
+
+/* Handle a "noreturn" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ tree type = TREE_TYPE (*node);
+
+ 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),
+ TYPE_READONLY (TREE_TYPE (type)), 1));
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "leaf" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_leaf_attribute (tree *node, tree name,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+ if (!TREE_PUBLIC (*node))
+ {
+ warning (OPT_Wattributes, "%qE attribute has no effect", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "const" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_const_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ tree type = TREE_TYPE (*node);
+
+ 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),
+ TYPE_READONLY (TREE_TYPE (type)), 1));
+ else
+ *no_add_attrs = true;
+
+ return NULL_TREE;
+}
+
+
+/* Handle a "malloc" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL
+ && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
+ DECL_IS_MALLOC (*node) = 1;
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+
+/* Handle a "pure" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ DECL_PURE_P (*node) = 1;
+ /* ??? TODO: Support types. */
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+
+/* Handle a "no vops" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool *ARG_UNUSED (no_add_attrs))
+{
+ gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+ DECL_IS_NOVOPS (*node) = 1;
+ return NULL_TREE;
+}
+
+
+/* Helper for nonnull attribute handling; fetch the operand number
+ from the attribute argument list. */
+
+static bool
+get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
+{
+ /* Verify the arg number is a constant. */
+ if (TREE_CODE (arg_num_expr) != INTEGER_CST
+ || TREE_INT_CST_HIGH (arg_num_expr) != 0)
+ return false;
+
+ *valp = TREE_INT_CST_LOW (arg_num_expr);
+ return true;
+}
+
+/* Handle the "nonnull" attribute. */
+
+static tree
+handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
+ tree args, int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ tree type = *node;
+ unsigned HOST_WIDE_INT attr_arg_num
+
+ /* If no arguments are specified, all pointer arguments should be
+ non-null. Verify a full prototype is given so that the arguments
+ will have the correct types when we actually check them later. */
+ if (!args)
+ {
+ if (!prototype_p (type))
+ {
+ error ("nonnull attribute without arguments on a non-prototype");
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+ }
+
+ /* Argument list specified. Verify that each argument number references
+ a pointer argument. */
+ for (attr_arg_num = 1; args; args = TREE_CHAIN (args))
+ {
+ unsigned HOST_WIDE_INT arg_num = 0, ck_num;
+
+ if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
+ {
+ error ("nonnull argument has invalid operand number (argument %lu)",
+ (unsigned long) attr_arg_num);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ if (prototype_p (type))
+ {
+ function_args_iterator iter;
+ tree argument;
+
+ function_args_iter_init (&iter, type);
+ for (ck_num = 1; ; ck_num++, function_args_iter_next (&iter))
+ {
+ argument = function_args_iter_cond (&iter);
+ if (!argument || ck_num == arg_num)
+ break;
+ }
+
+ if (!argument
+ || TREE_CODE (argument) == VOID_TYPE)
+ {
+ error ("nonnull argument with out-of-range operand number "
+ "(argument %lu, operand %lu)",
+ (unsigned long) attr_arg_num, (unsigned long) arg_num);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (argument) != POINTER_TYPE)
+ {
+ error ("nonnull argument references non-pointer operand "
+ "(argument %lu, operand %lu)",
+ (unsigned long) attr_arg_num, (unsigned long) arg_num);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ }
+ }
+
+ return NULL_TREE;
+}
+
+
+/* Handle a "nothrow" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ TREE_NOTHROW (*node) = 1;
+ else
+ *no_add_attrs = true;
+
+ return NULL_TREE;
+}
+
+
+/* Handle a "sentinel" attribute. */
+
+static tree
+handle_sentinel_attribute (tree *node, tree name, tree args,
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (!prototype_p (*node))
+ {
+ warning (OPT_Wattributes,
+ "%qs attribute requires prototypes with named arguments",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ {
+ if (!stdarg_p (*node))
+ {
+ warning (OPT_Wattributes,
+ "%qs attribute only applies to variadic functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ }
+
+ if (args)
+ {
+ tree position = TREE_VALUE (args);
+
+ if (TREE_CODE (position) != INTEGER_CST)
+ {
+ warning (0, "requested position is not an integer constant");
+ *no_add_attrs = true;
+ }
+ else
+ {
+ if (tree_int_cst_lt (position, integer_zero_node))
+ {
+ warning (0, "requested position is less than zero");
+ *no_add_attrs = true;
+ }
+ }
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "type_generic" attribute. */
+
+static tree
+handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool * ARG_UNUSED (no_add_attrs))
+{
+ /* Ensure we have a function type. */
+ gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
+
+ /* Ensure we have a variadic function. */
+ gcc_assert (!prototype_p (*node) || stdarg_p (*node));
+
+ return NULL_TREE;
+}
+
+/* Handle a "transaction_pure" attribute. */
+
+static tree
+handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ /* Ensure we have a function type. */
+ if (TREE_CODE (*node) != FUNCTION_TYPE)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "returns_twice" attribute. */
+
+static tree
+handle_returns_twice_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ DECL_IS_RETURNS_TWICE (*node) = 1;
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "fn spec" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_fnspec_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
+ tree args, int ARG_UNUSED (flags),
+ bool * ARG_UNUSED (no_add_attrs))
+{
+ gcc_assert (args
+ && TREE_CODE (TREE_VALUE (args)) == STRING_CST
+ && !TREE_CHAIN (args));
+ return NULL_TREE;
+}
+
+/* Ignore the given attribute. Used when this attribute may be usefully
+ overridden by the target, but is not used generically. */
+
+static tree
+ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
@@ -46,77 +46,6 @@ along with GCC; see the file COPYING3. If not see
static tree lto_type_for_size (unsigned, int);
-static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
-static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
-static tree handle_const_attribute (tree *, tree, tree, int, bool *);
-static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
-static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
-static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
-static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
-static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
-static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
-static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
-static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
-static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
-static tree ignore_attribute (tree *, tree, tree, int, bool *);
-
-static tree handle_format_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 *);
-
-/* Table of machine-independent attributes supported in GIMPLE. */
-const struct attribute_spec lto_attribute_table[] =
-{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- do_diagnostic } */
- { "noreturn", 0, 0, true, false, false,
- handle_noreturn_attribute, false },
- { "leaf", 0, 0, true, false, false,
- handle_leaf_attribute, false },
- /* The same comments as for noreturn attributes apply to const ones. */
- { "const", 0, 0, true, false, false,
- handle_const_attribute, false },
- { "malloc", 0, 0, true, false, false,
- handle_malloc_attribute, false },
- { "pure", 0, 0, true, false, false,
- handle_pure_attribute, false },
- { "no vops", 0, 0, true, false, false,
- handle_novops_attribute, false },
- { "nonnull", 0, -1, false, true, true,
- handle_nonnull_attribute, false },
- { "nothrow", 0, 0, true, false, false,
- handle_nothrow_attribute, false },
- { "returns_twice", 0, 0, true, false, false,
- handle_returns_twice_attribute, false },
- { "sentinel", 0, 1, false, true, true,
- handle_sentinel_attribute, false },
- { "type generic", 0, 0, false, true, true,
- handle_type_generic_attribute, false },
- { "fn spec", 1, 1, false, true, true,
- handle_fnspec_attribute, false },
- { "transaction_pure", 0, 0, false, true, true,
- handle_transaction_pure_attribute, false },
- /* For internal use only. The leading '*' both prevents its usage in
- source code and signals that it may be overridden by machine tables. */
- { "*tm regparm", 0, 0, false, true, true,
- ignore_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
-};
-
-/* Give the specifications for the format attributes, used by C and all
- descendants. */
-
-const struct attribute_spec lto_format_attribute_table[] =
-{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "format", 3, 3, false, true, true,
- handle_format_attribute, false },
- { "format_arg", 1, 1, false, true, true,
- handle_format_arg_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
-};
-
enum built_in_attribute
{
#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
@@ -194,325 +123,6 @@ int flag_isoc94;
int flag_isoc99;
int flag_isoc11;
-/* Attribute handlers. */
-
-/* Handle a "noreturn" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_noreturn_attribute (tree *node, tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool * ARG_UNUSED (no_add_attrs))
-{
- tree type = TREE_TYPE (*node);
-
- 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),
- TYPE_READONLY (TREE_TYPE (type)), 1));
- else
- gcc_unreachable ();
-
- return NULL_TREE;
-}
-
-/* Handle a "leaf" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_leaf_attribute (tree *node, tree name,
- tree ARG_UNUSED (args),
- int ARG_UNUSED (flags), bool *no_add_attrs)
-{
- if (TREE_CODE (*node) != FUNCTION_DECL)
- {
- warning (OPT_Wattributes, "%qE attribute ignored", name);
- *no_add_attrs = true;
- }
- if (!TREE_PUBLIC (*node))
- {
- warning (OPT_Wattributes, "%qE attribute has no effect on unit local functions", name);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "const" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_const_attribute (tree *node, tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool * ARG_UNUSED (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
- gcc_unreachable ();
-
- return NULL_TREE;
-}
-
-
-/* Handle a "malloc" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_malloc_attribute (tree *node, tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool * ARG_UNUSED (no_add_attrs))
-{
- if (TREE_CODE (*node) == FUNCTION_DECL
- && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
- DECL_IS_MALLOC (*node) = 1;
- else
- gcc_unreachable ();
-
- return NULL_TREE;
-}
-
-
-/* Handle a "pure" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_pure_attribute (tree *node, tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool * ARG_UNUSED (no_add_attrs))
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- DECL_PURE_P (*node) = 1;
- else
- gcc_unreachable ();
-
- return NULL_TREE;
-}
-
-
-/* Handle a "no vops" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool *ARG_UNUSED (no_add_attrs))
-{
- gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
- DECL_IS_NOVOPS (*node) = 1;
- return NULL_TREE;
-}
-
-
-/* Helper for nonnull attribute handling; fetch the operand number
- from the attribute argument list. */
-
-static bool
-get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
-{
- /* Verify the arg number is a constant. */
- if (TREE_CODE (arg_num_expr) != INTEGER_CST
- || TREE_INT_CST_HIGH (arg_num_expr) != 0)
- return false;
-
- *valp = TREE_INT_CST_LOW (arg_num_expr);
- return true;
-}
-
-/* Handle the "nonnull" attribute. */
-
-static tree
-handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
- tree args, int ARG_UNUSED (flags),
- bool * ARG_UNUSED (no_add_attrs))
-{
- tree type = *node;
-
- /* If no arguments are specified, all pointer arguments should be
- non-null. Verify a full prototype is given so that the arguments
- will have the correct types when we actually check them later. */
- if (!args)
- {
- gcc_assert (prototype_p (type));
- return NULL_TREE;
- }
-
- /* Argument list specified. Verify that each argument number references
- a pointer argument. */
- for (; args; args = TREE_CHAIN (args))
- {
- tree argument;
- unsigned HOST_WIDE_INT arg_num = 0, ck_num;
-
- if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
- gcc_unreachable ();
-
- argument = TYPE_ARG_TYPES (type);
- if (argument)
- {
- for (ck_num = 1; ; ck_num++)
- {
- if (!argument || ck_num == arg_num)
- break;
- argument = TREE_CHAIN (argument);
- }
-
- gcc_assert (argument
- && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE);
- }
- }
-
- return NULL_TREE;
-}
-
-
-/* Handle a "nothrow" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool * ARG_UNUSED (no_add_attrs))
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- TREE_NOTHROW (*node) = 1;
- else
- gcc_unreachable ();
-
- return NULL_TREE;
-}
-
-
-/* Handle a "sentinel" attribute. */
-
-static tree
-handle_sentinel_attribute (tree *node, tree ARG_UNUSED (name), tree args,
- int ARG_UNUSED (flags),
- bool * ARG_UNUSED (no_add_attrs))
-{
- gcc_assert (stdarg_p (*node));
-
- if (args)
- {
- tree position = TREE_VALUE (args);
- gcc_assert (TREE_CODE (position) == INTEGER_CST);
- if (tree_int_cst_lt (position, integer_zero_node))
- gcc_unreachable ();
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "type_generic" attribute. */
-
-static tree
-handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool * ARG_UNUSED (no_add_attrs))
-{
- /* Ensure we have a function type. */
- gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
-
- /* Ensure we have a variadic function. */
- gcc_assert (!prototype_p (*node) || stdarg_p (*node));
-
- return NULL_TREE;
-}
-
-/* Handle a "transaction_pure" attribute. */
-
-static tree
-handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name),
- tree ARG_UNUSED (args),
- int ARG_UNUSED (flags),
- bool * ARG_UNUSED (no_add_attrs))
-{
- /* Ensure we have a function type. */
- gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
-
- return NULL_TREE;
-}
-
-/* Handle a "returns_twice" attribute. */
-
-static tree
-handle_returns_twice_attribute (tree *node, tree ARG_UNUSED (name),
- tree ARG_UNUSED (args),
- int ARG_UNUSED (flags),
- bool * ARG_UNUSED (no_add_attrs))
-{
- gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
-
- DECL_IS_RETURNS_TWICE (*node) = 1;
-
- return NULL_TREE;
-}
-
-/* Ignore the given attribute. Used when this attribute may be usefully
- overridden by the target, but is not used generically. */
-
-static tree
-ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool *no_add_attrs)
-{
- *no_add_attrs = true;
- return NULL_TREE;
-}
-
-/* Handle a "format" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_format_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool *no_add_attrs)
-{
- *no_add_attrs = true;
- return NULL_TREE;
-}
-
-
-/* Handle a "format_arg" attribute; arguments as in
- struct attribute_spec.handler. */
-
-tree
-handle_format_arg_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
- tree ARG_UNUSED (args), int ARG_UNUSED (flags),
- bool *no_add_attrs)
-{
- *no_add_attrs = true;
- return NULL_TREE;
-}
-
-
-/* Handle a "fn spec" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
- tree args, int ARG_UNUSED (flags),
- bool *no_add_attrs ATTRIBUTE_UNUSED)
-{
- gcc_assert (args
- && TREE_CODE (TREE_VALUE (args)) == STRING_CST
- && !TREE_CHAIN (args));
- return NULL_TREE;
-}
-
/* Cribbed from c-common.c. */
static void
@@ -1286,12 +896,6 @@ static void lto_init_ts (void)
#undef LANG_HOOKS_EH_PERSONALITY
#define LANG_HOOKS_EH_PERSONALITY lto_eh_personality
-/* Attribute hooks. */
-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE lto_attribute_table
-#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE lto_format_attribute_table
-
#undef LANG_HOOKS_BEGIN_SECTION
#define LANG_HOOKS_BEGIN_SECTION lto_obj_begin_section
#undef LANG_HOOKS_APPEND_DATA