From patchwork Mon May 5 22:23:01 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 345943 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4147E140A99 for ; Tue, 6 May 2014 08:23:17 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:date:message-id:subject:from:to:content-type; q= dns; s=default; b=afmZrQFOsJcVNqZmI51zbvqLA8c7TFMJPISEYhe9HkCnaK XozzcMjQlFCa7leKeRb1NUu+jRORqUBbEPkyAwtMnGNdsaRhA1JQ8R0oTUj+PrTl vpMDtSuPVyxTfTn3rJjoQqurjEGGkJbBoEHZNsPWUwDE1dIgYRcCUOcDE5XT8= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:date:message-id:subject:from:to:content-type; s= default; bh=8aI+w8nn08kmN71yWg7BBif+enU=; b=Z8hNS0WTRLk86yua3vLI b9rUP9Cumidi+TZd8kVevoYIv8KtZqy2H3bDK8WX3RG9MoOPSUHI1LeSLtFd18GF c1I4vHHVii/FFJZr3itJcDf6KKxDXGKPP/h7xmAe10JlrS2279nPDkeRcEm/9MdJ 75MHQ2Le77BSWk/NDGhFNYM= Received: (qmail 4574 invoked by alias); 5 May 2014 22:23:08 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 4561 invoked by uid 89); 5 May 2014 22:23:07 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qa0-f50.google.com Received: from mail-qa0-f50.google.com (HELO mail-qa0-f50.google.com) (209.85.216.50) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Mon, 05 May 2014 22:23:03 +0000 Received: by mail-qa0-f50.google.com with SMTP id j15so2519389qaq.23 for ; Mon, 05 May 2014 15:23:01 -0700 (PDT) MIME-Version: 1.0 X-Received: by 10.224.163.17 with SMTP id y17mr15666129qax.44.1399328581566; Mon, 05 May 2014 15:23:01 -0700 (PDT) Received: by 10.229.236.133 with HTTP; Mon, 5 May 2014 15:23:01 -0700 (PDT) Date: Mon, 5 May 2014 23:23:01 +0100 Message-ID: Subject: [PATCH] Move shared attributes to common location From: Iain Buclaw To: gcc-patches X-IsSubscribed: yes Hi, This patch (changelog entry needs to be written up) moves the minimal set of attributes to accommodate the needs of builtins out of each respective front-end and into a common area shared between each. Defines lhd_common_attribute_table and lhd_format_attribute_table to provide as defaults for the COMMON_ATTRIBUTE_TABLE and FORMAT_ATTRIBUTE_TABLE langhooks respectively. All attribute handlers in LTO; Java, and most in Ada have been moved/merged together. Attributes not required for builtins.def, but in use by Ada have been left in their own language attribute table. And C family languages still override these two langhooks with their own common and format attribute tables defined in c-common.c langhooks.c seems the most appropriate place to put these, but they could just as easily go in a new source file. Regards Iain. diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index c81ab00..93e84e1 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -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. */ diff --git a/gcc/java/lang.c b/gcc/java/lang.c index 8a68691..2a4c5d0 100644 --- a/gcc/java/lang.c +++ b/gcc/java/lang.c @@ -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 diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index 95bd379..fb49e4d 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -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 \ diff --git a/gcc/langhooks.c b/gcc/langhooks.c index d00ebd8..da8b782 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -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; +} + diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c index 339bebf..875a345 100644 --- a/gcc/lto/lto-lang.c +++ b/gcc/lto/lto-lang.c @@ -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