From 333cd7613f38225c8bf75977700cdf41022ea967 Mon Sep 17 00:00:00 2001 From: amacleod Date: Fri, 19 Dec 2014 20:35:48 +0000 Subject: [PATCH] 2014-12-19 Andrew MacLeod * tree-core.h (struct attribute_spec): Add type_handler field. Rename handler to decl_handler. * attribs.c (empty_attribute_table): Add extra field. (process_attribute_spec): New. Factored from decl_attribute to return a valid attribute spec. (finalize_type_attribute): New. Factored from decl_attribute to process attributes for types after error checking. (type_attributes): New. Factored type specific portions of decl_attributes. (decl_attributes): Moved all type processing to other functions. * attribs.h (type_attributes): Export. * tree.c (handle_dll_attribute): Split into handle_dll_decl_attribute and handle_dll_type_attribute. * tree.h (handle_dll_decl_attribute, handle_dll_type_attribute): New prototypes. * c/c-decl.c (groktypename, grokdeclarator, finish_struct, finish_enum): Call type_attributes. * cp/decl.c (grokdeclarator): Call type_attributes. * cp/decl2.c (cplus_decl_attributes): Call type_attributes when node is a type. * ada/gcc-interface/utils.c (gnat_internal_attribute_table): Adjust handlers. (finish_record_type): Call type_attribute. (process_attributes): Call type_attribute or decl_attribute as needed. * cp/tree.c (cxx_attribute_table): Adjust attribute handlers. (handle_java_interface_decl_attributes, handle_java_interface_type_attribute): Factor from handle_java_interface_attribute. (handle_com_interface_decl_attributes, handle_com_interface_type_attribute): Factor from handle_com_interface_attribute. (handle_abi_tag_decl_attributes, handle_abi_tag_type_attribute): Factor from handle_abi_tag_attribute. * c-family/c-common.c (c_common_attribute_table): Adjust handlers. (c_common_format_attribute_table): Adjust handlers. (handle_packed_type_attribute, handle_packed_decl_attribute): Factor from handle_packed_attribute. (handle_unused_type_attribute, handle_unused_decl_attribute): Factor from handle_unused_attribute. (handle_transparent_union_type_attribute, handle_transparent_union_decl_attribute): Factor from handle_transparent_union_attribute. (get_align_expr, handle_aligned_type, handle_aligned_type_attribute, handle_aligned_decl_attribute): Factor from handle_aligned_attribute. (handle_decl_visibility, handle_visibility_decl_attribute, handle_visibility_type_attribute): factor from handle_visibility_attribute. (handle_fnspec_attribute): No need to assert TYPE_P any longer. (handle_warn_unused_type_attribute, handle_warn_unused_decl_attribute): Factor from handle_warn_unused_attribute. (handle_tm_attribute): Call type_attributes. (handle_deprecated_type_attribute, handle_deprecated_decl_attribute): Factored from handle_deprecated_attribute. * fortran/f95-lang.c (gfc_attribute_table): Adjust handlers. * lto/lto-lang.c (lto_attribute_table): Adjust handlers. * java/lang.c (java_attribute_table): Adjust handlers. * config/alpha/alpha.c (vms_attribute_table): Adjust handlers. * config/arc/arc.c (arc_attribute_table): Adjust handlers. * config/arm/arm.c (arm_attribute_table): Adjust handlers. (arm_handle_isr_decl_attribute, arm_handle_isr_type_attribute): Factor from arm_handle_isr_attribute. * config/avr/avr.c (avr_ignore_type_attribute, avr_warning_type_attribute): New. Generic handlers. (avr_attribute_table): Adjust handlers. * config/bfin/bfin.c (handle_int_type_attribute, handle_int_decl_attribute): Factor from handle_int_attribute. (bfin_handle_longcall_attribute): Impossible to ever see a FIELD_DECL or a TYPE_DECL, so don't handle those cases. (bfin_attribute_table): Adjust handlers. * config/cr16/cr16.c (cr16_attribute_table): Adjust comments. * config/darwin.h (SUBTARGET_ATTRIBUTE_TABLE): Adjust handlers. * config/epiphany/epiphany.c (epiphany_attribute_table): Adjust handlers. * config/h8300/h8300.c (h8300_attribute_table): Adjust handlers. * config/i386/cygming.h (SUBTARGET_ATTRIBUTE_TABLE): Adjust handlers. * config/i386/i386.c (ix86_handle_cconv_attribute): Remove check for FIELD_DECL and TYPE_DECL since they are impossible to see. (ix86_handle_tm_regparm_attribute): Call type_attribute or decl_attribute as required. (ix86_init_tm_builtins): Call type_attributes. (ix86_handle_struct_type_attribute,ix86_handle_struct_decl_attribute): Factor from ix86_handle_struct_attribute. (ix86_attribute_table): Adjust handlers. * config/ia64/ia64.c (ia64_attribute_table): Adjust handlers. * config/m32c/m32c.c (interrupt_type_handler, interrupt_decl_handler): Factor from interrupt_handler. (m32c_attribute_table): Adjust handlers. * config/m32r/m32r.c (m32r_attribute_table): Adjust handlers. * config/m68k/m68k.c (m68k_attribute_table): Adjust handlers. * config/mcore/mcore.c (mcore_attribute_table): Adjust handlers. * config/mep/mep.c (mep_validate_type_based_tiny, mep_validate_decl_based_tiny): Factor from mep_validate_based_tiny. (mep_validate_type_near_far, mep_validate_decl_near_far): Factor from mep_validate_near_far. (mep_validate_type_disinterrupt, mep_validate_decl_disinterrupt): Factor from mep_validate_disinterrupt. (mep_validate_type_warning): Issues warning handler. (mep_attribute_table): Adjust handlers. * config/microblaze/microblaze.c: (microblaze_attribute_table): Add extra fields. * config/mips/mips.c (mips_attribute_table): Adjust handlers. * config/msp430/msp430.c (msp430_attribute_table): Adjust handlers. * config/nds32/nds32.c (nds32_attribute_table): Add extra fields. * config/nvptx/nvptx.c (nvptx_attribute_table): Adjust handlers. * config/rl78/rl78.c (r178_attribute_table): Adjust handlers. * config/rs6000/rs6000.c (rs600_attribute_table): Adjust handlers. (rs6000_handle_longcall_attribute): Remove handling of FIELD_DECL and TYPE_DECL since they are impossible to reach. (rs6000_handle_struct_type_attribute, rs6000_handle_struct_decl_attribute): Factor from rs6000_handle_struct_attribute. * config/rx/rx.c (rx_attribute_table): Adjust handlers. * config/s390/s390.c (s390_attribute_table): Adjust handlers. * config/sh/sh.c (sh_attribute_table): Adjust handlers. * config/sol2.h (SOLARIS_ATTRIBUTE_TABLE): Add extra fields. * config/sparc/sparc.c (sparc_attribute_table): Add extra fields. * config/spu/spu.c (spu_attribute_table): Adjust handlers. * config/stormy16/stormy16.c (xstormy16_attribute_table): Adjust handlers. (xstormy16_handle_below100_attribute): Don't handle POINTER_TYPE or TYPE_DECL. * config/v850/v850.c (v850_attribute_table): Adjust handlers. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/ttype@218978 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog.ttype | 125 ++++++++ gcc/ada/gcc-interface/utils.c | 60 ++-- gcc/attribs.c | 457 ++++++++++++++++----------- gcc/attribs.h | 1 + gcc/c-family/c-common.c | 620 +++++++++++++++++++++---------------- gcc/c/c-decl.c | 8 +- gcc/config/alpha/alpha.c | 9 +- gcc/config/arc/arc.c | 15 +- gcc/config/arm/arm.c | 118 +++---- gcc/config/avr/avr.c | 53 +++- gcc/config/bfin/bfin.c | 67 ++-- gcc/config/cr16/cr16.c | 8 +- gcc/config/darwin.h | 4 +- gcc/config/epiphany/epiphany.c | 16 +- gcc/config/h8300/h8300.c | 16 +- gcc/config/i386/cygming.h | 6 +- gcc/config/i386/i386.c | 92 +++--- gcc/config/ia64/ia64.c | 14 +- gcc/config/m32c/m32c.c | 27 +- gcc/config/m32r/m32r.c | 10 +- gcc/config/m68k/m68k.c | 8 +- gcc/config/mcore/mcore.c | 8 +- gcc/config/mep/mep.c | 109 +++++-- gcc/config/microblaze/microblaze.c | 16 +- gcc/config/mips/mips.c | 30 +- gcc/config/msp430/msp430.c | 14 +- gcc/config/nds32/nds32.c | 27 +- gcc/config/nvptx/nvptx.c | 9 +- gcc/config/rl78/rl78.c | 12 +- gcc/config/rs6000/rs6000.c | 64 ++-- gcc/config/rx/rx.c | 14 +- gcc/config/s390/s390.c | 5 +- gcc/config/sh/sh.c | 22 +- gcc/config/sol2.h | 4 +- gcc/config/sparc/sparc.c | 6 +- gcc/config/spu/spu.c | 12 +- gcc/config/stormy16/stormy16.c | 24 +- gcc/config/v850/v850.c | 16 +- gcc/cp/decl.c | 8 +- gcc/cp/decl2.c | 15 +- gcc/cp/tree.c | 174 ++++++----- gcc/fortran/f95-lang.c | 8 +- gcc/java/lang.c | 5 +- gcc/lto/lto-lang.c | 35 ++- gcc/tree-core.h | 4 +- gcc/tree.c | 65 ++-- gcc/tree.h | 3 +- 47 files changed, 1471 insertions(+), 972 deletions(-) diff --git a/gcc/ChangeLog.ttype b/gcc/ChangeLog.ttype index b28ee241cd7..01e86d020c1 100644 --- a/gcc/ChangeLog.ttype +++ b/gcc/ChangeLog.ttype @@ -1,5 +1,130 @@ 2014-12-19 Andrew MacLeod + * tree-core.h (struct attribute_spec): Add type_handler field. Rename + handler to decl_handler. + * attribs.c (empty_attribute_table): Add extra field. + (process_attribute_spec): New. Factored from decl_attribute to return + a valid attribute spec. + (finalize_type_attribute): New. Factored from decl_attribute to + process attributes for types after error checking. + (type_attributes): New. Factored type specific portions of + decl_attributes. + (decl_attributes): Moved all type processing to other functions. + * attribs.h (type_attributes): Export. + * tree.c (handle_dll_attribute): Split into handle_dll_decl_attribute + and handle_dll_type_attribute. + * tree.h (handle_dll_decl_attribute, handle_dll_type_attribute): New + prototypes. + * c/c-decl.c (groktypename, grokdeclarator, finish_struct, + finish_enum): Call type_attributes. + * cp/decl.c (grokdeclarator): Call type_attributes. + * cp/decl2.c (cplus_decl_attributes): Call type_attributes when node is + a type. + * ada/gcc-interface/utils.c (gnat_internal_attribute_table): Adjust + handlers. + (finish_record_type): Call type_attribute. + (process_attributes): Call type_attribute or decl_attribute as needed. + * cp/tree.c (cxx_attribute_table): Adjust attribute handlers. + (handle_java_interface_decl_attributes, + handle_java_interface_type_attribute): Factor from + handle_java_interface_attribute. + (handle_com_interface_decl_attributes, + handle_com_interface_type_attribute): Factor from + handle_com_interface_attribute. + (handle_abi_tag_decl_attributes, handle_abi_tag_type_attribute): Factor + from handle_abi_tag_attribute. + * c-family/c-common.c (c_common_attribute_table): Adjust handlers. + (c_common_format_attribute_table): Adjust handlers. + (handle_packed_type_attribute, handle_packed_decl_attribute): Factor + from handle_packed_attribute. + (handle_unused_type_attribute, handle_unused_decl_attribute): Factor + from handle_unused_attribute. + (handle_transparent_union_type_attribute, + handle_transparent_union_decl_attribute): Factor from + handle_transparent_union_attribute. + (get_align_expr, handle_aligned_type, handle_aligned_type_attribute, + handle_aligned_decl_attribute): Factor from handle_aligned_attribute. + (handle_decl_visibility, handle_visibility_decl_attribute, + handle_visibility_type_attribute): factor from + handle_visibility_attribute. + (handle_fnspec_attribute): No need to assert TYPE_P any longer. + (handle_warn_unused_type_attribute, handle_warn_unused_decl_attribute): + Factor from handle_warn_unused_attribute. + (handle_tm_attribute): Call type_attributes. + (handle_deprecated_type_attribute, handle_deprecated_decl_attribute): + Factored from handle_deprecated_attribute. + * fortran/f95-lang.c (gfc_attribute_table): Adjust handlers. + * lto/lto-lang.c (lto_attribute_table): Adjust handlers. + * java/lang.c (java_attribute_table): Adjust handlers. + * config/alpha/alpha.c (vms_attribute_table): Adjust handlers. + * config/arc/arc.c (arc_attribute_table): Adjust handlers. + * config/arm/arm.c (arm_attribute_table): Adjust handlers. + (arm_handle_isr_decl_attribute, arm_handle_isr_type_attribute): Factor + from arm_handle_isr_attribute. + * config/avr/avr.c (avr_ignore_type_attribute, + avr_warning_type_attribute): New. Generic handlers. + (avr_attribute_table): Adjust handlers. + * config/bfin/bfin.c (handle_int_type_attribute, + handle_int_decl_attribute): Factor from handle_int_attribute. + (bfin_handle_longcall_attribute): Impossible to ever see a FIELD_DECL + or a TYPE_DECL, so don't handle those cases. + (bfin_attribute_table): Adjust handlers. + * config/cr16/cr16.c (cr16_attribute_table): Adjust comments. + * config/darwin.h (SUBTARGET_ATTRIBUTE_TABLE): Adjust handlers. + * config/epiphany/epiphany.c (epiphany_attribute_table): Adjust + handlers. + * config/h8300/h8300.c (h8300_attribute_table): Adjust handlers. + * config/i386/cygming.h (SUBTARGET_ATTRIBUTE_TABLE): Adjust handlers. + * config/i386/i386.c (ix86_handle_cconv_attribute): Remove check for + FIELD_DECL and TYPE_DECL since they are impossible to see. + (ix86_handle_tm_regparm_attribute): Call type_attribute or + decl_attribute as required. + (ix86_init_tm_builtins): Call type_attributes. + (ix86_handle_struct_type_attribute,ix86_handle_struct_decl_attribute): + Factor from ix86_handle_struct_attribute. + (ix86_attribute_table): Adjust handlers. + * config/ia64/ia64.c (ia64_attribute_table): Adjust handlers. + * config/m32c/m32c.c (interrupt_type_handler, interrupt_decl_handler): + Factor from interrupt_handler. + (m32c_attribute_table): Adjust handlers. + * config/m32r/m32r.c (m32r_attribute_table): Adjust handlers. + * config/m68k/m68k.c (m68k_attribute_table): Adjust handlers. + * config/mcore/mcore.c (mcore_attribute_table): Adjust handlers. + * config/mep/mep.c (mep_validate_type_based_tiny, + mep_validate_decl_based_tiny): Factor from mep_validate_based_tiny. + (mep_validate_type_near_far, mep_validate_decl_near_far): Factor + from mep_validate_near_far. + (mep_validate_type_disinterrupt, mep_validate_decl_disinterrupt): Factor + from mep_validate_disinterrupt. + (mep_validate_type_warning): Issues warning handler. + (mep_attribute_table): Adjust handlers. + * config/microblaze/microblaze.c: (microblaze_attribute_table): Add + extra fields. + * config/mips/mips.c (mips_attribute_table): Adjust handlers. + * config/msp430/msp430.c (msp430_attribute_table): Adjust handlers. + * config/nds32/nds32.c (nds32_attribute_table): Add extra fields. + * config/nvptx/nvptx.c (nvptx_attribute_table): Adjust handlers. + * config/rl78/rl78.c (r178_attribute_table): Adjust handlers. + * config/rs6000/rs6000.c (rs600_attribute_table): Adjust handlers. + (rs6000_handle_longcall_attribute): Remove handling of FIELD_DECL and + TYPE_DECL since they are impossible to reach. + (rs6000_handle_struct_type_attribute, + rs6000_handle_struct_decl_attribute): Factor from + rs6000_handle_struct_attribute. + * config/rx/rx.c (rx_attribute_table): Adjust handlers. + * config/s390/s390.c (s390_attribute_table): Adjust handlers. + * config/sh/sh.c (sh_attribute_table): Adjust handlers. + * config/sol2.h (SOLARIS_ATTRIBUTE_TABLE): Add extra fields. + * config/sparc/sparc.c (sparc_attribute_table): Add extra fields. + * config/spu/spu.c (spu_attribute_table): Adjust handlers. + * config/stormy16/stormy16.c (xstormy16_attribute_table): Adjust + handlers. + (xstormy16_handle_below100_attribute): Don't handle POINTER_TYPE or + TYPE_DECL. + * config/v850/v850.c (v850_attribute_table): Adjust handlers. + +2014-12-19 Andrew MacLeod + * tree.h (function_args_iter_init): Add a const_ttype arg. * ttype.patch: Initial patch to use ttype as a struct pointer only for compilation testing. diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 1b1473723c6..b566257e9a4 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -122,44 +122,46 @@ static tree fake_attribute_handler (tree *, tree, tree, int, bool *); 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, - affects_type_identity } */ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ { "const", 0, 0, true, false, false, handle_const_attribute, - false }, + NULL, false }, { "nothrow", 0, 0, true, false, false, handle_nothrow_attribute, - false }, + NULL, false }, { "pure", 0, 0, true, false, false, handle_pure_attribute, - false }, + NULL, 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 }, + NULL, false }, + { "nonnull", 0, -1, false, true, true, NULL, + handle_nonnull_attribute, false }, + { "sentinel", 0, 1, false, true, true, NULL, + handle_sentinel_attribute, false }, { "noreturn", 0, 0, true, false, false, handle_noreturn_attribute, - false }, + NULL, false }, { "leaf", 0, 0, true, false, false, handle_leaf_attribute, - false }, + NULL, false }, { "always_inline",0, 0, true, false, false, handle_always_inline_attribute, - false }, + NULL, false }, { "malloc", 0, 0, true, false, false, handle_malloc_attribute, - false }, - { "type generic", 0, 0, false, true, true, handle_type_generic_attribute, - false }, + NULL, false }, + { "type generic", 0, 0, false, true, true, NULL, + 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 }, + { "vector_size", 1, 1, false, true, false, NULL, + handle_vector_size_attribute, false }, + { "vector_type", 0, 0, false, true, false, NULL, + handle_vector_type_attribute, false }, + { "may_alias", 0, 0, false, true, false, NULL, 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 }, + { "format", 3, 3, false, true, true, NULL, + fake_attribute_handler, false }, + { "format_arg", 1, 1, false, true, true, NULL, + fake_attribute_handler, false }, - { NULL, 0, 0, false, false, false, NULL, false } + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Associates a GNAT tree node to a GCC tree node. It is used in @@ -1622,7 +1624,7 @@ finish_record_type (tree record_type, tree field_list, int rep_level, efficient packing in almost all cases. */ #ifdef TARGET_MS_BITFIELD_LAYOUT if (TARGET_MS_BITFIELD_LAYOUT && TYPE_PACKED (record_type)) - decl_attributes (&record_type, + type_attributes (&record_type, tree_cons (get_identifier ("gcc_struct"), NULL_TREE, NULL_TREE), ATTR_FLAG_TYPE_IN_PLACE); @@ -2643,8 +2645,12 @@ process_attributes (tree *node, struct attrib **attr_list, bool in_place, { case ATTR_MACHINE_ATTRIBUTE: Sloc_to_locus (Sloc (gnat_node), &input_location); - decl_attributes (node, tree_cons (attr->name, attr->args, NULL_TREE), - in_place ? ATTR_FLAG_TYPE_IN_PLACE : 0); + if (TYPE_P (*node)) + type_attributes (node, tree_cons (attr->name, attr->args, NULL_TREE), + in_place ? ATTR_FLAG_TYPE_IN_PLACE : 0); + else + decl_attributes (node, tree_cons (attr->name, attr->args, NULL_TREE), + in_place ? ATTR_FLAG_TYPE_IN_PLACE : 0); break; case ATTR_LINK_ALIAS: diff --git a/gcc/attribs.c b/gcc/attribs.c index fe847034897..96d40db4974 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -101,7 +101,7 @@ static bool attributes_initialized = false; static const struct attribute_spec empty_attribute_table[] = { - { NULL, 0, 0, false, false, false, NULL, false } + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Return base name of the attribute. Ie '__attr__' is turned into 'attr'. @@ -354,15 +354,268 @@ get_attribute_namespace (const_tree attr) return get_identifier ("gnu"); } +/* Lookup the spec for attribute A using FLAGS, and issue any warnings or + errors as appropriate. Return NULL or a valid spec. */ + +static const struct attribute_spec * +process_attribute_spec (tree a, int flags) +{ + tree name = get_attribute_name (a); + tree ns = get_attribute_namespace (a); + tree args = TREE_VALUE (a); + const struct attribute_spec *spec = lookup_scoped_attribute_spec (ns, name); + + if (spec == NULL) + { + if (!(flags & (int) ATTR_FLAG_BUILT_IN)) + { + if (ns == NULL_TREE || !cxx11_attribute_p (a)) + warning (OPT_Wattributes, "%qE attribute directive ignored", + name); + else + warning (OPT_Wattributes, + "%<%E::%E%> scoped attribute directive ignored", + ns, name); + } + return NULL; + } + else if (list_length (args) < spec->min_length + || (spec->max_length >= 0 + && list_length (args) > spec->max_length)) + { + error ("wrong number of arguments specified for %qE attribute", + name); + return NULL; + } + gcc_assert (is_attribute_p (spec->name, name)); + return spec; +} + +/* Perform the type specific processing of type_attribute. This is factored + out to allow decl_attributes() to process underlying types when necessary. + In those cases, DECL_NODE is passed in so the decl can have re-layout + called. SPEC is the already verified attribute spec structure. Otherwise + the parameters match those of type_attribute. */ + +static tree +finalize_type_attribute (tree *node, const struct attribute_spec *spec, + tree a, tree returned_attrs, int flags, + tree *decl_node = NULL) +{ + bool no_add_attrs = 0; + int fn_ptr_quals = 0; + tree fn_ptr_tmp = NULL_TREE; + tree name = get_attribute_name (a); + tree args = TREE_VALUE (a); + tree *anode = node; + + gcc_checking_assert (TYPE_P (*node)); + + if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE + && TREE_CODE (*anode) != METHOD_TYPE) + { + if (TREE_CODE (*anode) == POINTER_TYPE + && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE)) + { + /* OK, this is a bit convoluted. We can't just make a copy + of the pointer type and modify its TREE_TYPE, because if + we change the attributes of the target type the pointer + type needs to have a different TYPE_MAIN_VARIANT. So we + pull out the target type now, frob it as appropriate, and + rebuild the pointer type later. + + This would all be simpler if attributes were part of the + declarator, grumble grumble. */ + fn_ptr_tmp = TREE_TYPE (*anode); + fn_ptr_quals = TYPE_QUALS (*anode); + anode = &fn_ptr_tmp; + flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE; + } + else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT) + { + /* Pass on this attribute to be tried again. */ + returned_attrs = tree_cons (name, args, returned_attrs); + return returned_attrs; + } + + if (TREE_CODE (*anode) != FUNCTION_TYPE + && TREE_CODE (*anode) != METHOD_TYPE) + { + warning (OPT_Wattributes, + "%qE attribute only applies to function types", + name); + return returned_attrs; + } + } + + if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE) + && TYPE_SIZE (*anode) != NULL_TREE) + { + warning (OPT_Wattributes, "type attributes ignored after type is already defined"); + return returned_attrs; + } + + if (spec->type_handler != NULL) + { + int cxx11_flag = + cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0; + + returned_attrs = chainon ((*spec->type_handler) (anode, name, args, + flags|cxx11_flag, + &no_add_attrs), + returned_attrs); + } + + /* If there was a decl change the layout in case anything changed. */ + if (decl_node && spec->type_required + && (TREE_CODE (*decl_node) == VAR_DECL + || TREE_CODE (*decl_node) == PARM_DECL + || TREE_CODE (*decl_node) == RESULT_DECL)) + relayout_decl (*decl_node); + + if (!no_add_attrs) + { + tree old_attrs; + tree a; + + old_attrs = TYPE_ATTRIBUTES (*anode); + + for (a = lookup_attribute (spec->name, old_attrs); + a != NULL_TREE; + a = lookup_attribute (spec->name, TREE_CHAIN (a))) + { + if (simple_cst_equal (TREE_VALUE (a), args) == 1) + break; + } + + if (a == NULL_TREE) + { + if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE) + { + TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs); + /* If this is the main variant, also push the attributes + out to the other variants. */ + if (*anode == TYPE_MAIN_VARIANT (*anode)) + { + tree variant; + for (variant = *anode; variant; + variant = TYPE_NEXT_VARIANT (variant)) + { + if (TYPE_ATTRIBUTES (variant) == old_attrs) + TYPE_ATTRIBUTES (variant) + = TYPE_ATTRIBUTES (*anode); + else if (!lookup_attribute + (spec->name, TYPE_ATTRIBUTES (variant))) + TYPE_ATTRIBUTES (variant) = tree_cons + (name, args, TYPE_ATTRIBUTES (variant)); + } + } + } + else + *anode = build_type_attribute_variant (*anode, + tree_cons (name, args, + old_attrs)); + } + } + + if (fn_ptr_tmp) + { + /* Rebuild the function pointer type and put it in the + appropriate place. */ + fn_ptr_tmp = build_pointer_type (fn_ptr_tmp); + if (fn_ptr_quals) + fn_ptr_tmp = build_qualified_type (fn_ptr_tmp, fn_ptr_quals); + if (decl_node) + TREE_TYPE (*decl_node) = fn_ptr_tmp; + else + { + gcc_assert (TREE_CODE (*node) == POINTER_TYPE); + *node = fn_ptr_tmp; + } + } + return returned_attrs; + +} + +/* Process the attributes listed in ATTRIBUTES and install them in *NODE, + which is a TYPE. A copy should be created unless ATTR_FLAG_TYPE_IN_PLACE + is set in FLAGS. FLAGS gives further information, in the form of a + bitwise OR of flags in enum attribute_flags from tree.h. + Depending on these flags, some attributes may be returned to be + applied at a later stage (for example, to apply a decl attribute to the + declaration rather than to its type). */ + +tree +type_attributes (tree *node, tree attributes, int flags) +{ + tree a; + tree returned_attrs = NULL_TREE; + + if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node) + return NULL_TREE; + + gcc_checking_assert (TYPE_P (*node)); + + if (!attributes_initialized) + init_attributes (); + + targetm.insert_attributes (*node, &attributes); + + for (a = attributes; a; a = TREE_CHAIN (a)) + { + tree name = get_attribute_name (a); + tree args = TREE_VALUE (a); + const struct attribute_spec *spec = process_attribute_spec (a, flags); + + if (!spec) + continue; + + if (cxx11_attribute_p (a) && !(flags & ATTR_FLAG_TYPE_IN_PLACE)) + { + /* This is a c++11 attribute that appertains to a + type-specifier, outside of the definition of, a class + type. Ignore it. */ + warning (OPT_Wattributes, "attribute ignored"); + inform (input_location, + "an attribute that appertains to a type-specifier " + "is ignored"); + continue; + } + + if (spec->decl_required) + { + if (flags & ((int) ATTR_FLAG_DECL_NEXT + | (int) ATTR_FLAG_FUNCTION_NEXT + | (int) ATTR_FLAG_ARRAY_NEXT)) + { + /* Pass on this attribute to be tried again. */ + returned_attrs = tree_cons (name, args, returned_attrs); + continue; + } + else + { + warning (OPT_Wattributes, "%qE attribute does not apply to types", + name); + continue; + } + } + + returned_attrs = finalize_type_attribute (node, spec, a, returned_attrs, + flags); + } + + return returned_attrs; +} + + + /* Process the attributes listed in ATTRIBUTES and install them in *NODE, - which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL, - it should be modified in place; if a TYPE, a copy should be created - unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS. FLAGS gives further - information, in the form of a bitwise OR of flags in enum attribute_flags - from tree.h. Depending on these flags, some attributes may be - returned to be applied at a later stage (for example, to apply - a decl attribute to the declaration rather than to its type). */ + which is a DECL (including a TYPE_DECL) it should be modified in place; + FLAGS gives further information, in the form of a bitwise OR of flags in + enum attribute_flags from tree.h. Depending on these flags, some + attributes may be returned to be applied at a later stage. */ tree decl_attributes (tree *node, tree attributes, int flags) @@ -370,9 +623,12 @@ decl_attributes (tree *node, tree attributes, int flags) tree a; tree returned_attrs = NULL_TREE; + if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node) return NULL_TREE; + gcc_checking_assert (DECL_P (*node)); + if (!attributes_initialized) init_attributes (); @@ -429,155 +685,46 @@ decl_attributes (tree *node, tree attributes, int flags) for (a = attributes; a; a = TREE_CHAIN (a)) { - tree ns = get_attribute_namespace (a); tree name = get_attribute_name (a); tree args = TREE_VALUE (a); tree *anode = node; - const struct attribute_spec *spec = - lookup_scoped_attribute_spec (ns, name); bool no_add_attrs = 0; - int fn_ptr_quals = 0; - tree fn_ptr_tmp = NULL_TREE; - - if (spec == NULL) - { - if (!(flags & (int) ATTR_FLAG_BUILT_IN)) - { - if (ns == NULL_TREE || !cxx11_attribute_p (a)) - warning (OPT_Wattributes, "%qE attribute directive ignored", - name); - else - warning (OPT_Wattributes, - "%<%E::%E%> scoped attribute directive ignored", - ns, name); - } - continue; - } - else if (list_length (args) < spec->min_length - || (spec->max_length >= 0 - && list_length (args) > spec->max_length)) - { - error ("wrong number of arguments specified for %qE attribute", - name); - continue; - } - gcc_assert (is_attribute_p (spec->name, name)); + const struct attribute_spec *spec = process_attribute_spec (a, flags); - if (TYPE_P (*node) - && cxx11_attribute_p (a) - && !(flags & ATTR_FLAG_TYPE_IN_PLACE)) - { - /* This is a c++11 attribute that appertains to a - type-specifier, outside of the definition of, a class - type. Ignore it. */ - warning (OPT_Wattributes, "attribute ignored"); - inform (input_location, - "an attribute that appertains to a type-specifier " - "is ignored"); - continue; - } + gcc_assert (DECL_P (*node)); - if (spec->decl_required && !DECL_P (*anode)) - { - if (flags & ((int) ATTR_FLAG_DECL_NEXT - | (int) ATTR_FLAG_FUNCTION_NEXT - | (int) ATTR_FLAG_ARRAY_NEXT)) - { - /* Pass on this attribute to be tried again. */ - returned_attrs = tree_cons (name, args, returned_attrs); - continue; - } - else - { - warning (OPT_Wattributes, "%qE attribute does not apply to types", - name); - continue; - } - } + if (!spec) + continue; /* If we require a type, but were passed a decl, set up to make a new type and update the one in the decl. ATTR_FLAG_TYPE_IN_PLACE would have applied if we'd been passed a type, but we cannot modify the decl's type in place here. */ - if (spec->type_required && DECL_P (*anode)) + if (spec->type_required) { anode = &TREE_TYPE (*anode); flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE; - } - - if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE - && TREE_CODE (*anode) != METHOD_TYPE) - { - if (TREE_CODE (*anode) == POINTER_TYPE - && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE)) - { - /* OK, this is a bit convoluted. We can't just make a copy - of the pointer type and modify its TREE_TYPE, because if - we change the attributes of the target type the pointer - type needs to have a different TYPE_MAIN_VARIANT. So we - pull out the target type now, frob it as appropriate, and - rebuild the pointer type later. - - This would all be simpler if attributes were part of the - declarator, grumble grumble. */ - fn_ptr_tmp = TREE_TYPE (*anode); - fn_ptr_quals = TYPE_QUALS (*anode); - anode = &fn_ptr_tmp; - flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE; - } - else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT) - { - /* Pass on this attribute to be tried again. */ - returned_attrs = tree_cons (name, args, returned_attrs); - continue; - } - - if (TREE_CODE (*anode) != FUNCTION_TYPE - && TREE_CODE (*anode) != METHOD_TYPE) - { - warning (OPT_Wattributes, - "%qE attribute only applies to function types", - name); - continue; - } - } - - if (TYPE_P (*anode) - && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE) - && TYPE_SIZE (*anode) != NULL_TREE) - { - warning (OPT_Wattributes, "type attributes ignored after type is already defined"); + returned_attrs = finalize_type_attribute (anode, spec, a, + returned_attrs, flags, + node); continue; } - - if (spec->handler != NULL) + if (spec->decl_handler != NULL) { int cxx11_flag = cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0; - - returned_attrs = chainon ((*spec->handler) (anode, name, args, - flags|cxx11_flag, - &no_add_attrs), + returned_attrs = chainon ((*spec->decl_handler) (anode, name, args, + flags|cxx11_flag, + &no_add_attrs), returned_attrs); } - /* Layout the decl in case anything changed. */ - if (spec->type_required && DECL_P (*node) - && (TREE_CODE (*node) == VAR_DECL - || TREE_CODE (*node) == PARM_DECL - || TREE_CODE (*node) == RESULT_DECL)) - relayout_decl (*node); - if (!no_add_attrs) { tree old_attrs; tree a; - if (DECL_P (*anode)) - old_attrs = DECL_ATTRIBUTES (*anode); - else - old_attrs = TYPE_ATTRIBUTES (*anode); + old_attrs = DECL_ATTRIBUTES (*anode); for (a = lookup_attribute (spec->name, old_attrs); a != NULL_TREE; @@ -588,55 +735,11 @@ decl_attributes (tree *node, tree attributes, int flags) } if (a == NULL_TREE) - { - /* This attribute isn't already in the list. */ - if (DECL_P (*anode)) - DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs); - else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE) - { - TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs); - /* If this is the main variant, also push the attributes - out to the other variants. */ - if (*anode == TYPE_MAIN_VARIANT (*anode)) - { - tree variant; - for (variant = *anode; variant; - variant = TYPE_NEXT_VARIANT (variant)) - { - if (TYPE_ATTRIBUTES (variant) == old_attrs) - TYPE_ATTRIBUTES (variant) - = TYPE_ATTRIBUTES (*anode); - else if (!lookup_attribute - (spec->name, TYPE_ATTRIBUTES (variant))) - TYPE_ATTRIBUTES (variant) = tree_cons - (name, args, TYPE_ATTRIBUTES (variant)); - } - } - } - else - *anode = build_type_attribute_variant (*anode, - tree_cons (name, args, - old_attrs)); - } + /* This attribute isn't already in the list. */ + DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs); } - if (fn_ptr_tmp) - { - /* Rebuild the function pointer type and put it in the - appropriate place. */ - fn_ptr_tmp = build_pointer_type (fn_ptr_tmp); - if (fn_ptr_quals) - fn_ptr_tmp = build_qualified_type (fn_ptr_tmp, fn_ptr_quals); - if (DECL_P (*node)) - TREE_TYPE (*node) = fn_ptr_tmp; - else - { - gcc_assert (TREE_CODE (*node) == POINTER_TYPE); - *node = fn_ptr_tmp; - } - } } - return returned_attrs; } @@ -681,5 +784,5 @@ get_attribute_name (const_tree attr) void apply_tm_attr (tree fndecl, tree attr) { - decl_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0); + type_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0); } diff --git a/gcc/attribs.h b/gcc/attribs.h index 421110d1ee3..6d9b99b69b7 100644 --- a/gcc/attribs.h +++ b/gcc/attribs.h @@ -31,6 +31,7 @@ extern void init_attributes (void); from tree.h. Depending on these flags, some attributes may be returned to be applied at a later stage (for example, to apply a decl attribute to the declaration rather than to its type). */ +extern tree type_attributes (tree *, tree, int); extern tree decl_attributes (tree *, tree, int); extern bool cxx11_attribute_p (const_tree); diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 1066c6b96a7..3f12cadf2cd 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -312,7 +312,8 @@ static tree c_fully_fold_internal (tree expr, bool, bool *, bool *); static tree check_case_value (location_t, tree); static bool check_case_bounds (location_t, tree, tree, tree *, tree *); -static tree handle_packed_attribute (tree *, tree, tree, int, bool *); +static tree handle_packed_decl_attribute (tree *, tree, tree, int, bool *); +static tree handle_packed_type_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 *); @@ -334,26 +335,32 @@ static tree handle_artificial_attribute (tree *, tree, tree, int, bool *); static tree handle_flatten_attribute (tree *, tree, tree, int, bool *); static tree handle_error_attribute (tree *, tree, tree, int, bool *); static tree handle_used_attribute (tree *, tree, tree, int, bool *); -static tree handle_unused_attribute (tree *, tree, tree, int, bool *); +static tree handle_unused_decl_attribute (tree *, tree, tree, int, bool *); +static tree handle_unused_type_attribute (tree *, tree, tree, int, bool *); static tree handle_externally_visible_attribute (tree *, tree, tree, int, bool *); static tree handle_no_reorder_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_transparent_union_decl_attribute (tree *, tree, tree, + int, bool *); +static tree handle_transparent_union_type_attribute (tree *, tree, tree, + int, bool *); static tree handle_constructor_attribute (tree *, tree, tree, int, bool *); static tree handle_destructor_attribute (tree *, tree, tree, int, bool *); static tree handle_mode_attribute (tree *, tree, tree, int, bool *); static tree handle_section_attribute (tree *, tree, tree, int, bool *); -static tree handle_aligned_attribute (tree *, tree, tree, int, bool *); +static tree handle_aligned_type_attribute (tree *, tree, tree, int, bool *); +static tree handle_aligned_decl_attribute (tree *, tree, tree, int, bool *); static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ; static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *); static tree handle_ifunc_attribute (tree *, tree, tree, int, bool *); static tree handle_alias_attribute (tree *, tree, tree, int, bool *); static tree handle_weakref_attribute (tree *, tree, tree, int, bool *) ; -static tree handle_visibility_attribute (tree *, tree, tree, int, - bool *); +static tree handle_visibility_decl_attribute (tree *, tree, tree, int, + bool *); +static tree handle_visibility_type_attribute (tree *, tree, tree, int, + bool *); static tree handle_tls_model_attribute (tree *, tree, tree, int, bool *); static tree handle_no_instrument_function_attribute (tree *, tree, @@ -366,8 +373,10 @@ static tree handle_pure_attribute (tree *, tree, tree, int, bool *); static tree handle_tm_attribute (tree *, tree, tree, int, bool *); static tree handle_tm_wrap_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_deprecated_type_attribute (tree *, tree, tree, int, + bool *); +static tree handle_deprecated_decl_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 *); @@ -385,7 +394,8 @@ static tree handle_optimize_attribute (tree *, tree, tree, int, bool *); static tree ignore_attribute (tree *, tree, tree, int, bool *); static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *); static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *); -static tree handle_warn_unused_attribute (tree *, tree, tree, int, bool *); +static tree handle_warn_unused_decl_attribute (tree *, tree, tree, int, bool *); +static tree handle_warn_unused_type_attribute (tree *, tree, tree, int, bool *); static tree handle_returns_nonnull_attribute (tree *, tree, tree, int, bool *); static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); @@ -637,177 +647,186 @@ const unsigned int num_c_common_reswords = Current list of processed common attributes: nonnull. */ const struct attribute_spec c_common_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ { "packed", 0, 0, false, false, false, - handle_packed_attribute , false}, + handle_packed_decl_attribute, + handle_packed_type_attribute, false}, { "nocommon", 0, 0, true, false, false, - handle_nocommon_attribute, false}, + handle_nocommon_attribute, NULL, false}, { "common", 0, 0, true, false, false, - handle_common_attribute, false }, + handle_common_attribute, NULL, false }, /* 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, false }, + handle_noreturn_attribute, NULL, false }, { "volatile", 0, 0, true, false, false, - handle_noreturn_attribute, false }, + handle_noreturn_attribute, NULL, false }, { "noinline", 0, 0, true, false, false, - handle_noinline_attribute, false }, + handle_noinline_attribute, NULL, false }, { "noclone", 0, 0, true, false, false, - handle_noclone_attribute, false }, + handle_noclone_attribute, NULL, false }, { "leaf", 0, 0, true, false, false, - handle_leaf_attribute, false }, + handle_leaf_attribute, NULL, false }, { "always_inline", 0, 0, true, false, false, - handle_always_inline_attribute, false }, + handle_always_inline_attribute, NULL, false }, { "gnu_inline", 0, 0, true, false, false, - handle_gnu_inline_attribute, false }, + handle_gnu_inline_attribute, NULL, false }, { "artificial", 0, 0, true, false, false, - handle_artificial_attribute, false }, + handle_artificial_attribute, NULL, false }, { "flatten", 0, 0, true, false, false, - handle_flatten_attribute, false }, + handle_flatten_attribute, NULL, false }, { "used", 0, 0, true, false, false, - handle_used_attribute, false }, + handle_used_attribute, NULL, false }, { "unused", 0, 0, false, false, false, - handle_unused_attribute, false }, + handle_unused_decl_attribute, + handle_unused_type_attribute, false }, { "externally_visible", 0, 0, true, false, false, - handle_externally_visible_attribute, false }, + handle_externally_visible_attribute, NULL, + false }, { "no_reorder", 0, 0, true, false, false, - handle_no_reorder_attribute, false }, + handle_no_reorder_attribute, NULL, false }, /* The same comments as for noreturn attributes apply to const ones. */ { "const", 0, 0, true, false, false, - handle_const_attribute, false }, + handle_const_attribute, NULL, false }, { "transparent_union", 0, 0, false, false, false, - handle_transparent_union_attribute, false }, + handle_transparent_union_decl_attribute, + handle_transparent_union_type_attribute, false }, { "constructor", 0, 1, true, false, false, - handle_constructor_attribute, false }, + handle_constructor_attribute, NULL, false }, { "destructor", 0, 1, true, false, false, - handle_destructor_attribute, false }, - { "mode", 1, 1, false, true, false, + handle_destructor_attribute, NULL, false }, + { "mode", 1, 1, false, true, false, NULL, handle_mode_attribute, false }, { "section", 1, 1, true, false, false, - handle_section_attribute, false }, + handle_section_attribute, NULL, false }, { "aligned", 0, 1, false, false, false, - handle_aligned_attribute, false }, + handle_aligned_decl_attribute, + handle_aligned_type_attribute, false }, { "weak", 0, 0, true, false, false, - handle_weak_attribute, false }, + handle_weak_attribute, NULL, false }, { "ifunc", 1, 1, true, false, false, - handle_ifunc_attribute, false }, + handle_ifunc_attribute, NULL, false }, { "alias", 1, 1, true, false, false, - handle_alias_attribute, false }, + handle_alias_attribute, NULL, false }, { "weakref", 0, 1, true, false, false, - handle_weakref_attribute, false }, + handle_weakref_attribute, NULL, false }, { "no_instrument_function", 0, 0, true, false, false, handle_no_instrument_function_attribute, - false }, + NULL, false }, { "malloc", 0, 0, true, false, false, - handle_malloc_attribute, false }, + handle_malloc_attribute, NULL, false }, { "returns_twice", 0, 0, true, false, false, - handle_returns_twice_attribute, false }, + handle_returns_twice_attribute, NULL, false }, { "no_stack_limit", 0, 0, true, false, false, - handle_no_limit_stack_attribute, false }, + handle_no_limit_stack_attribute, NULL, false }, { "pure", 0, 0, true, false, false, - handle_pure_attribute, false }, - { "transaction_callable", 0, 0, false, true, false, + handle_pure_attribute, NULL, false }, + { "transaction_callable", 0, 0, false, true, false, NULL, handle_tm_attribute, false }, { "transaction_unsafe", 0, 0, false, true, false, - handle_tm_attribute, false }, + NULL, handle_tm_attribute, false }, { "transaction_safe", 0, 0, false, true, false, - handle_tm_attribute, false }, + NULL, handle_tm_attribute, false }, { "transaction_may_cancel_outer", 0, 0, false, true, false, - handle_tm_attribute, false }, + NULL, handle_tm_attribute, false }, /* ??? These two attributes didn't make the transition from the Intel language document to the multi-vendor language document. */ { "transaction_pure", 0, 0, false, true, false, - handle_tm_attribute, false }, + NULL, handle_tm_attribute, false }, { "transaction_wrap", 1, 1, true, false, false, - handle_tm_wrap_attribute, false }, + handle_tm_wrap_attribute, NULL, false }, /* 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, false }, + handle_novops_attribute, NULL, false }, { "deprecated", 0, 1, false, false, false, - handle_deprecated_attribute, false }, + handle_deprecated_decl_attribute, + handle_deprecated_type_attribute, false }, { "vector_size", 1, 1, false, true, false, - handle_vector_size_attribute, false }, + NULL, handle_vector_size_attribute, false }, { "visibility", 1, 1, false, false, false, - handle_visibility_attribute, false }, + handle_visibility_decl_attribute, + handle_visibility_type_attribute, false }, { "tls_model", 1, 1, true, false, false, - handle_tls_model_attribute, false }, + handle_tls_model_attribute, NULL, false }, { "nonnull", 0, -1, false, true, true, - handle_nonnull_attribute, false }, + NULL, handle_nonnull_attribute, false }, { "nothrow", 0, 0, true, false, false, - handle_nothrow_attribute, false }, - { "may_alias", 0, 0, false, true, false, NULL, false }, + handle_nothrow_attribute, NULL, false }, + { "may_alias", 0, 0, false, true, false, NULL, NULL, false }, { "cleanup", 1, 1, true, false, false, - handle_cleanup_attribute, false }, - { "warn_unused_result", 0, 0, false, true, true, + handle_cleanup_attribute, NULL, false }, + { "warn_unused_result", 0, 0, false, true, true, NULL, handle_warn_unused_result_attribute, false }, { "sentinel", 0, 1, false, true, true, - handle_sentinel_attribute, false }, + NULL, handle_sentinel_attribute, false }, /* 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, false }, + NULL, handle_type_generic_attribute, false }, { "alloc_size", 1, 2, false, true, true, - handle_alloc_size_attribute, false }, + NULL, handle_alloc_size_attribute, false }, { "cold", 0, 0, true, false, false, - handle_cold_attribute, false }, + handle_cold_attribute, NULL, false }, { "hot", 0, 0, true, false, false, - handle_hot_attribute, false }, + handle_hot_attribute, NULL, false }, { "no_address_safety_analysis", 0, 0, true, false, false, handle_no_address_safety_analysis_attribute, - false }, + NULL, false }, { "no_sanitize_address", 0, 0, true, false, false, handle_no_sanitize_address_attribute, - false }, + NULL, false }, { "no_sanitize_undefined", 0, 0, true, false, false, handle_no_sanitize_undefined_attribute, - false }, + NULL, false }, { "warning", 1, 1, true, false, false, - handle_error_attribute, false }, + handle_error_attribute, NULL, false }, { "error", 1, 1, true, false, false, - handle_error_attribute, false }, + handle_error_attribute, NULL, false }, { "target", 1, -1, true, false, false, - handle_target_attribute, false }, + handle_target_attribute, NULL, false }, { "optimize", 1, -1, true, false, false, - handle_optimize_attribute, false }, + handle_optimize_attribute, NULL, 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, ignore_attribute, false }, { "no_split_stack", 0, 0, true, false, false, - handle_no_split_stack_attribute, false }, + handle_no_split_stack_attribute, NULL, false }, /* For internal use (marking of builtins and runtime functions) only. The name contains space to prevent its usage in source code. */ { "fn spec", 1, 1, false, true, true, - handle_fnspec_attribute, false }, + NULL, handle_fnspec_attribute, false }, { "warn_unused", 0, 0, false, false, false, - handle_warn_unused_attribute, false }, + handle_warn_unused_decl_attribute, + handle_warn_unused_type_attribute, false }, { "returns_nonnull", 0, 0, false, true, true, - handle_returns_nonnull_attribute, false }, + NULL, handle_returns_nonnull_attribute, false }, { "omp declare simd", 0, -1, true, false, false, - handle_omp_declare_simd_attribute, false }, + handle_omp_declare_simd_attribute, NULL, false }, { "cilk simd function", 0, -1, true, false, false, - handle_omp_declare_simd_attribute, false }, + handle_omp_declare_simd_attribute, NULL, false }, { "omp declare target", 0, 0, true, false, false, - handle_omp_declare_target_attribute, false }, + handle_omp_declare_target_attribute, NULL, + false }, { "alloc_align", 1, 1, false, true, true, - handle_alloc_align_attribute, false }, + NULL, handle_alloc_align_attribute, false }, { "assume_aligned", 1, 2, false, true, true, - handle_assume_aligned_attribute, false }, + NULL, handle_assume_aligned_attribute, false }, { "designated_init", 0, 0, false, true, false, - handle_designated_init_attribute, false }, + NULL, handle_designated_init_attribute, false }, { "bnd_variable_size", 0, 0, true, false, false, - handle_bnd_variable_size_attribute, false }, + handle_bnd_variable_size_attribute, NULL, false }, { "bnd_legacy", 0, 0, true, false, false, - handle_bnd_legacy, false }, + handle_bnd_legacy, NULL, false }, { "bnd_instrument", 0, 0, true, false, false, - handle_bnd_instrument, false }, - { NULL, 0, 0, false, false, false, NULL, false } + handle_bnd_instrument, NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Give the specifications for the format attributes, used by C and all @@ -822,10 +841,10 @@ const struct attribute_spec c_common_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 }, + NULL, handle_format_attribute, false }, { "format_arg", 1, 1, false, true, true, - handle_format_arg_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } + NULL, handle_format_arg_attribute, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Return identifier for address space AS. */ @@ -6547,16 +6566,10 @@ attribute_takes_identifier_p (const_tree attr_id) struct attribute_spec.handler. */ static tree -handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args), - int flags, bool *no_add_attrs) +handle_packed_decl_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) { - if (TYPE_P (*node)) - { - if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) - *node = build_variant_type_copy (*node); - TYPE_PACKED (*node) = 1; - } - else if (TREE_CODE (*node) == FIELD_DECL) + if (TREE_CODE (*node) == FIELD_DECL) { if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT /* Still pack bitfields. */ @@ -6580,6 +6593,18 @@ handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args), return NULL_TREE; } +static tree +handle_packed_type_attribute (tree *node, tree ARG_UNUSED (name), + tree ARG_UNUSED (args), + int flags, bool *ARG_UNUSED (no_add_attrs)) +{ + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_variant_type_copy (*node); + TYPE_PACKED (*node) = 1; + + return NULL_TREE; +} + /* Handle a "nocommon" attribute; arguments as in struct attribute_spec.handler. */ @@ -6967,38 +6992,40 @@ handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args), /* Handle a "unused" attribute; arguments as in struct attribute_spec.handler. */ - static tree -handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args), - int flags, bool *no_add_attrs) +handle_unused_decl_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) { - if (DECL_P (*node)) - { - tree decl = *node; + tree decl = *node; - if (TREE_CODE (decl) == PARM_DECL - || TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == FUNCTION_DECL - || TREE_CODE (decl) == LABEL_DECL - || TREE_CODE (decl) == TYPE_DECL) - { - TREE_USED (decl) = 1; - if (TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == PARM_DECL) - DECL_READ_P (decl) = 1; - } - else - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } + if (TREE_CODE (decl) == PARM_DECL + || TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == LABEL_DECL + || TREE_CODE (decl) == TYPE_DECL) + { + TREE_USED (decl) = 1; + if (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == PARM_DECL) + DECL_READ_P (decl) = 1; } else { - if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) - *node = build_variant_type_copy (*node); - TREE_USED (*node) = 1; + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; } + return NULL_TREE; +} + + +static tree +handle_unused_type_attribute (tree *node, tree ARG_UNUSED (name), + tree ARG_UNUSED (args), int flags, + bool *ARG_UNUSED (no_add_attrs)) +{ + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_variant_type_copy (*node); + TREE_USED (*node) = 1; return NULL_TREE; } @@ -7090,20 +7117,13 @@ handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args), struct attribute_spec.handler. */ static tree -handle_transparent_union_attribute (tree *node, tree name, - tree ARG_UNUSED (args), int flags, - bool *no_add_attrs) +handle_transparent_union_type_attribute (tree *node, tree name, + tree ARG_UNUSED (args), int flags, + bool *no_add_attrs) { - tree type; - + tree type = *node; *no_add_attrs = true; - - if (TREE_CODE (*node) == TYPE_DECL - && ! (flags & ATTR_FLAG_CXX11)) - node = &TREE_TYPE (*node); - type = *node; - if (TREE_CODE (type) == UNION_TYPE) { /* Make sure that the first field will work for a transparent union. @@ -7143,6 +7163,21 @@ handle_transparent_union_attribute (tree *node, tree name, return NULL_TREE; } + +static tree +handle_transparent_union_decl_attribute (tree *node, tree name, tree args, + int flags, bool *no_add_attrs) +{ + *no_add_attrs = true; + + if (TREE_CODE (*node) == TYPE_DECL && !(flags & ATTR_FLAG_CXX11)) + return handle_transparent_union_type_attribute (&TREE_TYPE (*node), name, + args, flags, no_add_attrs); + + warning (OPT_Wattributes, "%qE attribute ignored", name); + return NULL_TREE; +} + /* Subroutine of handle_{con,de}structor_attribute. Evaluate ARGS to get the requested priority for a constructor or destructor, possibly issuing diagnostics for invalid or reserved @@ -7663,18 +7698,12 @@ check_cxx_fundamental_alignment_constraints (tree node, return !alignment_too_large_p; } -/* Handle a "aligned" attribute; arguments as in - struct attribute_spec.handler. */ +/* Return the alignment expression from tree_list element ARGS. */ static tree -handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, - int flags, bool *no_add_attrs) +get_align_expr (tree args) { - tree decl = NULL_TREE; - tree *type = NULL; - int is_type = 0; tree align_expr; - int i; if (args) { @@ -7686,40 +7715,60 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, else align_expr = size_int (ATTRIBUTE_ALIGNED_VALUE / BITS_PER_UNIT); - if (DECL_P (*node)) - { - decl = *node; - type = &TREE_TYPE (decl); - is_type = TREE_CODE (*node) == TYPE_DECL; - } - else if (TYPE_P (*node)) - type = node, is_type = 1; + return align_expr; +} + +/* Set the type alignment fields of NODE, based on FLAGS to I. */ + +static void +handle_aligned_type (tree *node, int flags, int i) +{ + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_variant_type_copy (*node); + + TYPE_ALIGN (*node) = (1U << i) * BITS_PER_UNIT; + TYPE_USER_ALIGN (*node) = 1; +} + +/* Handle a "aligned" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_aligned_type_attribute (tree *node, tree ARG_UNUSED (name), tree args, + int flags, bool *no_add_attrs) +{ + tree align_expr; + int i; + + align_expr = get_align_expr (args); if ((i = check_user_alignment (align_expr, false)) == -1 || !check_cxx_fundamental_alignment_constraints (*node, i, flags)) *no_add_attrs = true; - else if (is_type) - { - if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) - /* OK, modify the type in place. */; - /* If we have a TYPE_DECL, then copy the type, so that we - don't accidentally modify a builtin type. See pushdecl. */ - else if (decl && TREE_TYPE (decl) != error_mark_node - && DECL_ORIGINAL_TYPE (decl) == NULL_TREE) - { - tree tt = TREE_TYPE (decl); - *type = build_variant_type_copy (*type); - DECL_ORIGINAL_TYPE (decl) = tt; - TYPE_NAME (*type) = decl; - TREE_USED (*type) = TREE_USED (decl); - TREE_TYPE (decl) = *type; - } - else - *type = build_variant_type_copy (*type); + else + handle_aligned_type (node, flags, i); + + return NULL_TREE; +} + + +static tree +handle_aligned_decl_attribute (tree *node, tree ARG_UNUSED (name), tree args, + int flags, bool *no_add_attrs) +{ + tree align_expr; + tree decl = *node; + int i; - TYPE_ALIGN (*type) = (1U << i) * BITS_PER_UNIT; - TYPE_USER_ALIGN (*type) = 1; + align_expr = get_align_expr (args); + + if ((i = check_user_alignment (align_expr, false)) == -1 + || !check_cxx_fundamental_alignment_constraints (*node, i, flags)) + { + *no_add_attrs = true; } + else if (TREE_CODE (*node) == TYPE_DECL) + handle_aligned_type (&TREE_TYPE (*node), flags, i); else if (! VAR_OR_FUNCTION_DECL_P (decl) && TREE_CODE (decl) != FIELD_DECL) { @@ -7965,61 +8014,13 @@ handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args, return NULL_TREE; } -/* Handle an "visibility" attribute; arguments as in - struct attribute_spec.handler. */ +/* Process the DECL common parts of handle_visibility_attribute. */ -static tree -handle_visibility_attribute (tree *node, tree name, tree args, - int ARG_UNUSED (flags), - bool *ARG_UNUSED (no_add_attrs)) +static void +handle_decl_visibility (tree decl, tree id, tree attributes) { - tree decl = *node; - tree id = TREE_VALUE (args); enum symbol_visibility vis; - if (TYPE_P (*node)) - { - if (TREE_CODE (*node) == ENUMERAL_TYPE) - /* OK */; - else if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE) - { - warning (OPT_Wattributes, "%qE attribute ignored on non-class types", - name); - return NULL_TREE; - } - else if (TYPE_FIELDS (*node)) - { - error ("%qE attribute ignored because %qT is already defined", - name, *node); - return NULL_TREE; - } - } - else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl)) - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - return NULL_TREE; - } - - if (TREE_CODE (id) != STRING_CST) - { - error ("visibility argument not a string"); - return NULL_TREE; - } - - /* If this is a type, set the visibility on the type decl. */ - if (TYPE_P (decl)) - { - decl = TYPE_NAME (decl); - if (!decl) - return NULL_TREE; - if (TREE_CODE (decl) == IDENTIFIER_NODE) - { - warning (OPT_Wattributes, "%qE attribute ignored on types", - name); - return NULL_TREE; - } - } - if (strcmp (TREE_STRING_POINTER (id), "default") == 0) vis = VISIBILITY_DEFAULT; else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0) @@ -8037,9 +8038,6 @@ handle_visibility_attribute (tree *node, tree name, tree args, if (DECL_VISIBILITY_SPECIFIED (decl) && vis != DECL_VISIBILITY (decl)) { - tree attributes = (TYPE_P (*node) - ? TYPE_ATTRIBUTES (*node) - : DECL_ATTRIBUTES (decl)); if (lookup_attribute ("visibility", attributes)) error ("%qD redeclared with different visibility", decl); else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES @@ -8054,6 +8052,81 @@ handle_visibility_attribute (tree *node, tree name, tree args, DECL_VISIBILITY (decl) = vis; DECL_VISIBILITY_SPECIFIED (decl) = 1; +} + +/* Handle an "visibility" attribute; arguments as in + struct attribute_spec.handler. */ +static tree +handle_visibility_decl_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), + bool *ARG_UNUSED (no_add_attrs)) +{ + tree decl = *node; + tree id = TREE_VALUE (args); + + if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl)) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + return NULL_TREE; + } + + if (TREE_CODE (id) != STRING_CST) + { + error ("visibility argument not a string"); + return NULL_TREE; + } + + handle_decl_visibility (decl, id, DECL_ATTRIBUTES (decl)); + /* Go ahead and attach the attribute to the node as well. This is needed + so we can determine whether we have VISIBILITY_DEFAULT because the + visibility was not specified, or because it was explicitly overridden + from the containing scope. */ + + return NULL_TREE; +} + + +static tree +handle_visibility_type_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), + bool *ARG_UNUSED (no_add_attrs)) +{ + tree decl; + tree id = TREE_VALUE (args); + + if (TREE_CODE (*node) == ENUMERAL_TYPE) + /* OK */; + else if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE) + { + warning (OPT_Wattributes, "%qE attribute ignored on non-class types", + name); + return NULL_TREE; + } + else if (TYPE_FIELDS (*node)) + { + error ("%qE attribute ignored because %qT is already defined", + name, *node); + return NULL_TREE; + } + + if (TREE_CODE (id) != STRING_CST) + { + error ("visibility argument not a string"); + return NULL_TREE; + } + + decl = TYPE_NAME (*node); + if (!decl) + return NULL_TREE; + + if (TREE_CODE (decl) == IDENTIFIER_NODE) + { + warning (OPT_Wattributes, "%qE attribute ignored on types", + name); + return NULL_TREE; + } + + handle_decl_visibility (decl, id, TYPE_ATTRIBUTES (*node)); /* Go ahead and attach the attribute to the node as well. This is needed so we can determine whether we have VISIBILITY_DEFAULT because the @@ -8278,7 +8351,7 @@ 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 + gcc_assert (TYPE_P (*node) && args && TREE_CODE (TREE_VALUE (args)) == STRING_CST && !TREE_CHAIN (args)); return NULL_TREE; @@ -8336,20 +8409,26 @@ handle_bnd_instrument (tree *node, tree name, tree ARG_UNUSED (args), struct attribute_spec.handler. */ static tree -handle_warn_unused_attribute (tree *node, tree name, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) -{ - if (TYPE_P (*node)) - /* Do nothing else, just set the attribute. We'll get at - it later with lookup_attribute. */ - ; - else - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } +handle_warn_unused_type_attribute (tree *node ATTRIBUTE_UNUSED, + tree name ATTRIBUTE_UNUSED, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs ATTRIBUTE_UNUSED) +{ + /* Do nothing else, just set the attribute. We'll get at + it later with lookup_attribute. */ + return NULL_TREE; +} +static tree +handle_warn_unused_decl_attribute (tree *node ATTRIBUTE_UNUSED, + tree name ATTRIBUTE_UNUSED, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs ATTRIBUTE_UNUSED) +{ + /* Do nothing else, just set the attribute. We'll get at + it later with lookup_attribute. */ return NULL_TREE; } @@ -8580,7 +8659,7 @@ handle_tm_attribute (tree *node, tree name, tree args, if (subcode == FUNCTION_TYPE || subcode == METHOD_TYPE) { tree fn_tmp = TREE_TYPE (*node); - decl_attributes (&fn_tmp, tree_cons (name, args, NULL), 0); + type_attributes (&fn_tmp, tree_cons (name, args, NULL), 0); *node = build_pointer_type (fn_tmp); break; } @@ -8673,14 +8752,10 @@ handle_novops_attribute (tree *node, tree ARG_UNUSED (name), struct attribute_spec.handler. */ static tree -handle_deprecated_attribute (tree *node, tree name, - tree args, int flags, - bool *no_add_attrs) +handle_deprecated_type_attribute (tree *node, tree ARG_UNUSED (name), + tree args, int flags, + bool *no_add_attrs) { - tree type = NULL_TREE; - int warn = 0; - tree what = NULL_TREE; - if (!args) *no_add_attrs = true; else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) @@ -8689,33 +8764,40 @@ handle_deprecated_attribute (tree *node, tree name, *no_add_attrs = true; } - if (DECL_P (*node)) - { - tree decl = *node; - type = TREE_TYPE (decl); + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_variant_type_copy (*node); + TREE_DEPRECATED (*node) = 1; - if (TREE_CODE (decl) == TYPE_DECL - || TREE_CODE (decl) == PARM_DECL - || TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == FUNCTION_DECL - || TREE_CODE (decl) == FIELD_DECL - || objc_method_decl (TREE_CODE (decl))) - TREE_DEPRECATED (decl) = 1; - else - warn = 1; - } - else if (TYPE_P (*node)) + return NULL_TREE; +} + + +static tree +handle_deprecated_decl_attribute (tree *node, tree name, + tree args, int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + tree decl = *node; + tree what = NULL_TREE; + + if (!args) + *no_add_attrs = true; + else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) { - if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) - *node = build_variant_type_copy (*node); - TREE_DEPRECATED (*node) = 1; - type = *node; + error ("deprecated message is not a string"); + *no_add_attrs = true; } - else - warn = 1; - if (warn) + if (TREE_CODE (decl) == TYPE_DECL + || TREE_CODE (decl) == PARM_DECL + || TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == FIELD_DECL + || objc_method_decl (TREE_CODE (decl))) + TREE_DEPRECATED (decl) = 1; + else { + tree type = TREE_TYPE (decl); *no_add_attrs = true; if (type && TYPE_NAME (type)) { diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 6413e6f8f35..609d8891ffc 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -4383,7 +4383,7 @@ groktypename (struct c_type_name *type_name, tree *expr, DEPRECATED_NORMAL); /* Apply attributes. */ - decl_attributes (&type, attrs, 0); + type_attributes (&type, attrs, 0); return type; } @@ -5691,7 +5691,7 @@ grokdeclarator (const struct c_declarator *declarator, attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT; else if (inner_decl->kind == cdk_array) attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT; - returned_attrs = decl_attributes (&type, + returned_attrs = type_attributes (&type, chainon (returned_attrs, attrs), attr_flags); break; @@ -7576,7 +7576,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, TYPE_SIZE (t) = 0; - decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); + type_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); if (pedantic) { @@ -7949,7 +7949,7 @@ finish_enum (tree enumtype, tree values, tree attributes) bool toplevel = (file_scope == current_scope); struct lang_type *lt; - decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); + type_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); /* Calculate the maximum value of any enumerator in this type. */ diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index afcede9c736..a6b6ee4a554 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -7539,10 +7539,11 @@ common_object_handler (tree *node, tree name ATTRIBUTE_UNUSED, static const struct attribute_spec vms_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ - { COMMON_OBJECT, 0, 1, true, false, false, common_object_handler, false }, - { NULL, 0, 0, false, false, false, NULL, false } + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ + { COMMON_OBJECT, 0, 1, true, false, false, common_object_handler, NULL, + false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; void diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 764f7366c9a..20e26304923 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -366,20 +366,21 @@ static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *); machine specific supported attributes. */ const struct attribute_spec arc_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ - { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute, true }, + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ + { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute, + NULL, true }, /* Function calls made to this symbol must be done indirectly, because it may lie outside of the 21/25 bit addressing range of a normal function call. */ - { "long_call", 0, 0, false, true, true, NULL, false }, + { "long_call", 0, 0, false, true, true, NULL, NULL, false }, /* Whereas these functions are always known to reside within the 25 bit addressing range of unconditionalized bl. */ - { "medium_call", 0, 0, false, true, true, NULL, false }, + { "medium_call", 0, 0, false, true, true, NULL, NULL, false }, /* And these functions are always known to reside within the 21 bit addressing range of blcc. */ - { "short_call", 0, 0, false, true, true, NULL, false }, - { NULL, 0, 0, false, false, false, NULL, false } + { "short_call", 0, 0, false, true, true, NULL, NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; static int arc_comp_type_attributes (const_tree, const_tree); static void arc_file_start (void); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 0ec526b73ad..d5cd994c4fb 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -149,7 +149,8 @@ static unsigned long arm_isr_value (tree); static unsigned long arm_compute_func_type (void); static tree arm_handle_fndecl_attribute (tree *, tree, tree, int, bool *); static tree arm_handle_pcs_attribute (tree *, tree, tree, int, bool *); -static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *); +static tree arm_handle_isr_decl_attribute (tree *, tree, tree, int, bool *); +static tree arm_handle_isr_type_attribute (tree *, tree, tree, int, bool *); #if TARGET_DLLIMPORT_DECL_ATTRIBUTES static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *); #endif @@ -309,25 +310,26 @@ static void arm_sched_fusion_priority (rtx_insn *, int, int *, int*); /* Table of machine attributes. */ static const struct attribute_spec arm_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handle, affects_type_identity } */ /* Function calls made to this symbol must be done indirectly, because it may lie outside of the 26 bit addressing range of a normal function call. */ - { "long_call", 0, 0, false, true, true, NULL, false }, + { "long_call", 0, 0, false, true, true, NULL, NULL, false }, /* Whereas these functions are always known to reside within the 26 bit addressing range. */ - { "short_call", 0, 0, false, true, true, NULL, false }, + { "short_call", 0, 0, false, true, true, NULL, NULL, false }, /* Specify the procedure call conventions for a function. */ - { "pcs", 1, 1, false, true, true, arm_handle_pcs_attribute, + { "pcs", 1, 1, false, true, true, NULL, arm_handle_pcs_attribute, false }, /* Interrupt Service Routines have special prologue and epilogue requirements. */ - { "isr", 0, 1, false, false, false, arm_handle_isr_attribute, - false }, - { "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute, + { "isr", 0, 1, false, false, false, arm_handle_isr_decl_attribute, + arm_handle_isr_type_attribute, false }, + { "interrupt", 0, 1, false, false, false, arm_handle_isr_decl_attribute, + arm_handle_isr_type_attribute, false }, { "naked", 0, 0, true, false, false, arm_handle_fndecl_attribute, - false }, + NULL, false }, #ifdef ARM_PE /* ARM/PE has three new attributes: interfacearm - ? @@ -338,17 +340,19 @@ static const struct attribute_spec arm_attribute_table[] = them with spaces. We do NOT support this. Instead, use __declspec multiple times. */ - { "dllimport", 0, 0, true, false, false, NULL, false }, - { "dllexport", 0, 0, true, false, false, NULL, false }, + { "dllimport", 0, 0, true, false, false, NULL, NULL, false }, + { "dllexport", 0, 0, true, false, false, NULL, NULL, false }, { "interfacearm", 0, 0, true, false, false, arm_handle_fndecl_attribute, - false }, + NULL, false }, #elif TARGET_DLLIMPORT_DECL_ATTRIBUTES - { "dllimport", 0, 0, false, false, false, handle_dll_attribute, false }, - { "dllexport", 0, 0, false, false, false, handle_dll_attribute, false }, - { "notshared", 0, 0, false, true, false, arm_handle_notshared_attribute, - false }, + { "dllimport", 0, 0, false, false, false, handle_dll_decl_attribute, + handle_dll_type_attribute, false }, + { "dllexport", 0, 0, false, false, false, handle_dll_decl_attribute, + handle_dll_type_attribute, false }, + { "notshared", 0, 0, false, true, false, NULL, + arm_handle_notshared_attribute, false }, #endif - { NULL, 0, 0, false, false, false, NULL, false } + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Initialize the GCC target structure. */ @@ -6112,58 +6116,60 @@ arm_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, /* Handle an "interrupt" or "isr" attribute; arguments as in struct attribute_spec.handler. */ static tree -arm_handle_isr_attribute (tree *node, tree name, tree args, int flags, - bool *no_add_attrs) +arm_handle_isr_decl_attribute (tree *node, tree name, tree args, int flags, + bool *no_add_attrs) { - if (DECL_P (*node)) + if (TREE_CODE (*node) != FUNCTION_DECL) { - if (TREE_CODE (*node) != FUNCTION_DECL) + warning (OPT_Wattributes, "%qE attribute only applies to functions", + name); + *no_add_attrs = true; + } + /* FIXME: the argument if any is checked for type attributes; + should it be checked for decl ones? */ + + return NULL_TREE; +} + +static tree +arm_handle_isr_type_attribute (tree *node, tree name, tree args, int flags, + bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_TYPE + || TREE_CODE (*node) == METHOD_TYPE) + { + if (arm_isr_value (args) == ARM_FT_UNKNOWN) { - warning (OPT_Wattributes, "%qE attribute only applies to functions", + warning (OPT_Wattributes, "%qE attribute ignored", name); *no_add_attrs = true; } - /* FIXME: the argument if any is checked for type attributes; - should it be checked for decl ones? */ + } + else if (TREE_CODE (*node) == POINTER_TYPE + && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE) + && arm_isr_value (args) != ARM_FT_UNKNOWN) + { + *node = build_variant_type_copy (*node); + TREE_TYPE (*node) = build_type_attribute_variant + (TREE_TYPE (*node), + tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node)))); + *no_add_attrs = true; } else { - if (TREE_CODE (*node) == FUNCTION_TYPE - || TREE_CODE (*node) == METHOD_TYPE) - { - if (arm_isr_value (args) == ARM_FT_UNKNOWN) - { - warning (OPT_Wattributes, "%qE attribute ignored", - name); - *no_add_attrs = true; - } - } - else if (TREE_CODE (*node) == POINTER_TYPE - && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE) - && arm_isr_value (args) != ARM_FT_UNKNOWN) + /* Possibly pass this attribute on from the type to a decl. */ + if (flags & ((int) ATTR_FLAG_DECL_NEXT + | (int) ATTR_FLAG_FUNCTION_NEXT + | (int) ATTR_FLAG_ARRAY_NEXT)) { - *node = build_variant_type_copy (*node); - TREE_TYPE (*node) = build_type_attribute_variant - (TREE_TYPE (*node), - tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node)))); *no_add_attrs = true; + return tree_cons (name, args, NULL_TREE); } else { - /* Possibly pass this attribute on from the type to a decl. */ - if (flags & ((int) ATTR_FLAG_DECL_NEXT - | (int) ATTR_FLAG_FUNCTION_NEXT - | (int) ATTR_FLAG_ARRAY_NEXT)) - { - *no_add_attrs = true; - return tree_cons (name, args, NULL_TREE); - } - else - { - warning (OPT_Wattributes, "%qE attribute ignored", - name); - } + warning (OPT_Wattributes, "%qE attribute ignored", + name); } } diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index bc83adb7c3f..dbf6152c0ff 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -8867,6 +8867,25 @@ avr_class_likely_spilled_p (reg_class_t c) naked - Don't generate function prologue/epilogue and RET instruction. */ +static tree +avr_ignore_type_attribute (tree *node ATTRIBUTE_UNUSED, + tree name ATTRIBUTE_UNUSED, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs ATTRIBUTE_UNUSED) +{ + return NULL_TREE; +} + +static tree +avr_warning_type_attribute (tree *node ATTRIBUTE_UNUSED, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + warning (OPT_Wattributes, "%qE attribute does not apply to types", + name); + *no_add_attrs = true; +} /* Handle a "progmem" attribute; arguments as in struct attribute_spec.handler. */ @@ -9026,27 +9045,29 @@ avr_eval_addr_attrib (rtx x) static const struct attribute_spec avr_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ - { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute, - false }, - { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute, - false }, - { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute, - false }, - { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute, - false }, - { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute, + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ + { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute, + avr_ignore_type_attribute, false }, - { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute, + { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute, + avr_warning_type_attribute, false }, + { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute, + avr_warning_type_attribute, false }, + { "naked", 0, 0, false, true, true, NULL, avr_handle_fntype_attribute, false }, - { "io", 0, 1, false, false, false, avr_handle_addr_attribute, + { "OS_task", 0, 0, false, true, true, NULL, avr_handle_fntype_attribute, false }, - { "io_low", 0, 1, false, false, false, avr_handle_addr_attribute, + { "OS_main", 0, 0, false, true, true, NULL, avr_handle_fntype_attribute, false }, - { "address", 1, 1, false, false, false, avr_handle_addr_attribute, + { "io", 0, 1, false, false, false, avr_handle_addr_attribute, + avr_warning_type_attribute, false }, + { "io_low", 0, 1, false, false, false, avr_handle_addr_attribute, + avr_warning_type_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } + { "address", 1, 1, false, false, false, avr_handle_addr_attribute, + avr_warning_type_attribute, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 4c9ce5733b2..319cbe14abc 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -4671,15 +4671,12 @@ bfin_reorg (void) attributes; arguments as in struct attribute_spec.handler. */ static tree -handle_int_attribute (tree *node, tree name, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs) +handle_int_type_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) { tree x = *node; - if (TREE_CODE (x) == FUNCTION_DECL) - x = TREE_TYPE (x); - if (TREE_CODE (x) != FUNCTION_TYPE) { warning (OPT_Wattributes, "%qE attribute only applies to functions", @@ -4692,6 +4689,21 @@ handle_int_attribute (tree *node, tree name, return NULL_TREE; } +static tree +handle_int_decl_attribute (tree *node, tree name, tree args, int flags, + bool *no_add_attrs) +{ + tree x = *node; + if (TREE_CODE (x) == FUNCTION_DECL) + return handle_int_type_attribute (&TREE_TYPE(x), name, args, flags, + no_add_attrs); + + warning (OPT_Wattributes, "%qE attribute only applies to functions", name); + *no_add_attrs = true; + + return NULL_TREE; +} + /* Return 0 if the attributes for two types are incompatible, 1 if they are compatible, and 2 if they are nearly compatible (which causes a warning to be generated). */ @@ -4739,9 +4751,7 @@ bfin_handle_longcall_attribute (tree *node, tree name, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) { - if (TREE_CODE (*node) != FUNCTION_TYPE - && TREE_CODE (*node) != FIELD_DECL - && TREE_CODE (*node) != TYPE_DECL) + if (TREE_CODE (*node) != FUNCTION_TYPE) { warning (OPT_Wattributes, "%qE attribute only applies to functions", name); @@ -4889,28 +4899,29 @@ static const struct attribute_spec bfin_attribute_table[] = { /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, affects_type_identity } */ - { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute, - false }, - { "exception_handler", 0, 0, false, true, true, handle_int_attribute, - false }, - { "nmi_handler", 0, 0, false, true, true, handle_int_attribute, false }, - { "nesting", 0, 0, false, true, true, NULL, false }, - { "kspisusp", 0, 0, false, true, true, NULL, false }, - { "saveall", 0, 0, false, true, true, NULL, false }, - { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute, - false }, - { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute, - false }, - { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute, + { "interrupt_handler", 0, 0, false, true, true, handle_int_decl_attribute, + handle_int_type_attribute, false }, + { "exception_handler", 0, 0, false, true, true, handle_int_decl_attribute, + handle_int_type_attribute, false }, + { "nmi_handler", 0, 0, false, true, true, handle_int_decl_attribute, + handle_int_type_attribute, false }, + { "nesting", 0, 0, false, true, true, NULL, NULL, false }, + { "kspisusp", 0, 0, false, true, true, NULL, NULL, false }, + { "saveall", 0, 0, false, true, true, NULL, NULL, false }, + { "longcall", 0, 0, false, true, true, NULL, + bfin_handle_longcall_attribute, false }, + { "shortcall", 0, 0, false, true, true, NULL, + bfin_handle_longcall_attribute, false }, + { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute, NULL, false }, - { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute, + { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute, NULL, false }, - { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute, + { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute, NULL, false }, - { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute, + { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute, NULL, false }, - { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } + { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute, NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to diff --git a/gcc/config/cr16/cr16.c b/gcc/config/cr16/cr16.c index be7d663721d..874675cf171 100644 --- a/gcc/config/cr16/cr16.c +++ b/gcc/config/cr16/cr16.c @@ -217,10 +217,10 @@ static void cr16_print_operand_address (FILE *, rtx); /* Table of machine attributes. */ static const struct attribute_spec cr16_attribute_table[] = { /* ISRs have special prologue and epilogue requirements. */ - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity }. */ - {"interrupt", 0, 0, false, true, true, NULL, false}, - {NULL, 0, 0, false, false, false, NULL, false} + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity }. */ + {"interrupt", 0, 0, false, true, true, NULL, NULL, false}, + {NULL, 0, 0, false, false, false, NULL, NULL, false} }; /* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index d973d1d2929..c01ae35cd0b 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -705,9 +705,9 @@ extern GTY(()) section * darwin_sections[NUM_DARWIN_SECTIONS]; /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, \ affects_type_identity } */ \ { "apple_kext_compatibility", 0, 0, false, true, false, \ - darwin_handle_kext_attribute, false }, \ + NULL, darwin_handle_kext_attribute, false }, \ { "weak_import", 0, 0, true, false, false, \ - darwin_handle_weak_import_attribute, false } + darwin_handle_weak_import_attribute, NULL, false } #undef ASM_GENERATE_INTERNAL_LABEL #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c index 92024aa91f6..65e01962fd1 100644 --- a/gcc/config/epiphany/epiphany.c +++ b/gcc/config/epiphany/epiphany.c @@ -469,13 +469,15 @@ epiphany_init_reg_tables (void) static const struct attribute_spec epiphany_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ - { "interrupt", 0, 9, true, false, false, epiphany_handle_interrupt_attribute, true }, - { "forwarder_section", 1, 1, true, false, false, epiphany_handle_forwarder_attribute, false }, - { "long_call", 0, 0, false, true, true, NULL, false }, - { "short_call", 0, 0, false, true, true, NULL, false }, - { "disinterrupt", 0, 0, false, true, true, NULL, true }, - { NULL, 0, 0, false, false, false, NULL, false } + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler } */ + { "interrupt", 0, 9, true, false, false, + epiphany_handle_interrupt_attribute, NULL, true }, + { "forwarder_section", 1, 1, true, false, false, epiphany_handle_forwarder_attribute, NULL, false }, + { "long_call", 0, 0, false, true, true, NULL, NULL, false }, + { "short_call", 0, 0, false, true, true, NULL, NULL, false }, + { "disinterrupt", 0, 0, false, true, true, NULL, NULL, true }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Handle an "interrupt" attribute; arguments as in diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index c9494260360..16e8acc78f9 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -5430,20 +5430,20 @@ static const struct attribute_spec h8300_attribute_table[] = /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, affects_type_identity } */ { "interrupt_handler", 0, 0, true, false, false, - h8300_handle_fndecl_attribute, false }, + h8300_handle_fndecl_attribute, NULL, false }, { "saveall", 0, 0, true, false, false, - h8300_handle_fndecl_attribute, false }, + h8300_handle_fndecl_attribute, NULL, false }, { "OS_Task", 0, 0, true, false, false, - h8300_handle_fndecl_attribute, false }, + h8300_handle_fndecl_attribute, NULL, false }, { "monitor", 0, 0, true, false, false, - h8300_handle_fndecl_attribute, false }, + h8300_handle_fndecl_attribute, NULL, false }, { "function_vector", 0, 0, true, false, false, - h8300_handle_fndecl_attribute, false }, + h8300_handle_fndecl_attribute, NULL, false }, { "eightbit_data", 0, 0, true, false, false, - h8300_handle_eightbit_data_attribute, false }, + h8300_handle_eightbit_data_attribute, NULL, false }, { "tiny_data", 0, 0, true, false, false, - h8300_handle_tiny_data_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } + h8300_handle_tiny_data_attribute, NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h index 95b8f6fb966..ec6e842e671 100644 --- a/gcc/config/i386/cygming.h +++ b/gcc/config/i386/cygming.h @@ -459,9 +459,9 @@ do { \ #define SUBTARGET_ATTRIBUTE_TABLE \ { "selectany", 0, 0, true, false, false, ix86_handle_selectany_attribute, \ - false } - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ + NULL, false } + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ /* mcount() does not need a counter variable. */ #undef NO_PROFILE_COUNTERS diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 122a350d99d..32762759dc3 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -5482,9 +5482,7 @@ ix86_handle_cconv_attribute (tree *node, tree name, bool *no_add_attrs) { if (TREE_CODE (*node) != FUNCTION_TYPE - && TREE_CODE (*node) != METHOD_TYPE - && TREE_CODE (*node) != FIELD_DECL - && TREE_CODE (*node) != TYPE_DECL) + && TREE_CODE (*node) != METHOD_TYPE) { warning (OPT_Wattributes, "%qE attribute only applies to functions", name); @@ -5643,7 +5641,10 @@ ix86_handle_tm_regparm_attribute (tree *node, tree, tree, alt = tree_cons (NULL, build_int_cst (NULL, 2), NULL); alt = tree_cons (get_identifier ("regparm"), alt, NULL); } - decl_attributes (node, alt, flags); + if (TYPE_P (*node)) + type_attributes (node, alt, flags); + else + decl_attributes (node, alt, flags); return NULL_TREE; } @@ -33440,7 +33441,7 @@ ix86_init_tm_builtins (void) attrs); /* add_builtin_function() will set the DECL_ATTRIBUTES, now set the TYPE_ATTRIBUTES. */ - decl_attributes (&TREE_TYPE (decl), attrs_type, ATTR_FLAG_BUILT_IN); + type_attributes (&TREE_TYPE (decl), attrs_type, ATTR_FLAG_BUILT_IN); set_builtin_decl (code, decl, false); } @@ -42605,22 +42606,12 @@ ix86_handle_abi_attribute (tree *node, tree name, tree, int, /* Handle a "ms_struct" or "gcc_struct" attribute; arguments as in struct attribute_spec.handler. */ static tree -ix86_handle_struct_attribute (tree *node, tree name, tree, int, - bool *no_add_attrs) +ix86_handle_struct_type_attribute (tree *type, tree name, tree, int, + bool *no_add_attrs) { - tree *type = NULL; - if (DECL_P (*node)) + if (!(RECORD_OR_UNION_TYPE_P (*type))) { - if (TREE_CODE (*node) == TYPE_DECL) - type = &TREE_TYPE (*node); - } - else - type = node; - - if (!(type && RECORD_OR_UNION_TYPE_P (*type))) - { - warning (OPT_Wattributes, "%qE attribute ignored", - name); + warning (OPT_Wattributes, "%qE attribute ignored", name); *no_add_attrs = true; } @@ -42638,6 +42629,20 @@ ix86_handle_struct_attribute (tree *node, tree name, tree, int, } static tree +ix86_handle_struct_decl_attribute (tree *node, tree name, tree arg, int flags, + bool *no_add_attrs) +{ + if (TREE_CODE (*node) == TYPE_DECL) + return ix86_handle_struct_type_attribute (&(TREE_TYPE (*node)), name, arg, + flags, no_add_attrs); + + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + + return NULL_TREE; +} + +static tree ix86_handle_fndecl_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { @@ -46494,61 +46499,64 @@ ix86_expand_round_sse4 (rtx op0, rtx op1) /* Table of valid machine attributes. */ static const struct attribute_spec ix86_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ /* Stdcall attribute says callee is responsible for popping arguments if they are not variable. */ - { "stdcall", 0, 0, false, true, true, ix86_handle_cconv_attribute, + { "stdcall", 0, 0, false, true, true, NULL, ix86_handle_cconv_attribute, true }, /* Fastcall attribute says callee is responsible for popping arguments if they are not variable. */ - { "fastcall", 0, 0, false, true, true, ix86_handle_cconv_attribute, + { "fastcall", 0, 0, false, true, true, NULL, ix86_handle_cconv_attribute, true }, /* Thiscall attribute says callee is responsible for popping arguments if they are not variable. */ - { "thiscall", 0, 0, false, true, true, ix86_handle_cconv_attribute, + { "thiscall", 0, 0, false, true, true, NULL, ix86_handle_cconv_attribute, true }, /* Cdecl attribute says the callee is a normal C declaration */ - { "cdecl", 0, 0, false, true, true, ix86_handle_cconv_attribute, + { "cdecl", 0, 0, false, true, true, NULL, ix86_handle_cconv_attribute, true }, /* Regparm attribute specifies how many integer arguments are to be passed in registers. */ - { "regparm", 1, 1, false, true, true, ix86_handle_cconv_attribute, + { "regparm", 1, 1, false, true, true, NULL, ix86_handle_cconv_attribute, true }, /* Sseregparm attribute says we are using x86_64 calling conventions for FP arguments. */ - { "sseregparm", 0, 0, false, true, true, ix86_handle_cconv_attribute, + { "sseregparm", 0, 0, false, true, true, NULL, ix86_handle_cconv_attribute, true }, /* The transactional memory builtins are implicitly regparm or fastcall depending on the ABI. Override the generic do-nothing attribute that these builtins were declared with. */ - { "*tm regparm", 0, 0, false, true, true, ix86_handle_tm_regparm_attribute, - true }, + { "*tm regparm", 0, 0, false, true, true, NULL, + ix86_handle_tm_regparm_attribute, true }, /* force_align_arg_pointer says this function realigns the stack at entry. */ { (const char *)&ix86_force_align_arg_pointer_string, 0, 0, - false, true, true, ix86_handle_cconv_attribute, false }, + false, true, true, NULL, ix86_handle_cconv_attribute, false }, #if TARGET_DLLIMPORT_DECL_ATTRIBUTES - { "dllimport", 0, 0, false, false, false, handle_dll_attribute, false }, - { "dllexport", 0, 0, false, false, false, handle_dll_attribute, false }, - { "shared", 0, 0, true, false, false, ix86_handle_shared_attribute, + { "dllimport", 0, 0, false, false, false, handle_dll_decl_attribute, + handle_dll_type_attribute, false }, + { "dllexport", 0, 0, false, false, false, handle_dll_decl_attribute, + handle_dll_type_attribute, false }, + { "shared", 0, 0, true, false, false, ix86_handle_shared_attribute, NULL, false }, #endif - { "ms_struct", 0, 0, false, false, false, ix86_handle_struct_attribute, - false }, - { "gcc_struct", 0, 0, false, false, false, ix86_handle_struct_attribute, - false }, + { "ms_struct", 0, 0, false, false, false, ix86_handle_struct_decl_attribute, + ix86_handle_struct_type_attribute, false }, + { "gcc_struct", 0, 0, false, false, false, ix86_handle_struct_decl_attribute, + ix86_handle_struct_type_attribute, false }, #ifdef SUBTARGET_ATTRIBUTE_TABLE SUBTARGET_ATTRIBUTE_TABLE, #endif /* ms_abi and sysv_abi calling convention function attributes. */ - { "ms_abi", 0, 0, false, true, true, ix86_handle_abi_attribute, true }, - { "sysv_abi", 0, 0, false, true, true, ix86_handle_abi_attribute, true }, + { "ms_abi", 0, 0, false, true, true, NULL, ix86_handle_abi_attribute, true }, + { "sysv_abi", 0, 0, false, true, true, NULL, ix86_handle_abi_attribute, + true }, { "ms_hook_prologue", 0, 0, true, false, false, ix86_handle_fndecl_attribute, - false }, - { "callee_pop_aggregate_return", 1, 1, false, true, true, + NULL, false }, + { "callee_pop_aggregate_return", 1, 1, false, true, true, NULL, ix86_handle_callee_pop_aggregate_return, true }, /* End element. */ - { NULL, 0, 0, false, false, false, NULL, false } + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Implement targetm.vectorize.builtin_vectorization_cost. */ diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 73d328904f2..36f99d2c5e5 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -373,18 +373,18 @@ static bool ia64_expand_vec_perm_const_1 (struct expand_vec_perm_d *d); /* Table of valid machine attributes. */ static const struct attribute_spec ia64_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ - { "syscall_linkage", 0, 0, false, true, true, NULL, false }, + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ + { "syscall_linkage", 0, 0, false, true, true, NULL, NULL, false }, { "model", 1, 1, true, false, false, ia64_handle_model_attribute, - false }, + NULL, false }, #if TARGET_ABI_OPEN_VMS { "common_object", 1, 1, true, false, false, - ia64_vms_common_object_attribute, false }, + ia64_vms_common_object_attribute, NULL, false }, #endif { "version_id", 1, 1, true, false, false, - ia64_handle_version_id_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } + ia64_handle_version_id_attribute, NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Initialize the GCC target structure. */ diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c index fa0e883c37d..d5eda945e26 100644 --- a/gcc/config/m32c/m32c.c +++ b/gcc/config/m32c/m32c.c @@ -86,7 +86,8 @@ typedef enum } Push_Pop_Type; static bool m32c_function_needs_enter (void); -static tree interrupt_handler (tree *, tree, tree, int, bool *); +static tree interrupt_decl_handler (tree *, tree, tree, int, bool *); +static tree interrupt_type_handler (tree *, tree, tree, int, bool *); static tree function_vector_handler (tree *, tree, tree, int, bool *); static int interrupt_p (tree node); static int bank_switch_p (tree node); @@ -2904,7 +2905,7 @@ fast_interrupt_p (tree node ATTRIBUTE_UNUSED) } static tree -interrupt_handler (tree * node ATTRIBUTE_UNUSED, +interrupt_decl_handler (tree * node ATTRIBUTE_UNUSED, tree name ATTRIBUTE_UNUSED, tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, @@ -2913,6 +2914,15 @@ interrupt_handler (tree * node ATTRIBUTE_UNUSED, return NULL_TREE; } +static tree +interrupt_type_handler (tree * node ATTRIBUTE_UNUSED, + tree name ATTRIBUTE_UNUSED, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool * no_add_attrs ATTRIBUTE_UNUSED) +{ + return NULL_TREE; +} /* Returns TRUE if given tree has the "function_vector" attribute. */ int m32c_special_page_vector_p (tree func) @@ -3012,12 +3022,15 @@ current_function_special_page_vector (rtx x) #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE m32c_attribute_table static const struct attribute_spec m32c_attribute_table[] = { - {"interrupt", 0, 0, false, false, false, interrupt_handler, false}, - {"bank_switch", 0, 0, false, false, false, interrupt_handler, false}, - {"fast_interrupt", 0, 0, false, false, false, interrupt_handler, false}, - {"function_vector", 1, 1, true, false, false, function_vector_handler, + {"interrupt", 0, 0, false, false, false, interrupt_decl_handler, + interrupt_type_handler, false}, + {"bank_switch", 0, 0, false, false, false, interrupt_decl_handler, + interrupt_type_handler, false}, + {"fast_interrupt", 0, 0, false, false, false, interrupt_decl_handler, + interrupt_type_handler, false}, + {"function_vector", 1, 1, true, false, false,function_vector_handler, NULL, false}, - {0, 0, 0, 0, 0, 0, 0, false} + {0, 0, 0, 0, 0, 0, 0, 0, false} }; #undef TARGET_COMP_TYPE_ATTRIBUTES diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index 26b93bf2b6a..039a22699e6 100644 --- a/gcc/config/m32r/m32r.c +++ b/gcc/config/m32r/m32r.c @@ -121,12 +121,12 @@ static bool m32r_legitimate_constant_p (machine_mode, rtx); static const struct attribute_spec m32r_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ - { "interrupt", 0, 0, true, false, false, NULL, false }, - { "model", 1, 1, true, false, false, m32r_handle_model_attribute, + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ + { "interrupt", 0, 0, true, false, false, NULL, NULL, false }, + { "model", 1, 1, true, false, false, m32r_handle_model_attribute, NULL, false }, - { NULL, 0, 0, false, false, false, NULL, false } + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Initialize the GCC target structure. */ diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index d8abc0e74c7..634602d6891 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -328,13 +328,13 @@ static const struct attribute_spec m68k_attribute_table[] = { /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, affects_type_identity } */ - { "interrupt", 0, 0, true, false, false, m68k_handle_fndecl_attribute, + { "interrupt", 0, 0, true, false, false, m68k_handle_fndecl_attribute, NULL, false }, { "interrupt_handler", 0, 0, true, false, false, - m68k_handle_fndecl_attribute, false }, + m68k_handle_fndecl_attribute, NULL, false }, { "interrupt_thread", 0, 0, true, false, false, - m68k_handle_fndecl_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } + m68k_handle_fndecl_attribute, NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; struct gcc_target targetm = TARGET_INITIALIZER; diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c index c2db3345a58..60c72be8f13 100644 --- a/gcc/config/mcore/mcore.c +++ b/gcc/config/mcore/mcore.c @@ -166,11 +166,11 @@ static const struct attribute_spec mcore_attribute_table[] = { /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, affects_type_identity } */ - { "dllexport", 0, 0, true, false, false, NULL, false }, - { "dllimport", 0, 0, true, false, false, NULL, false }, - { "naked", 0, 0, true, false, false, mcore_handle_naked_attribute, + { "dllexport", 0, 0, true, false, false, NULL, NULL, false }, + { "dllimport", 0, 0, true, false, false, NULL, NULL, false }, + { "naked", 0, 0, true, false, false, mcore_handle_naked_attribute, NULL, false }, - { NULL, 0, 0, false, false, false, NULL, false } + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Initialize the GCC target structure. */ diff --git a/gcc/config/mep/mep.c b/gcc/config/mep/mep.c index 7244db410d3..b1dbc7cf9cc 100644 --- a/gcc/config/mep/mep.c +++ b/gcc/config/mep/mep.c @@ -194,9 +194,13 @@ static bool mep_function_ok_for_sibcall (tree, tree); static int unique_bit_in (HOST_WIDE_INT); static int bit_size_for_clip (HOST_WIDE_INT); static int bytesize (const_tree, machine_mode); -static tree mep_validate_based_tiny (tree *, tree, tree, int, bool *); -static tree mep_validate_near_far (tree *, tree, tree, int, bool *); -static tree mep_validate_disinterrupt (tree *, tree, tree, int, bool *); +static tree mep_validate_type_based_tiny (tree *, tree, tree, int, bool *); +static tree mep_validate_decl_based_tiny (tree *, tree, tree, int, bool *); +static tree mep_validate_type_near_far (tree *, tree, tree, int, bool *); +static tree mep_validate_decl_near_far (tree *, tree, tree, int, bool *); +static tree mep_validate_type_disinterrupt (tree *, tree, tree, int, bool *); +static tree mep_validate_decl_disinterrupt (tree *, tree, tree, int, bool *); +static tree mep_validate_type_warning(tree *, tree, tree, int, bool *); static tree mep_validate_interrupt (tree *, tree, tree, int, bool *); static tree mep_validate_io_cb (tree *, tree, tree, int, bool *); static tree mep_validate_vliw (tree *, tree, tree, int, bool *); @@ -3810,11 +3814,23 @@ mep_asm_output_opcode (FILE *file, const char *ptr) /* Handle attributes. */ static tree -mep_validate_based_tiny (tree *node, tree name, tree args, +mep_validate_type_based_tiny (tree *node, tree name, tree args, + int flags ATTRIBUTE_UNUSED, bool *no_add) +{ + if (TREE_CODE (*node) != POINTER_TYPE) + { + warning (0, "%qE attribute only applies to variables", name); + *no_add = true; + } + + return NULL_TREE; +} + +static tree +mep_validate_decl_based_tiny (tree *node, tree name, tree args, int flags ATTRIBUTE_UNUSED, bool *no_add) { if (TREE_CODE (*node) != VAR_DECL - && TREE_CODE (*node) != POINTER_TYPE && TREE_CODE (*node) != TYPE_DECL) { warning (0, "%qE attribute only applies to variables", name); @@ -3870,13 +3886,29 @@ mep_multiple_address_regions (tree list, bool check_section_attr) : TYPE_ATTRIBUTES (TREE_TYPE (decl)) static tree -mep_validate_near_far (tree *node, tree name, tree args, +mep_validate_type_near_far (tree *node, tree name, tree args, + int flags ATTRIBUTE_UNUSED, bool *no_add) +{ + if (TREE_CODE (*node) != METHOD_TYPE && TREE_CODE (*node) != POINTER_TYPE) + { + warning (0, "%qE attribute only applies to variables and functions", + name); + *no_add = true; + } + else if (mep_multiple_address_regions (MEP_ATTRIBUTES (*node), false) > 0) + { + warning (0, "duplicate address region attribute %qE", name); + TYPE_ATTRIBUTES (*node) = NULL_TREE; + } + return NULL_TREE; +} + +static tree +mep_validate_decl_near_far (tree *node, tree name, tree args, int flags ATTRIBUTE_UNUSED, bool *no_add) { if (TREE_CODE (*node) != VAR_DECL && TREE_CODE (*node) != FUNCTION_DECL - && TREE_CODE (*node) != METHOD_TYPE - && TREE_CODE (*node) != POINTER_TYPE && TREE_CODE (*node) != TYPE_DECL) { warning (0, "%qE attribute only applies to variables and functions", @@ -3907,11 +3939,24 @@ mep_validate_near_far (tree *node, tree name, tree args, } static tree -mep_validate_disinterrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, bool *no_add) +mep_validate_type_disinterrupt (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add) +{ + if (TREE_CODE (*node) != METHOD_TYPE) + { + warning (0, "%qE attribute only applies to functions", name); + *no_add = true; + } + return NULL_TREE; +} + +static tree +mep_validate_decl_disinterrupt (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add) { - if (TREE_CODE (*node) != FUNCTION_DECL - && TREE_CODE (*node) != METHOD_TYPE) + if (TREE_CODE (*node) != FUNCTION_DECL) { warning (0, "%qE attribute only applies to functions", name); *no_add = true; @@ -3920,6 +3965,17 @@ mep_validate_disinterrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED, } static tree +mep_validate_type_warning (tree *node ATTRIBUTE_UNUSED, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add) +{ + warning (0, "%qE attribute only applies to functions", name); + *no_add = true; + return NULL_TREE; +} + + +static tree mep_validate_interrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, bool *no_add) { @@ -4032,17 +4088,24 @@ static const struct attribute_spec mep_attribute_table[11] = { /* name min max decl type func handler affects_type_identity */ - { "based", 0, 0, false, false, false, mep_validate_based_tiny, false }, - { "tiny", 0, 0, false, false, false, mep_validate_based_tiny, false }, - { "near", 0, 0, false, false, false, mep_validate_near_far, false }, - { "far", 0, 0, false, false, false, mep_validate_near_far, false }, - { "disinterrupt", 0, 0, false, false, false, mep_validate_disinterrupt, - false }, - { "interrupt", 0, 0, false, false, false, mep_validate_interrupt, false }, - { "io", 0, 1, false, false, false, mep_validate_io_cb, false }, - { "cb", 0, 1, false, false, false, mep_validate_io_cb, false }, - { "vliw", 0, 0, false, true, false, mep_validate_vliw, false }, - { NULL, 0, 0, false, false, false, NULL, false } + { "based", 0, 0, false, false, false, mep_validate_decl_based_tiny, + mep_validate_type_based_tiny, false }, + { "tiny", 0, 0, false, false, false, mep_validate_decl_based_tiny, + mep_validate_type_based_tiny, false }, + { "near", 0, 0, false, false, false, mep_validate_decl_near_far, + mep_validate_type_near_far, false }, + { "far", 0, 0, false, false, false, mep_validate_decl_near_far, + mep_validate_type_near_far, false }, + { "disinterrupt", 0, 0, false, false, false, mep_validate_decl_disinterrupt, + mep_validate_type_disinterrupt, false }, + { "interrupt", 0, 0, false, false, false, mep_validate_interrupt, + mep_validate_type_warning, false }, + { "io", 0, 1, false, false, false, mep_validate_io_cb, + mep_validate_type_warning, false }, + { "cb", 0, 1, false, false, false, mep_validate_io_cb, + mep_validate_type_warning, false }, + { "vliw", 0, 0, false, true, false, NULL, mep_validate_vliw, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; static bool diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c index 7a44396def6..6a085c1f857 100644 --- a/gcc/config/microblaze/microblaze.c +++ b/gcc/config/microblaze/microblaze.c @@ -234,18 +234,18 @@ int fast_interrupt; int save_volatiles; const struct attribute_spec microblaze_attribute_table[] = { - /* name min_len, max_len, decl_req, type_req, fn_type, req_handler, - affects_type_identity */ - {"interrupt_handler", 0, 0, true, false, false, NULL, - false }, + /* name min_len, max_len, decl_req, type_req, fn_type, decl_handler, + type_handler, affects_type_identity */ + {"interrupt_handler", 0, 0, true, false, false, NULL, + NULL, false }, {"break_handler", 0, 0, true, false, false, NULL, - false }, + NULL, false }, {"fast_interrupt", 0, 0, true, false, false, NULL, - false }, + NULL, false }, {"save_volatiles" , 0, 0, true, false, false, NULL, - false }, + NULL, false }, { NULL, 0, 0, false, false, false, NULL, - false } + NULL, false } }; static int microblaze_interrupt_function_p (tree); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 1aea23e66e5..122864ba764 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -724,26 +724,26 @@ const enum reg_class mips_regno_to_class[FIRST_PSEUDO_REGISTER] = { /* The value of TARGET_ATTRIBUTE_TABLE. */ static const struct attribute_spec mips_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - om_diagnostic } */ - { "long_call", 0, 0, false, true, true, NULL, false }, - { "far", 0, 0, false, true, true, NULL, false }, - { "near", 0, 0, false, true, true, NULL, false }, + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, om_diagnostic } */ + { "long_call", 0, 0, false, true, true, NULL, NULL, false }, + { "far", 0, 0, false, true, true, NULL, NULL, false }, + { "near", 0, 0, false, true, true, NULL, NULL, false }, /* We would really like to treat "mips16" and "nomips16" as type attributes, but GCC doesn't provide the hooks we need to support the right conversion rules. As declaration attributes, they affect code generation but don't carry other semantics. */ - { "mips16", 0, 0, true, false, false, NULL, false }, - { "nomips16", 0, 0, true, false, false, NULL, false }, - { "micromips", 0, 0, true, false, false, NULL, false }, - { "nomicromips", 0, 0, true, false, false, NULL, false }, - { "nocompression", 0, 0, true, false, false, NULL, false }, + { "mips16", 0, 0, true, false, false, NULL, NULL, false }, + { "nomips16", 0, 0, true, false, false, NULL, NULL, false }, + { "micromips", 0, 0, true, false, false, NULL, NULL, false }, + { "nomicromips", 0, 0, true, false, false, NULL, NULL, false }, + { "nocompression", 0, 0, true, false, false, NULL, NULL, false }, /* Allow functions to be specified as interrupt handlers */ - { "interrupt", 0, 0, false, true, true, NULL, false }, - { "use_shadow_register_set", 0, 0, false, true, true, NULL, false }, - { "keep_interrupts_masked", 0, 0, false, true, true, NULL, false }, - { "use_debug_exception_return", 0, 0, false, true, true, NULL, false }, - { NULL, 0, 0, false, false, false, NULL, false } + { "interrupt", 0, 0, false, true, true, NULL, NULL, false }, + { "use_shadow_register_set", 0, 0, false, true, true, NULL, NULL, false }, + { "keep_interrupts_masked", 0, 0, false, true, true, NULL, NULL, false }, + { "use_debug_exception_return", 0, 0, false, true, true, NULL, NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* A table describing all the processors GCC knows about; see diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c index bf29e182df8..f7518f3184a 100644 --- a/gcc/config/msp430/msp430.c +++ b/gcc/config/msp430/msp430.c @@ -1315,13 +1315,13 @@ msp430_attr (tree * node, const struct attribute_spec msp430_attribute_table[] = { /* Name min_len decl_req, fn_type_req, affects_type_identity - max_len, type_req, handler. */ - { "interrupt", 0, 1, true, false, false, msp430_attr, false }, - { "naked", 0, 0, true, false, false, msp430_attr, false }, - { "reentrant", 0, 0, true, false, false, msp430_attr, false }, - { "critical", 0, 0, true, false, false, msp430_attr, false }, - { "wakeup", 0, 0, true, false, false, msp430_attr, false }, - { NULL, 0, 0, false, false, false, NULL, false } + max_len, type_req, decl_handler, type_handler. */ + { "interrupt", 0, 1, true, false, false, msp430_attr, NULL, false }, + { "naked", 0, 0, true, false, false, msp430_attr, NULL, false }, + { "reentrant", 0, 0, true, false, false, msp430_attr, NULL, false }, + { "critical", 0, 0, true, false, false, msp430_attr, NULL, false }, + { "wakeup", 0, 0, true, false, false, msp430_attr, NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; void diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c index 5a8e24fc175..70b2590a876 100644 --- a/gcc/config/nds32/nds32.c +++ b/gcc/config/nds32/nds32.c @@ -100,33 +100,34 @@ static const char * const nds32_intrinsic_register_names[] = static const struct attribute_spec nds32_attribute_table[] = { /* Syntax: { name, min_len, max_len, decl_required, type_required, - function_type_required, handler, affects_type_identity } */ + function_type_required, decl_handler, type_handler, + affects_type_identity } */ /* The interrupt vid: [0-63]+ (actual vector number starts from 9 to 72). */ - { "interrupt", 1, 64, false, false, false, NULL, false }, + { "interrupt", 1, 64, false, false, false, NULL, NULL, false }, /* The exception vid: [1-8]+ (actual vector number starts from 1 to 8). */ - { "exception", 1, 8, false, false, false, NULL, false }, + { "exception", 1, 8, false, false, false, NULL, NULL, false }, /* Argument is user's interrupt numbers. The vector number is always 0. */ - { "reset", 1, 1, false, false, false, NULL, false }, + { "reset", 1, 1, false, false, false, NULL, NULL, false }, /* The attributes describing isr nested type. */ - { "nested", 0, 0, false, false, false, NULL, false }, - { "not_nested", 0, 0, false, false, false, NULL, false }, - { "nested_ready", 0, 0, false, false, false, NULL, false }, + { "nested", 0, 0, false, false, false, NULL, NULL, false }, + { "not_nested", 0, 0, false, false, false, NULL, NULL, false }, + { "nested_ready", 0, 0, false, false, false, NULL, NULL, false }, /* The attributes describing isr register save scheme. */ - { "save_all", 0, 0, false, false, false, NULL, false }, - { "partial_save", 0, 0, false, false, false, NULL, false }, + { "save_all", 0, 0, false, false, false, NULL, NULL, false }, + { "partial_save", 0, 0, false, false, false, NULL, NULL, false }, /* The attributes used by reset attribute. */ - { "nmi", 1, 1, false, false, false, NULL, false }, - { "warm", 1, 1, false, false, false, NULL, false }, + { "nmi", 1, 1, false, false, false, NULL, NULL, false }, + { "warm", 1, 1, false, false, false, NULL, NULL, false }, /* The attribute telling no prologue/epilogue. */ - { "naked", 0, 0, false, false, false, NULL, false }, + { "naked", 0, 0, false, false, false, NULL, NULL, false }, /* The last attribute spec is set to be NULL. */ - { NULL, 0, 0, false, false, false, NULL, false } + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c index ebc419f92e8..8e249022be6 100644 --- a/gcc/config/nvptx/nvptx.c +++ b/gcc/config/nvptx/nvptx.c @@ -1993,10 +1993,11 @@ nvptx_handle_kernel_attribute (tree *node, tree name, tree ARG_UNUSED (args), /* Table of valid machine attributes. */ static const struct attribute_spec nvptx_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ - { "kernel", 0, 0, true, false, false, nvptx_handle_kernel_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ + { "kernel", 0, 0, true, false, false, nvptx_handle_kernel_attribute, NULL, + false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Limit vector alignments to BIGGEST_ALIGNMENT. */ diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c index c7520aaac6b..5667b326878 100644 --- a/gcc/config/rl78/rl78.c +++ b/gcc/config/rl78/rl78.c @@ -687,15 +687,15 @@ rl78_handle_func_attribute (tree * node, /* Table of RL78-specific attributes. */ const struct attribute_spec rl78_attribute_table[] = { - /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity. */ + /* Name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity. */ { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute, - false }, + NULL, false }, { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute, - false }, + NULL, false }, { "naked", 0, 0, true, false, false, rl78_handle_func_attribute, - false }, - { NULL, 0, 0, false, false, false, NULL, false } + NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 73152ce47d1..d6389a177f4 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1083,7 +1083,10 @@ static struct machine_function * rs6000_init_machine_status (void); static int rs6000_ra_ever_killed (void); static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *); static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *); -static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *); +static tree rs6000_handle_struct_decl_attribute (tree *, tree, tree, int, + bool *); +static tree rs6000_handle_struct_type_attribute (tree *, tree, tree, int, + bool *); static tree rs6000_builtin_vectorized_libmass (tree, tree, tree); static void rs6000_emit_set_long_const (rtx, HOST_WIDE_INT); static int rs6000_memory_move_cost (machine_mode, reg_class_t, bool); @@ -1295,22 +1298,23 @@ static const char alt_reg_names[][8] = static const struct attribute_spec rs6000_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ - { "altivec", 1, 1, false, true, false, rs6000_handle_altivec_attribute, - false }, - { "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute, - false }, - { "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute, - false }, - { "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute, - false }, - { "gcc_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute, + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ + { "altivec", 1, 1, false, true, false, NULL, + rs6000_handle_altivec_attribute, false }, + { "longcall", 0, 0, false, true, true, NULL, + rs6000_handle_longcall_attribute, false }, + { "shortcall", 0, 0, false, true, true, NULL, + rs6000_handle_longcall_attribute, false }, + { "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_decl_attribute, + rs6000_handle_struct_type_attribute, false }, + { "gcc_struct", 0, 0, false, false, false, + rs6000_handle_struct_decl_attribute, rs6000_handle_struct_type_attribute, false }, #ifdef SUBTARGET_ATTRIBUTE_TABLE SUBTARGET_ATTRIBUTE_TABLE, #endif - { NULL, 0, 0, false, false, false, NULL, false } + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; #ifndef TARGET_PROFILE_KERNEL @@ -28761,9 +28765,7 @@ rs6000_handle_longcall_attribute (tree *node, tree name, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) { - if (TREE_CODE (*node) != FUNCTION_TYPE - && TREE_CODE (*node) != FIELD_DECL - && TREE_CODE (*node) != TYPE_DECL) + if (TREE_CODE (*node) != FUNCTION_TYPE) { warning (OPT_Wattributes, "%qE attribute only applies to functions", name); @@ -28822,19 +28824,14 @@ rs6000_longcall_ref (rtx call_ref) /* Handle a "ms_struct" or "gcc_struct" attribute; arguments as in struct attribute_spec.handler. */ + static tree -rs6000_handle_struct_attribute (tree *node, tree name, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +rs6000_handle_struct_type_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) { - tree *type = NULL; - if (DECL_P (*node)) - { - if (TREE_CODE (*node) == TYPE_DECL) - type = &TREE_TYPE (*node); - } - else - type = node; + tree *type = node; if (!(type && (TREE_CODE (*type) == RECORD_TYPE || TREE_CODE (*type) == UNION_TYPE))) @@ -28856,6 +28853,19 @@ rs6000_handle_struct_attribute (tree *node, tree name, return NULL_TREE; } +static tree +rs6000_handle_struct_decl_attribute (tree *node, tree name, tree args, + int flags, bool *no_add_attrs) +{ + if (TREE_CODE (*node) == TYPE_DECL) + return rs6000_handle_struct_type_attribute (&TREE_TYPE (*node), name, args, + flags, no_add_attrs); + + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + return NULL_TREE; +} + static bool rs6000_ms_bitfield_layout_p (const_tree record_type) { diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index e7575667bc2..dacf990fad7 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -2717,17 +2717,17 @@ rx_handle_vector_attribute (tree * node, /* Table of RX specific attributes. */ const struct attribute_spec rx_attribute_table[] = { - /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity. */ - { "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute, + /* Name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity. */ + { "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute, NULL, false }, - { "interrupt", 0, -1, true, false, false, rx_handle_func_attribute, + { "interrupt", 0, -1, true, false, false, rx_handle_func_attribute, NULL, false }, - { "naked", 0, 0, true, false, false, rx_handle_func_attribute, + { "naked", 0, 0, true, false, false, rx_handle_func_attribute, NULL, false }, { "vector", 1, -1, true, false, false, rx_handle_vector_attribute, - false }, - { NULL, 0, 0, false, false, false, NULL, false } + NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE. */ diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index ae3ffd12db1..3107fad7c8f 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -497,10 +497,11 @@ s390_handle_hotpatch_attribute (tree *node, tree name, tree args, } static const struct attribute_spec s390_attribute_table[] = { - { "hotpatch", 0, 1, true, false, false, s390_handle_hotpatch_attribute, false + { "hotpatch", 0, 1, true, false, false, s390_handle_hotpatch_attribute, NULL, + false }, /* End element. */ - { NULL, 0, 0, false, false, false, NULL, false } + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Return the alignment for LABEL. We default to the -falign-labels diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index b89d0481fac..fc3c9006d0f 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -352,25 +352,25 @@ static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED; static const struct attribute_spec sh_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ { "interrupt_handler", 0, 0, true, false, false, - sh_handle_interrupt_handler_attribute, false }, + sh_handle_interrupt_handler_attribute, NULL, false }, { "sp_switch", 1, 1, true, false, false, - sh_handle_sp_switch_attribute, false }, + sh_handle_sp_switch_attribute, NULL, false }, { "trap_exit", 1, 1, true, false, false, - sh_handle_trap_exit_attribute, false }, - { "renesas", 0, 0, false, true, false, + sh_handle_trap_exit_attribute, NULL, false }, + { "renesas", 0, 0, false, true, false, NULL, sh_handle_renesas_attribute, false }, { "trapa_handler", 0, 0, true, false, false, - sh_handle_interrupt_handler_attribute, false }, + sh_handle_interrupt_handler_attribute, NULL, false }, { "nosave_low_regs", 0, 0, true, false, false, - sh_handle_interrupt_handler_attribute, false }, + sh_handle_interrupt_handler_attribute, NULL, false }, { "resbank", 0, 0, true, false, false, - sh_handle_resbank_handler_attribute, false }, + sh_handle_resbank_handler_attribute, NULL, false }, { "function_vector", 1, 1, true, false, false, - sh2a_handle_function_vector_handler_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } + sh2a_handle_function_vector_handler_attribute, NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Initialize the GCC target structure. */ diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h index d41e3c4428a..43e081e39e1 100644 --- a/gcc/config/sol2.h +++ b/gcc/config/sol2.h @@ -316,8 +316,8 @@ along with GCC; see the file COPYING3. If not see /* #pragma init and #pragma fini are implemented on top of init and fini attributes. */ #define SOLARIS_ATTRIBUTE_TABLE \ - { "init", 0, 0, true, false, false, NULL, false }, \ - { "fini", 0, 0, true, false, false, NULL, false } + { "init", 0, 0, true, false, false, NULL, NULL, false }, \ + { "fini", 0, 0, true, false, false, NULL, NULL, false } /* Solaris-specific #pragmas are implemented on top of attributes. Hook in the bits from config/sol2.c. */ diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 1d0d45ad16c..01e8f98299c 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -653,10 +653,10 @@ static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *); /* Table of valid machine attributes. */ static const struct attribute_spec sparc_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - do_diagnostic } */ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, do_diagnostic } */ SUBTARGET_ATTRIBUTE_TABLE, - { NULL, 0, 0, false, false, false, NULL, false } + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; #endif diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c index d679a347c8b..2a5d1401b8e 100644 --- a/gcc/config/spu/spu.c +++ b/gcc/config/spu/spu.c @@ -7146,13 +7146,13 @@ spu_canonicalize_comparison (int *code, rtx *op0, rtx *op1, /* Table of machine attributes. */ static const struct attribute_spec spu_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ { "naked", 0, 0, true, false, false, spu_handle_fndecl_attribute, - false }, - { "spu_vector", 0, 0, false, true, false, spu_handle_vector_attribute, - false }, - { NULL, 0, 0, false, false, false, NULL, false } + NULL, false }, + { "spu_vector", 0, 0, false, true, false, NULL, + spu_handle_vector_attribute, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* TARGET overrides. */ diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c index 0b1548789fe..f1926cd0220 100644 --- a/gcc/config/stormy16/stormy16.c +++ b/gcc/config/stormy16/stormy16.c @@ -2212,15 +2212,15 @@ static tree xstormy16_handle_below100_attribute static const struct attribute_spec xstormy16_attribute_table[] = { - /* name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity. */ - { "interrupt", 0, 0, false, true, true, - xstormy16_handle_interrupt_attribute , false }, - { "BELOW100", 0, 0, false, false, false, - xstormy16_handle_below100_attribute, false }, - { "below100", 0, 0, false, false, false, - xstormy16_handle_below100_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } + /* name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity. */ + { "interrupt", 0, 0, false, true, true, NULL, + xstormy16_handle_interrupt_attribute , false }, + { "BELOW100", 0, 0, true, false, false, + xstormy16_handle_below100_attribute, NULL, false }, + { "below100", 0, 0, true, false, false, + xstormy16_handle_below100_attribute, NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Handle an "interrupt" attribute; @@ -2252,15 +2252,13 @@ xstormy16_handle_below100_attribute (tree *node, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) { - if (TREE_CODE (*node) != VAR_DECL - && TREE_CODE (*node) != POINTER_TYPE - && TREE_CODE (*node) != TYPE_DECL) + if (TREE_CODE (*node) != VAR_DECL) { warning (OPT_Wattributes, "%<__BELOW100__%> attribute only applies to variables"); *no_add_attrs = true; } - else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL) + else if (args == NULL_TREE) { if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node))) { diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c index bdeb56b2368..250f1894a5a 100644 --- a/gcc/config/v850/v850.c +++ b/gcc/config/v850/v850.c @@ -3138,19 +3138,19 @@ v850_adjust_insn_length (rtx_insn *insn, int length) static const struct attribute_spec v850_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ { "interrupt_handler", 0, 0, true, false, false, - v850_handle_interrupt_attribute, false }, + v850_handle_interrupt_attribute, NULL, false }, { "interrupt", 0, 0, true, false, false, - v850_handle_interrupt_attribute, false }, + v850_handle_interrupt_attribute, NULL, false }, { "sda", 0, 0, true, false, false, - v850_handle_data_area_attribute, false }, + v850_handle_data_area_attribute, NULL, false }, { "tda", 0, 0, true, false, false, - v850_handle_data_area_attribute, false }, + v850_handle_data_area_attribute, NULL, false }, { "zda", 0, 0, true, false, false, - v850_handle_data_area_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } + v850_handle_data_area_attribute, NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; static void diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index f02452e4552..74bf3170a4c 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9641,7 +9641,7 @@ grokdeclarator (const cp_declarator *declarator, { /* Apply the c++11 attributes to the type preceding them. */ input_location = declspecs->locations[ds_std_attribute]; - decl_attributes (&type, declspecs->std_attributes, 0); + type_attributes (&type, declspecs->std_attributes, 0); input_location = saved_loc; } @@ -9667,7 +9667,7 @@ grokdeclarator (const cp_declarator *declarator, attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT; if (declarator->kind == cdk_array) attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT; - returned_attrs = decl_attributes (&type, + returned_attrs = type_attributes (&type, chainon (returned_attrs, attrs), attr_flags); } @@ -9913,7 +9913,7 @@ grokdeclarator (const cp_declarator *declarator, The optional attribute-specifier-seq appertains to the function type. */ - decl_attributes (&type, declarator->std_attributes, + type_attributes (&type, declarator->std_attributes, 0); } break; @@ -10087,7 +10087,7 @@ grokdeclarator (const cp_declarator *declarator, [the optional attribute-specifier-seq (7.6.1) appertains to the pointer and not to the object pointed to]. */ if (declarator->std_attributes) - decl_attributes (&type, declarator->std_attributes, + type_attributes (&type, declarator->std_attributes, 0); ctype = NULL_TREE; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index b2123f2decb..4478c6cb15c 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1472,13 +1472,20 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags) if (TREE_TYPE (*decl) && TYPE_PTRMEMFUNC_P (TREE_TYPE (*decl))) { - attributes - = decl_attributes (decl, attributes, flags | ATTR_FLAG_FUNCTION_NEXT); - decl_attributes (&TYPE_PTRMEMFUNC_FN_TYPE_RAW (TREE_TYPE (*decl)), + if (TYPE_P (*decl)) + attributes + = type_attributes (decl, attributes, flags | ATTR_FLAG_FUNCTION_NEXT); + else + attributes + = decl_attributes (decl, attributes, flags | ATTR_FLAG_FUNCTION_NEXT); + type_attributes (&TYPE_PTRMEMFUNC_FN_TYPE_RAW (TREE_TYPE (*decl)), attributes, flags); } else - decl_attributes (decl, attributes, flags); + if (TYPE_P (*decl)) + type_attributes (decl, attributes, flags); + else + decl_attributes (decl, attributes, flags); if (TREE_CODE (*decl) == TYPE_DECL) SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl)); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 6d6abe9020a..b74d22dfea6 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -58,10 +58,17 @@ static tree count_trees_r (tree *, int *, void *); static tree verify_stmt_tree_r (tree *, int *, void *); static tree build_local_temp (tree); -static tree handle_java_interface_attribute (tree *, tree, tree, int, bool *); -static tree handle_com_interface_attribute (tree *, tree, tree, int, bool *); +static tree handle_java_interface_decl_attribute (tree *, tree, tree, int, + bool *); +static tree handle_java_interface_type_attribute (tree *, tree, tree, int, + bool *); +static tree handle_com_interface_decl_attribute (tree *, tree, tree, int, + bool *); +static tree handle_com_interface_type_attribute (tree *, tree, tree, int, + bool *); static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *); -static tree handle_abi_tag_attribute (tree *, tree, tree, int, bool *); +static tree handle_abi_tag_decl_attribute (tree *, tree, tree, int, bool *); +static tree handle_abi_tag_type_attribute (tree *, tree, tree, int, bool *); /* If REF is an lvalue, returns the kind of lvalue that REF is. Otherwise, returns clk_none. */ @@ -3313,31 +3320,51 @@ zero_init_p (const_tree t) /* Table of valid C++ attributes. */ const struct attribute_spec cxx_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ { "java_interface", 0, 0, false, false, false, - handle_java_interface_attribute, false }, + handle_java_interface_decl_attribute, handle_java_interface_type_attribute, + false }, { "com_interface", 0, 0, false, false, false, - handle_com_interface_attribute, false }, + handle_com_interface_decl_attribute, handle_com_interface_type_attribute, + false }, { "init_priority", 1, 1, true, false, false, - handle_init_priority_attribute, false }, + handle_init_priority_attribute, NULL, false }, { "abi_tag", 1, -1, false, false, false, - handle_abi_tag_attribute, true }, - { NULL, 0, 0, false, false, false, NULL, false } + handle_abi_tag_decl_attribute, handle_abi_tag_type_attribute, true }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; + +static tree +handle_java_interface_decl_attribute (tree* /*node*/, tree name, tree /*args*/, + int /*flags*/, bool* no_add_attrs) +{ + error ("%qE attribute can only be applied to Java class definitions", name); + *no_add_attrs = true; + return NULL_TREE; +} + +static tree +handle_com_interface_decl_attribute (tree* /*node*/, tree name, tree /*args*/, + int /*flags*/, bool* no_add_attrs) +{ + warning (OPT_Wattributes, "%qE attribute can only be applied " + "to class definitions", name); + *no_add_attrs = true; + return NULL_TREE; +} + /* Handle a "java_interface" attribute; arguments as in struct attribute_spec.handler. */ static tree -handle_java_interface_attribute (tree* node, - tree name, - tree /*args*/, - int flags, - bool* no_add_attrs) -{ - if (DECL_P (*node) - || !CLASS_TYPE_P (*node) - || !TYPE_FOR_JAVA (*node)) +handle_java_interface_type_attribute (tree* node, + tree name, + tree /*args*/, + int flags, + bool* no_add_attrs) +{ + if (!CLASS_TYPE_P (*node) || !TYPE_FOR_JAVA (*node)) { error ("%qE attribute can only be applied to Java class definitions", name); @@ -3354,19 +3381,17 @@ handle_java_interface_attribute (tree* node, /* Handle a "com_interface" attribute; arguments as in struct attribute_spec.handler. */ static tree -handle_com_interface_attribute (tree* node, - tree name, - tree /*args*/, - int /*flags*/, - bool* no_add_attrs) +handle_com_interface_type_attribute (tree* node, + tree name, + tree /*args*/, + int /*flags*/, + bool* no_add_attrs) { static int warned; *no_add_attrs = true; - if (DECL_P (*node) - || !CLASS_TYPE_P (*node) - || *node != TYPE_MAIN_VARIANT (*node)) + if (!CLASS_TYPE_P (*node) || *node != TYPE_MAIN_VARIANT (*node)) { warning (OPT_Wattributes, "%qE attribute can only be applied " "to class definitions", name); @@ -3492,36 +3517,55 @@ check_abi_tag_redeclaration (const_tree decl, const_tree old, const_tree new_) struct attribute_spec.handler. */ static tree -handle_abi_tag_attribute (tree* node, tree name, tree args, - int flags, bool* no_add_attrs) +handle_abi_tag_decl_attribute (tree* node, tree name, tree /*args*/, + int /*flags*/, bool* no_add_attrs) { - if (TYPE_P (*node)) + if (TREE_CODE (*node) != FUNCTION_DECL) { - if (!OVERLOAD_TYPE_P (*node)) - { - error ("%qE attribute applied to non-class, non-enum type %qT", - name, *node); - goto fail; - } - else if (!(flags & (int)ATTR_FLAG_TYPE_IN_PLACE)) - { - error ("%qE attribute applied to %qT after its definition", - name, *node); - goto fail; - } - else if (CLASSTYPE_TEMPLATE_INSTANTIATION (*node)) - { - warning (OPT_Wattributes, "ignoring %qE attribute applied to " - "template instantiation %qT", name, *node); - goto fail; - } - else if (CLASSTYPE_TEMPLATE_SPECIALIZATION (*node)) - { - warning (OPT_Wattributes, "ignoring %qE attribute applied to " - "template specialization %qT", name, *node); - goto fail; - } + error ("%qE attribute applied to non-function %qD", name, *node); + *no_add_attrs = true; + } + else if (DECL_LANGUAGE (*node) == lang_c) + { + error ("%qE attribute applied to extern \"C\" function %qD", + name, *node); + *no_add_attrs = true; + } + return NULL_TREE; +} + + +static tree +handle_abi_tag_type_attribute (tree* node, tree name, tree args, + int flags, bool* no_add_attrs) +{ + if (!OVERLOAD_TYPE_P (*node)) + { + error ("%qE attribute applied to non-class, non-enum type %qT", + name, *node); + *no_add_attrs = true; + } + else if (!(flags & (int)ATTR_FLAG_TYPE_IN_PLACE)) + { + error ("%qE attribute applied to %qT after its definition", + name, *node); + *no_add_attrs = true; + } + else if (CLASSTYPE_TEMPLATE_INSTANTIATION (*node)) + { + warning (OPT_Wattributes, "ignoring %qE attribute applied to " + "template instantiation %qT", name, *node); + *no_add_attrs = true; + } + else if (CLASSTYPE_TEMPLATE_SPECIALIZATION (*node)) + { + warning (OPT_Wattributes, "ignoring %qE attribute applied to " + "template specialization %qT", name, *node); + *no_add_attrs = true; + } + else + { tree attributes = TYPE_ATTRIBUTES (*node); tree decl = TYPE_NAME (*node); @@ -3532,29 +3576,11 @@ handle_abi_tag_attribute (tree* node, tree name, tree args, lookup_attribute ("abi_tag", attributes), args)) - goto fail; + *no_add_attrs = true; } - } - else - { - if (TREE_CODE (*node) != FUNCTION_DECL) - { - error ("%qE attribute applied to non-function %qD", name, *node); - goto fail; - } - else if (DECL_LANGUAGE (*node) == lang_c) - { - error ("%qE attribute applied to extern \"C\" function %qD", - name, *node); - goto fail; - } - } + } return NULL_TREE; - - fail: - *no_add_attrs = true; - return NULL_TREE; } /* Return a new PTRMEM_CST of the indicated TYPE. The MEMBER is the diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index 10542307a35..2a75b8780c7 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -108,11 +108,11 @@ gfc_handle_omp_declare_target_attribute (tree *, tree, tree, int, bool *) /* Table of valid Fortran attributes. */ static const struct attribute_spec gfc_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler, + type_handler, affects_type_identity } */ { "omp declare target", 0, 0, true, false, false, - gfc_handle_omp_declare_target_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } + gfc_handle_omp_declare_target_attribute, NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; #undef LANG_HOOKS_NAME diff --git a/gcc/java/lang.c b/gcc/java/lang.c index b64e4eaba06..4dbd9e6066b 100644 --- a/gcc/java/lang.c +++ b/gcc/java/lang.c @@ -72,9 +72,8 @@ static tree java_eh_personality (void); /* 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 } + { "nonnull", 0, -1, false, true, true, NULL, NULL, false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Used to avoid printing error messages with bogus function diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c index a4ae2a80a68..7b948da6bff 100644 --- a/gcc/lto/lto-lang.c +++ b/gcc/lto/lto-lang.c @@ -82,37 +82,38 @@ 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 }, + handle_noreturn_attribute, NULL, false }, { "leaf", 0, 0, true, false, false, - handle_leaf_attribute, false }, + handle_leaf_attribute, NULL, false }, /* The same comments as for noreturn attributes apply to const ones. */ { "const", 0, 0, true, false, false, - handle_const_attribute, false }, + handle_const_attribute, NULL, false }, { "malloc", 0, 0, true, false, false, - handle_malloc_attribute, false }, + handle_malloc_attribute, NULL, false }, { "pure", 0, 0, true, false, false, - handle_pure_attribute, false }, + handle_pure_attribute, NULL, false }, { "no vops", 0, 0, true, false, false, - handle_novops_attribute, false }, + handle_novops_attribute, NULL, false }, { "nonnull", 0, -1, false, true, true, - handle_nonnull_attribute, false }, + NULL, handle_nonnull_attribute, false }, { "nothrow", 0, 0, true, false, false, - handle_nothrow_attribute, false }, + handle_nothrow_attribute, NULL, false }, { "returns_twice", 0, 0, true, false, false, - handle_returns_twice_attribute, false }, + handle_returns_twice_attribute, NULL, false }, { "sentinel", 0, 1, false, true, true, - handle_sentinel_attribute, false }, + NULL, handle_sentinel_attribute, false }, { "type generic", 0, 0, false, true, true, - handle_type_generic_attribute, false }, + NULL, handle_type_generic_attribute, false }, { "fn spec", 1, 1, false, true, true, - handle_fnspec_attribute, false }, + NULL, handle_fnspec_attribute, false }, { "transaction_pure", 0, 0, false, true, true, - handle_transaction_pure_attribute, false }, + NULL, 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 } + NULL, ignore_attribute, + false }, + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; /* Give the specifications for the format attributes, used by C and all @@ -123,10 +124,12 @@ 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, + NULL, handle_format_attribute, false }, { "format_arg", 1, 1, false, true, true, + NULL, handle_format_arg_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } + { NULL, 0, 0, false, false, false, NULL, NULL, false } }; enum built_in_attribute diff --git a/gcc/tree-core.h b/gcc/tree-core.h index d20f5137c0d..9d61ed7eda9 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -1743,7 +1743,9 @@ struct attribute_spec { otherwise the return value should be NULL_TREE. This pointer may be NULL if no special handling is required beyond the checks implied by the rest of this structure. */ - tree (*handler) (tree *node, tree name, tree args, + tree (*decl_handler) (tree *node, tree name, tree args, + int flags, bool *no_add_attrs); + tree (*type_handler) (tree *node, tree name, tree args, int flags, bool *no_add_attrs); /* Specifies if attribute affects type's identity. */ bool affects_type_identity; diff --git a/gcc/tree.c b/gcc/tree.c index e8a3f156dd0..d45e051d5de 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -6109,42 +6109,16 @@ merge_dllimport_decl_attributes (tree old, tree new_tree) return a; } -/* Handle a "dllimport" or "dllexport" attribute; arguments as in +/* Handle a "dllimport" or "dllexport" attribute for decls; arguments as in struct attribute_spec.handler. */ tree -handle_dll_attribute (tree * pnode, tree name, tree args, int flags, - bool *no_add_attrs) +handle_dll_decl_attribute (tree * pnode, tree name, tree args, int flags, + bool *no_add_attrs) { tree node = *pnode; bool is_dllimport; - /* These attributes may apply to structure and union types being created, - but otherwise should pass to the declaration involved. */ - if (!DECL_P (node)) - { - if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT - | (int) ATTR_FLAG_ARRAY_NEXT)) - { - *no_add_attrs = true; - return tree_cons (name, args, NULL_TREE); - } - if (TREE_CODE (node) == RECORD_TYPE - || TREE_CODE (node) == UNION_TYPE) - { - node = TYPE_NAME (node); - if (!node) - return NULL_TREE; - } - else - { - warning (OPT_Wattributes, "%qE attribute ignored", - name); - *no_add_attrs = true; - return NULL_TREE; - } - } - if (TREE_CODE (node) != FUNCTION_DECL && TREE_CODE (node) != VAR_DECL && TREE_CODE (node) != TYPE_DECL) @@ -6246,6 +6220,39 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, return NULL_TREE; } + +/* Handle a "dllimport" or "dllexport" attribute for types; arguments as in + struct attribute_spec.handler. */ + +tree +handle_dll_type_attribute (tree * pnode, tree name, tree args, int flags, + bool *no_add_attrs) +{ + tree node = *pnode; + + /* These attributes may apply to structure and union types being created, + but otherwise should pass to the declaration involved. */ + if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT + | (int) ATTR_FLAG_ARRAY_NEXT)) + { + *no_add_attrs = true; + return tree_cons (name, args, NULL_TREE); + } + + if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + return NULL_TREE; + } + + if (!TYPE_NAME (node)) + return NULL_TREE; + + return handle_dll_decl_attribute (&TYPE_NAME (node), name, args, flags, + no_add_attrs); +} + #endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES */ /* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask diff --git a/gcc/tree.h b/gcc/tree.h index 086313e9401..2aaa2137706 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3892,7 +3892,8 @@ extern tree merge_attributes (tree, tree); extern tree merge_dllimport_decl_attributes (tree, tree); /* Handle a "dllimport" or "dllexport" attribute. */ -extern tree handle_dll_attribute (tree *, tree, tree, int, bool *); +extern tree handle_dll_decl_attribute (tree *, tree, tree, int, bool *); +extern tree handle_dll_type_attribute (tree *, tree, tree, int, bool *); #endif /* Returns true iff unqualified CAND and BASE are equivalent. */ -- 2.11.4.GIT