[PATCH] make a bunch of attribute handlers globally available
Olivier Hainque
hainque@adacore.com
Wed Jun 24 10:12:00 GMT 2009
Hello,
Following up a on recent exchange about vector_size handling for Ada
at http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01799.html, this is a
re-post of the patch initially suggested at
http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01203.html
<< A number of GCC attribute handlers today shared by the C family of
languages are needed by at least Ada and possibly others, e.g. for
builtins support.
For Ada, we so far dealt with this by copy-paste operations, not
exactly proper software engineering practice. We'd like to
improve the situation, all the more that we now have needs for
the vector_size attribute as well, and maybe others in the future.
>>
... adjusted to account for Paolo's suggestion to move the common
attribute handling object files to libbackend instead of explicitely
adding them to every front-end.
Tested on x86_64-linux-suse with languages=all,ada.
Thanks in advance,
With Kind Regards,
Olivier
2009-06-26 Olivier Hainque <hainque@adacore.com>
* c-common.c (handle_noreturn_attribute, handle_const_attribute,
handle_malloc_attribute, handle_pure_attribute,
handle_novops_attribute, handle_vector_size_attribute,
handle_nonnull_attribute, handle_nothrow_attribute,
handle_sentinel_attribute, handle_type_generic_attribute,
get_nonnull_operand): Move bodies to attrib-handlers.c.
(c_common_attribute_table, "noreturn", "volatile", "const", "malloc",
"pure", "no vops", "vector_size", "nonnull", "nothrow", "sentinel",
"type generic"): Move entries to global_attribute_table in ...
* attrib-handlers.c: New file. Host global attribute handlers
extracted from c-common.c.
(global_attribute_table): Define.
* tree.h (get_nonnull_operand): Declare.
* attribs.c (global_attribute_table): Declare.
(attribute_tables, init_attributes): Handle global_attribute_table.
Use enum symbols instead of harcoded constants to designate the slots.
* Makefile.in (attrib-handlers.o): List dependencies.
(OBJS-common): Add attribs.o and attrib-handlers.o.
(C_AND_OBJC_OBJS): Remove attribs.o.
ada/
* Make-lang.in (ADA_BACKEND): Remove.
(gnat1): Use $(BACKEND) instead.
* gcc-interface/utils.c: Remove attribute handlers formerly
imported from c-common and now available to all languages. Use
NULL instead of fake_attribute_handler and remove the latter.
cp/
* Make-lang.in (CXX_C_OBJS): Remove attribs.o.
fortran/
* Make-lang.in (f951): Remove attribs.o from the dependencies.
java/
* Make-lang.in (jc1): Remove attribs.o from the dependencies.
* lang.c (java_attribute_table, LANG_HOOKS_ATTRIBUTE_TABLE): Remove.
-------------- next part --------------
Index: attribs.c
===================================================================
*** attribs.c (revision 148540)
--- attribs.c (working copy)
*************** along with GCC; see the file COPYING3.
*** 37,45 ****
static void init_attributes (void);
! /* Table of the tables of attributes (common, language, format, machine)
! searched. */
! static const struct attribute_spec *attribute_tables[4];
/* Hashtable mapping names (represented as substrings) to attribute specs. */
static htab_t attribute_hash;
--- 37,55 ----
static void init_attributes (void);
! /* Table of the tables of attributes searched. */
! enum {
! ATT_GLOBAL, /* Global, available to all languages and targets. */
! ATT_COMMON, /* Common to a family of front-ends. */
! ATT_LANGUAGE, /* Language specific. */
! ATT_FORMAT, /* For C printf format processing. */
! ATT_MACHINE, /* Machine specific. */
! N_ATT
! };
! static const struct attribute_spec *attribute_tables[N_ATT];
!
! /* The global attribute table, exposed by a dedicated unit. */
! extern const struct attribute_spec global_attribute_table[];
/* Hashtable mapping names (represented as substrings) to attribute specs. */
static htab_t attribute_hash;
*************** init_attributes (void)
*** 114,123 ****
size_t i;
int k;
! 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++)
--- 124,134 ----
size_t i;
int k;
! attribute_tables[ATT_GLOBAL] = global_attribute_table;
! attribute_tables[ATT_COMMON] = lang_hooks.common_attribute_table;
! attribute_tables[ATT_LANGUAGE] = lang_hooks.attribute_table;
! attribute_tables[ATT_FORMAT] = lang_hooks.format_attribute_table;
! attribute_tables[ATT_MACHINE] = targetm.attribute_table;
/* Translate NULL pointers to pointers to the empty table. */
for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
Index: java/Make-lang.in
===================================================================
*** java/Make-lang.in (revision 148540)
--- java/Make-lang.in (working copy)
*************** java-warn = $(STRICT_WARN)
*** 98,107 ****
# String length warnings
jvspec.o-warn = -Wno-error
! jc1$(exeext): $(JAVA_OBJS) $(BACKEND) $(LIBDEPS) attribs.o
rm -f $@
$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
! $(JAVA_OBJS) $(BACKEND) $(ZLIB) $(LIBICONV) $(LIBS) attribs.o $(BACKENDLIBS)
jcf-dump$(exeext): $(JCFDUMP_OBJS) $(LIBDEPS)
rm -f $@
--- 98,108 ----
# String length warnings
jvspec.o-warn = -Wno-error
! jc1$(exeext): $(JAVA_OBJS) $(BACKEND) $(LIBDEPS)
rm -f $@
$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
! $(JAVA_OBJS) $(BACKEND) $(ZLIB) $(LIBICONV) $(LIBS) \
! $(BACKENDLIBS)
jcf-dump$(exeext): $(JCFDUMP_OBJS) $(LIBDEPS)
rm -f $@
Index: java/lang.c
===================================================================
*** java/lang.c (revision 148540)
--- java/lang.c (working copy)
*************** static enum classify_record java_classif
*** 68,81 ****
# 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 },
- { NULL, 0, 0, false, false, false, NULL }
- };
-
/* Used to avoid printing error messages with bogus function
prototypes. Starts out false. */
static bool inhibit_error_function_printing;
--- 68,73 ----
*************** struct GTY(()) language_function {
*** 157,165 ****
#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
-
/* Each front end provides its own. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
--- 149,154 ----
Index: tree.h
===================================================================
*** tree.h (revision 148540)
--- tree.h (working copy)
*************** extern const struct attribute_spec *look
*** 4985,4990 ****
--- 4985,4995 ----
a decl attribute to the declaration rather than to its type). */
extern tree decl_attributes (tree *, tree, int);
+ /* In attrib-handlers.c. */
+
+ /* Fetch operand number from the attribute argument list. */
+ extern bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *);
+
/* In integrate.c */
extern void set_decl_abstract_flags (tree, int);
extern void set_decl_origin_self (tree);
Index: cp/Make-lang.in
===================================================================
*** cp/Make-lang.in (revision 148540)
--- cp/Make-lang.in (working copy)
*************** g++-cross$(exeext): g++$(exeext)
*** 70,76 ****
# The compiler itself.
# Shared with C front end:
! CXX_C_OBJS = attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \
c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o c-pch.o \
incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o \
c-gimplify.o c-omp.o tree-inline.o
--- 70,76 ----
# The compiler itself.
# Shared with C front end:
! CXX_C_OBJS = c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \
c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o c-pch.o \
incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o \
c-gimplify.o c-omp.o tree-inline.o
Index: ada/gcc-interface/utils.c
===================================================================
*** ada/gcc-interface/utils.c (revision 148540)
--- ada/gcc-interface/utils.c (working copy)
*************** tree gnat_std_decls[(int) ADT_LAST];
*** 90,134 ****
/* Functions to call for each of the possible raise reasons. */
tree gnat_raise_decls[(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_malloc_attribute (tree *, tree, tree, int, bool *);
- static tree handle_type_generic_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. */
- const struct attribute_spec gnat_internal_attribute_table[] =
- {
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- { "const", 0, 0, true, false, false, handle_const_attribute },
- { "nothrow", 0, 0, true, false, false, handle_nothrow_attribute },
- { "pure", 0, 0, true, false, false, handle_pure_attribute },
- { "no vops", 0, 0, true, false, false, handle_novops_attribute },
- { "nonnull", 0, -1, false, true, true, handle_nonnull_attribute },
- { "sentinel", 0, 1, false, true, true, handle_sentinel_attribute },
- { "noreturn", 0, 0, true, false, false, handle_noreturn_attribute },
- { "malloc", 0, 0, true, false, false, handle_malloc_attribute },
- { "type generic", 0, 0, false, true, true, handle_type_generic_attribute },
-
- /* ??? 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 },
- { "format_arg", 1, 1, false, true, true, fake_attribute_handler },
-
- { NULL, 0, 0, false, false, false, NULL }
- };
-
/* Associates a GNAT tree node to a GCC tree node. It is used in
`save_gnu_tree', `get_gnu_tree' and `present_gnu_tree'. See documentation
of `save_gnu_tree' for more info. */
--- 90,95 ----
*************** install_builtin_attributes (void)
*** 4998,5249 ****
#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, "%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 (!TYPE_ARG_TYPES (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))
! {
! tree argument;
! 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;
! }
!
! argument = TYPE_ARG_TYPES (type);
! if (argument)
! {
! for (ck_num = 1; ; ck_num++)
! {
! if (!argument || ck_num == arg_num)
! break;
! argument = TREE_CHAIN (argument);
! }
!
! if (!argument
! || TREE_CODE (TREE_VALUE (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 (TREE_VALUE (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)
! {
! tree params = TYPE_ARG_TYPES (*node);
!
! if (!params)
! {
! warning (OPT_Wattributes,
! "%qE attribute requires prototypes with named arguments", name);
! *no_add_attrs = true;
! }
! else
! {
! while (TREE_CHAIN (params))
! params = TREE_CHAIN (params);
!
! if (VOID_TYPE_P (TREE_VALUE (params)))
! {
! warning (OPT_Wattributes,
! "%qE attribute only applies to variadic functions", 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, "%qE attribute ignored", 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, "%qE attribute ignored", 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),
--- 4959,4976 ----
#undef DEF_ATTR_TREE_LIST
}
! /* ----------------------------------------------------------------------- *
! * ATTRIBUTES HANDLERS *
! * ----------------------------------------------------------------------- */
! /* Most of the attributes are simple and have a common handler for all
! languages. The io format related attributes are complex and very C
! specific, so remain part of the C family specific units. We fake them
! for Ada and don't support the corresponding builtin functions. */
/* Fake handler for attributes we don't properly support. */
! static tree
fake_attribute_handler (tree * ARG_UNUSED (node),
tree ARG_UNUSED (name),
tree ARG_UNUSED (args),
*************** fake_attribute_handler (tree * ARG_UNUSE
*** 5253,5279 ****
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))
{
! tree params;
!
! /* Ensure we have a function type. */
! gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
!
! params = TYPE_ARG_TYPES (*node);
! while (params && ! VOID_TYPE_P (TREE_VALUE (params)))
! params = TREE_CHAIN (params);
!
! /* Ensure we have a variadic function. */
! gcc_assert (!params);
! return NULL_TREE;
! }
/* ----------------------------------------------------------------------- *
* BUILTIN FUNCTIONS *
--- 4980,4992 ----
return NULL_TREE;
}
! const struct attribute_spec gnat_internal_attribute_table[] =
{
! { "format", 3, 3, false, true, true, fake_attribute_handler },
! { "format_arg", 1, 1, false, true, true, fake_attribute_handler },
! { NULL, 0, 0, false, false, false, NULL }
! };
/* ----------------------------------------------------------------------- *
* BUILTIN FUNCTIONS *
Index: ada/gcc-interface/Make-lang.in
===================================================================
*** ada/gcc-interface/Make-lang.in (revision 148540)
--- ada/gcc-interface/Make-lang.in (working copy)
*************** GNATBIND_OBJS = \
*** 299,315 ****
EXTRA_GNAT1_OBJS = prefix.o
EXTRA_GNATBIND_OBJS = prefix.o version.o
- # Language-independent object files.
- ADA_BACKEND = $(BACKEND) attribs.o
-
# List of target dependent sources, overridden below as necessary
TARGET_ADA_SRCS =
# Needs to be built with CC=gcc
# Since the RTL should be built with the latest compiler, remove the
# stamp target in the parent directory whenever gnat1 is rebuilt
! gnat1$(exeext): $(TARGET_ADA_SRCS) $(GNAT1_OBJS) $(ADA_BACKEND) $(LIBDEPS)
! $(GCC_LINK) -o $@ $(GNAT1_OBJS) $(ADA_BACKEND) $(LIBS) $(SYSLIBS) $(BACKENDLIBS) $(CFLAGS)
$(RM) stamp-gnatlib2-rts stamp-tools
gnatbind$(exeext): ada/b_gnatb.o $(CONFIG_H) $(GNATBIND_OBJS)
--- 299,312 ----
EXTRA_GNAT1_OBJS = prefix.o
EXTRA_GNATBIND_OBJS = prefix.o version.o
# List of target dependent sources, overridden below as necessary
TARGET_ADA_SRCS =
# Needs to be built with CC=gcc
# Since the RTL should be built with the latest compiler, remove the
# stamp target in the parent directory whenever gnat1 is rebuilt
! gnat1$(exeext): $(TARGET_ADA_SRCS) $(GNAT1_OBJS) $(BACKEND) $(LIBDEPS)
! $(GCC_LINK) -o $@ $(GNAT1_OBJS) $(BACKEND) $(LIBS) $(SYSLIBS) $(BACKENDLIBS) $(CFLAGS)
$(RM) stamp-gnatlib2-rts stamp-tools
gnatbind$(exeext): ada/b_gnatb.o $(CONFIG_H) $(GNATBIND_OBJS)
Index: fortran/Make-lang.in
===================================================================
*** fortran/Make-lang.in (revision 148540)
--- fortran/Make-lang.in (working copy)
*************** gfortran-cross$(exeext): gfortran$(exeex
*** 95,104 ****
cp gfortran$(exeext) gfortran-cross$(exeext)
# The compiler itself is called f951.
! f951$(exeext): $(F95_OBJS) \
! $(BACKEND) $(LIBDEPS) attribs.o
$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
! $(F95_OBJS) $(BACKEND) $(LIBS) attribs.o $(BACKENDLIBS)
gt-fortran-trans.h : s-gtype; @true
#
--- 95,103 ----
cp gfortran$(exeext) gfortran-cross$(exeext)
# The compiler itself is called f951.
! f951$(exeext): $(F95_OBJS) $(BACKEND) $(LIBDEPS)
$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
! $(F95_OBJS) $(BACKEND) $(LIBS) $(BACKENDLIBS)
gt-fortran-trans.h : s-gtype; @true
#
Index: attrib-handlers.c
===================================================================
*** attrib-handlers.c (revision 0)
--- attrib-handlers.c (revision 0)
***************
*** 0 ****
--- 1,438 ----
+ /* Global attribute handlers.
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+ /* This unit exposes attribute handlers of possible use to all front-ends and
+ known to be of use to at least the C family plus another language. Typical
+ examples are handlers for attributes of builtin functions or those required
+ to access to core compiler features such as vector modes processing. */
+
+ /* Some handlers use C specific format specifiers in warning messages. Make
+ sure they are properly recognized. */
+ #define GCC_DIAG_STYLE __gcc_cdiag__
+
+ #include <config.h>
+ #include <system.h>
+ #include <coretypes.h>
+ #include <tm.h>
+ #include <tree.h>
+ #include <langhooks.h>
+ #include <toplev.h>
+
+ /* Fetch operand number from the attribute argument list. */
+
+ 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 a "const" attribute. */
+
+ static tree
+ handle_const_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 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 (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+ }
+
+ /* Handle a "nothrow" attribute. */
+
+ static tree
+ handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+ {
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ TREE_NOTHROW (*node) = 1;
+ /* ??? TODO: Support types. */
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+ }
+
+ /* Handle a "pure" attribute. */
+
+ 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. */
+
+ 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;
+ }
+
+
+ /* 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 (!TYPE_ARG_TYPES (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))
+ {
+ tree argument;
+ 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;
+ }
+
+ argument = TYPE_ARG_TYPES (type);
+ if (argument)
+ {
+ for (ck_num = 1; ; ck_num++)
+ {
+ if (!argument || ck_num == arg_num)
+ break;
+ argument = TREE_CHAIN (argument);
+ }
+
+ if (!argument
+ || TREE_CODE (TREE_VALUE (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 (TREE_VALUE (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)
+ {
+ tree params = TYPE_ARG_TYPES (*node);
+
+ if (!params)
+ {
+ warning (OPT_Wattributes,
+ "%qE attribute requires prototypes with named arguments", name);
+ *no_add_attrs = true;
+ }
+ else
+ {
+ while (TREE_CHAIN (params))
+ params = TREE_CHAIN (params);
+
+ if (VOID_TYPE_P (TREE_VALUE (params)))
+ {
+ warning (OPT_Wattributes,
+ "%qE attribute only applies to variadic functions", name);
+ *no_add_attrs = true;
+ }
+ }
+
+ if (args)
+ {
+ tree position = TREE_VALUE (args);
+
+ if (TREE_CODE (position) != INTEGER_CST)
+ {
+ warning (OPT_Wattributes,
+ "requested position is not an integer constant");
+ *no_add_attrs = true;
+ }
+ else
+ {
+ if (tree_int_cst_lt (position, integer_zero_node))
+ {
+ warning (OPT_Wattributes,
+ "requested position is less than zero");
+ *no_add_attrs = true;
+ }
+ }
+ }
+
+ return NULL_TREE;
+ }
+
+ /* Handle a "noreturn" attribute. */
+
+ 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, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+ }
+
+ /* Handle a "malloc" attribute. */
+
+ 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 "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))
+ {
+ tree params;
+
+ /* Ensure we have a function type. */
+ gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
+
+ params = TYPE_ARG_TYPES (*node);
+ while (params && ! VOID_TYPE_P (TREE_VALUE (params)))
+ params = TREE_CHAIN (params);
+
+ /* Ensure we have a variadic function. */
+ gcc_assert (!params);
+
+ return NULL_TREE;
+ }
+
+ /* Handle a "vector_size" attribute. */
+
+ static tree
+ handle_vector_size_attribute (tree *node, tree name, tree args,
+ int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+ {
+ unsigned HOST_WIDE_INT vecsize, nunits;
+ enum machine_mode orig_mode;
+ tree type = *node, new_type, size;
+
+ *no_add_attrs = true;
+
+ size = TREE_VALUE (args);
+
+ if (!host_integerp (size, 1))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ return NULL_TREE;
+ }
+
+ /* Get the vector size (in bytes). */
+ vecsize = tree_low_cst (size, 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) == METHOD_TYPE
+ || TREE_CODE (type) == ARRAY_TYPE
+ || TREE_CODE (type) == OFFSET_TYPE)
+ type = TREE_TYPE (type);
+
+ /* Get the mode of the type being modified. */
+ orig_mode = TYPE_MODE (type);
+
+ if ((!INTEGRAL_TYPE_P (type)
+ && !SCALAR_FLOAT_TYPE_P (type)
+ && !FIXED_POINT_TYPE_P (type))
+ || (!SCALAR_FLOAT_MODE_P (orig_mode)
+ && GET_MODE_CLASS (orig_mode) != MODE_INT
+ && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
+ || !host_integerp (TYPE_SIZE_UNIT (type), 1)
+ || TREE_CODE (type) == BOOLEAN_TYPE)
+ {
+ error ("invalid vector type for attribute %qE", name);
+ return NULL_TREE;
+ }
+
+ if (vecsize % tree_low_cst (TYPE_SIZE_UNIT (type), 1))
+ {
+ error ("vector size not an integral multiple of component size");
+ return NULL;
+ }
+
+ if (vecsize == 0)
+ {
+ error ("zero vector size");
+ return NULL;
+ }
+
+ /* Calculate how many units fit in the vector. */
+ nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+ if (nunits & (nunits - 1))
+ {
+ error ("number of components of the vector not a power of two");
+ return NULL_TREE;
+ }
+
+ new_type = build_vector_type (type, nunits);
+
+ /* Build back pointers if needed. */
+ *node = lang_hooks.types.reconstruct_complex_type (*node, new_type);
+
+ return NULL_TREE;
+ }
+
+
+ /* Global attribute table, available to all the target machines and language
+ front-ends. */
+
+ const struct attribute_spec global_attribute_table[] =
+ {
+ /* FIXME: logically, noreturn and const 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 },
+ { "const", 0, 0, true, false, false,
+ handle_const_attribute },
+ { "nothrow", 0, 0, true, false, false,
+ handle_nothrow_attribute },
+ { "pure", 0, 0, true, false, false,
+ handle_pure_attribute },
+ { "nonnull", 0, -1, false, true, true,
+ handle_nonnull_attribute },
+ { "sentinel", 0, 1, false, true, true,
+ handle_sentinel_attribute },
+ { "malloc", 0, 0, true, false, false,
+ handle_malloc_attribute },
+ /* For internal use (marking of builtins) only. The name contains space
+ to prevent its usage in source code. */
+ { "no vops", 0, 0, true, false, false,
+ handle_novops_attribute },
+ { "type generic", 0, 0, false, true, true,
+ handle_type_generic_attribute },
+
+ { "vector_size", 1, 1, false, true, false,
+ handle_vector_size_attribute },
+
+ { NULL, 0, 0, false, false, false, NULL }
+ };
+
+
Index: c-common.c
===================================================================
*** c-common.c (revision 148540)
--- c-common.c (working copy)
*************** static bool check_case_bounds (tree, tre
*** 478,484 ****
static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
static tree handle_common_attribute (tree *, tree, tree, int, bool *);
- static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
--- 478,483 ----
*************** static tree handle_used_attribute (tree
*** 492,498 ****
static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
static tree handle_externally_visible_attribute (tree *, tree, tree, int,
bool *);
- static tree handle_const_attribute (tree *, tree, tree, int, bool *);
static tree handle_transparent_union_attribute (tree *, tree, tree,
int, bool *);
static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
--- 491,496 ----
*************** static tree handle_tls_model_attribute (
*** 509,531 ****
bool *);
static tree handle_no_instrument_function_attribute (tree *, tree,
tree, int, bool *);
- static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
bool *);
- static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
- static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
static tree handle_deprecated_attribute (tree *, tree, tree, int,
bool *);
- static tree handle_vector_size_attribute (tree *, tree, tree, int,
- bool *);
- static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
- static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
static tree handle_warn_unused_result_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_alloc_size_attribute (tree *, tree, tree, int, bool *);
static tree handle_target_attribute (tree *, tree, tree, int, bool *);
static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
--- 507,520 ----
*************** static tree handle_optimize_attribute (t
*** 533,539 ****
static void check_function_nonnull (tree, int, tree *);
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT);
- static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *);
static int resort_field_decl_cmp (const void *, const void *);
/* Reserved words. The third field is a mask: keywords are disabled
--- 522,527 ----
*************** const struct attribute_spec c_common_att
*** 720,734 ****
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,
--- 708,713 ----
*************** const struct attribute_spec c_common_att
*** 745,753 ****
handle_unused_attribute },
{ "externally_visible", 0, 0, true, false, false,
handle_externally_visible_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, 1, true, false, false,
--- 724,729 ----
*************** const struct attribute_spec c_common_att
*** 768,808 ****
handle_weakref_attribute },
{ "no_instrument_function", 0, 0, true, false, false,
handle_no_instrument_function_attribute },
- { "malloc", 0, 0, true, false, false,
- handle_malloc_attribute },
{ "returns_twice", 0, 0, true, false, false,
handle_returns_twice_attribute },
{ "no_stack_limit", 0, 0, true, false, false,
handle_no_limit_stack_attribute },
- { "pure", 0, 0, true, false, false,
- handle_pure_attribute },
- /* For internal use (marking of builtins) only. The name contains space
- to prevent its usage in source code. */
- { "no vops", 0, 0, true, false, false,
- handle_novops_attribute },
{ "deprecated", 0, 1, false, false, false,
handle_deprecated_attribute },
- { "vector_size", 1, 1, false, true, false,
- handle_vector_size_attribute },
{ "visibility", 1, 1, false, false, false,
handle_visibility_attribute },
{ "tls_model", 1, 1, true, false, false,
handle_tls_model_attribute },
- { "nonnull", 0, -1, false, true, true,
- handle_nonnull_attribute },
- { "nothrow", 0, 0, true, false, false,
- handle_nothrow_attribute },
{ "may_alias", 0, 0, false, true, false, NULL },
{ "cleanup", 1, 1, true, false, false,
handle_cleanup_attribute },
{ "warn_unused_result", 0, 0, false, true, true,
handle_warn_unused_result_attribute },
- { "sentinel", 0, 1, false, true, true,
- handle_sentinel_attribute },
- /* For internal use (marking of builtins) only. The name contains space
- to prevent its usage in source code. */
- { "type generic", 0, 0, false, true, true,
- handle_type_generic_attribute },
{ "alloc_size", 1, 2, false, true, true,
handle_alloc_size_attribute },
{ "cold", 0, 0, true, false, false,
--- 744,764 ----
*************** handle_common_attribute (tree *node, tre
*** 5812,5844 ****
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, "%qE attribute ignored", name);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
- }
-
/* Handle a "hot" and attribute; arguments as in
struct attribute_spec.handler. */
--- 5768,5773 ----
*************** handle_externally_visible_attribute (tre
*** 6110,6142 ****
return NULL_TREE;
}
- /* Handle a "const" attribute; arguments as in
- struct attribute_spec.handler. */
-
- static tree
- handle_const_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 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 (OPT_Wattributes, "%qE attribute ignored", name);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
- }
-
/* Handle a "transparent_union" attribute; arguments as in
struct attribute_spec.handler. */
--- 6039,6044 ----
*************** handle_no_instrument_function_attribute
*** 6975,6999 ****
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 "alloc_size" attribute; arguments as in
struct attribute_spec.handler. */
--- 6877,6882 ----
*************** handle_no_limit_stack_attribute (tree *n
*** 7065,7102 ****
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;
- }
-
/* Handle a "deprecated" attribute; arguments as in
struct attribute_spec.handler. */
--- 6948,6953 ----
*************** handle_deprecated_attribute (tree *node,
*** 7161,7319 ****
return NULL_TREE;
}
- /* Handle a "vector_size" attribute; arguments as in
- struct attribute_spec.handler. */
-
- static tree
- handle_vector_size_attribute (tree *node, tree name, tree args,
- int ARG_UNUSED (flags),
- bool *no_add_attrs)
- {
- unsigned HOST_WIDE_INT vecsize, nunits;
- enum machine_mode orig_mode;
- tree type = *node, new_type, size;
-
- *no_add_attrs = true;
-
- size = TREE_VALUE (args);
-
- if (!host_integerp (size, 1))
- {
- warning (OPT_Wattributes, "%qE attribute ignored", name);
- return NULL_TREE;
- }
-
- /* Get the vector size (in bytes). */
- vecsize = tree_low_cst (size, 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) == METHOD_TYPE
- || TREE_CODE (type) == ARRAY_TYPE
- || TREE_CODE (type) == OFFSET_TYPE)
- type = TREE_TYPE (type);
-
- /* Get the mode of the type being modified. */
- orig_mode = TYPE_MODE (type);
-
- if ((!INTEGRAL_TYPE_P (type)
- && !SCALAR_FLOAT_TYPE_P (type)
- && !FIXED_POINT_TYPE_P (type))
- || (!SCALAR_FLOAT_MODE_P (orig_mode)
- && GET_MODE_CLASS (orig_mode) != MODE_INT
- && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
- || !host_integerp (TYPE_SIZE_UNIT (type), 1)
- || TREE_CODE (type) == BOOLEAN_TYPE)
- {
- error ("invalid vector type for attribute %qE", name);
- return NULL_TREE;
- }
-
- if (vecsize % tree_low_cst (TYPE_SIZE_UNIT (type), 1))
- {
- error ("vector size not an integral multiple of component size");
- return NULL;
- }
-
- if (vecsize == 0)
- {
- error ("zero vector size");
- return NULL;
- }
-
- /* Calculate how many units fit in the vector. */
- nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
- if (nunits & (nunits - 1))
- {
- error ("number of components of the vector not a power of two");
- return NULL_TREE;
- }
-
- new_type = build_vector_type (type, nunits);
-
- /* Build back pointers if needed. */
- *node = lang_hooks.types.reconstruct_complex_type (*node, new_type);
-
- return NULL_TREE;
- }
-
- /* 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 (!TYPE_ARG_TYPES (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))
- {
- tree argument;
- 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;
- }
-
- argument = TYPE_ARG_TYPES (type);
- if (argument)
- {
- for (ck_num = 1; ; ck_num++)
- {
- if (!argument || ck_num == arg_num)
- break;
- argument = TREE_CHAIN (argument);
- }
-
- if (!argument
- || TREE_CODE (TREE_VALUE (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 (TREE_VALUE (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;
- }
-
/* Check the argument list of a function call for null in argument slots
that are marked as requiring a non-null pointer argument. The NARGS
arguments are passed in the array ARGARRAY.
--- 7012,7017 ----
*************** check_nonnull_arg (void * ARG_UNUSED (ct
*** 7438,7477 ****
"(argument %lu)", (unsigned long) param_num);
}
- /* 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 a "nothrow" attribute; arguments as in
- struct attribute_spec.handler. */
-
- static tree
- handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
- int ARG_UNUSED (flags), bool *no_add_attrs)
- {
- if (TREE_CODE (*node) == FUNCTION_DECL)
- TREE_NOTHROW (*node) = 1;
- /* ??? TODO: Support types. */
- else
- {
- warning (OPT_Wattributes, "%qE attribute ignored", name);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
- }
-
/* Handle a "cleanup" attribute; arguments as in
struct attribute_spec.handler. */
--- 7136,7141 ----
*************** handle_warn_unused_result_attribute (tre
*** 7534,7612 ****
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)
- {
- tree params = TYPE_ARG_TYPES (*node);
-
- if (!params)
- {
- warning (OPT_Wattributes,
- "%qE attribute requires prototypes with named arguments", name);
- *no_add_attrs = true;
- }
- else
- {
- while (TREE_CHAIN (params))
- params = TREE_CHAIN (params);
-
- if (VOID_TYPE_P (TREE_VALUE (params)))
- {
- warning (OPT_Wattributes,
- "%qE attribute only applies to variadic functions", name);
- *no_add_attrs = true;
- }
- }
-
- if (args)
- {
- tree position = TREE_VALUE (args);
-
- if (TREE_CODE (position) != INTEGER_CST)
- {
- warning (OPT_Wattributes,
- "requested position is not an integer constant");
- *no_add_attrs = true;
- }
- else
- {
- if (tree_int_cst_lt (position, integer_zero_node))
- {
- warning (OPT_Wattributes,
- "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))
- {
- tree params;
-
- /* Ensure we have a function type. */
- gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
-
- params = TYPE_ARG_TYPES (*node);
- while (params && ! VOID_TYPE_P (TREE_VALUE (params)))
- params = TREE_CHAIN (params);
-
- /* Ensure we have a variadic function. */
- gcc_assert (!params);
-
- return NULL_TREE;
- }
-
/* Handle a "target" attribute. */
static tree
--- 7198,7203 ----
Index: Makefile.in
===================================================================
*** Makefile.in (revision 148540)
--- Makefile.in (working copy)
*************** FORTRAN_TARGET_OBJS=@fortran_target_objs
*** 1053,1059 ****
GCC_OBJS = gcc.o opts-common.o gcc-options.o
# Language-specific object files for C and Objective C.
! C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \
c-ppoutput.o c-cppbuiltin.o \
c-objc-common.o c-dump.o c-pch.o c-parser.o $(C_TARGET_OBJS) \
--- 1053,1059 ----
GCC_OBJS = gcc.o opts-common.o gcc-options.o
# Language-specific object files for C and Objective C.
! C_AND_OBJC_OBJS = c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \
c-ppoutput.o c-cppbuiltin.o \
c-objc-common.o c-dump.o c-pch.o c-parser.o $(C_TARGET_OBJS) \
*************** OBJS-common = \
*** 1080,1085 ****
--- 1080,1087 ----
$(GGC) \
alias.o \
alloc-pool.o \
+ attribs.o \
+ attrib-handlers.o \
auto-inc-dec.o \
bb-reorder.o \
bitmap.o \
*************** c-cppbuiltin.o : c-cppbuiltin.c $(CONFIG
*** 1947,1957 ****
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DBASEVER=$(BASEVER_s) $< $(OUTPUT_OPTION)
! # A file used by all variants of C and some other languages.
attribs.o : attribs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(FLAGS_H) $(TOPLEV_H) output.h $(RTL_H) $(GGC_H) $(TM_P_H) \
$(TARGET_H) langhooks.h $(CPPLIB_H)
c-format.o : c-format.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) langhooks.h \
$(C_COMMON_H) $(FLAGS_H) $(TOPLEV_H) intl.h $(DIAGNOSTIC_H) alloc-pool.h \
--- 1949,1961 ----
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DBASEVER=$(BASEVER_s) $< $(OUTPUT_OPTION)
! # A couple of files used by all variants of C and some other languages.
attribs.o : attribs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(FLAGS_H) $(TOPLEV_H) output.h $(RTL_H) $(GGC_H) $(TM_P_H) \
$(TARGET_H) langhooks.h $(CPPLIB_H)
+ attrib-handlers.o : attrib-handlers.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(TREE_H) langhooks.h toplev.h
c-format.o : c-format.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) langhooks.h \
$(C_COMMON_H) $(FLAGS_H) $(TOPLEV_H) intl.h $(DIAGNOSTIC_H) alloc-pool.h \
More information about the Gcc-patches
mailing list