This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Table-driven attributes patch
- To: <gcc-patches at gcc dot gnu dot org>
- Subject: Table-driven attributes patch
- From: "Joseph S. Myers" <jsm28 at cam dot ac dot uk>
- Date: Wed, 19 Sep 2001 21:53:37 +0100 (BST)
This patch implements table-driven attribute handling, as previously
discussed (e.g.,
<URL:http://gcc.gnu.org/ml/gcc-patches/2001-07/msg00826.html>,
<URL:http://gcc.gnu.org/ml/gcc/2001-07/msg00872.html>).
Because of the way various related issues seemed to be interdependent
on implementation, this patch does more and took longer to finish than
I'd originally intended when I started it:
* c-common attributes are made table-driven; so are the C++ front-end
ones and all the machine attributes.
* The C front end will handle attributes on nested declarators
properly; the bug in how the C++ front end handles them noted in
<URL:http://gcc.gnu.org/ml/gcc/2001-07/msg00106.html> is fixed.
Documentation is added about the problems with the semantics of
attributes in C++ and warning of the possible deprecation of nested
attributes in C++ per
<URL:http://gcc.gnu.org/ml/gcc/2001-07/msg01607.html>.
* However, useful support for the c-common attributes to be nested is
not added; for example, doing this for noreturn requires various
places in the compiler checking TREE_THIS_VOLATILE on decls to
change to checking the types of those decls (see
<URL:http://gcc.gnu.org/ml/gcc/2001-07/msg01676.html>), and doing
this for format and format_arg attributes will require the support
to be written for the default format and format_arg attributes to be
added lazily when the relevant decls are created. (However, once
this support is done, the fragile use of DECL_ASSEMBLER_NAME in
format checking can go away, as well as providing a user-demanded
feature by supporting format attributes on function pointers.)
* Attributes in general, rather than just machine ones, get stored
with the corresponding decls and types. DECL_MACHINE_ATTRIBUTES is
renamed to DECL_ATTRIBUTES.
* Multiple attributes with the same name and different arguments are
allowed to be applied to the same decl or type. This is in
preparation for the handling of format_arg attributes as applying to
a type rather than a function name or assembler name - multiple
format_arg attributes is natural for the GNU function ngettext, and
the latest GNU libc has them; with current GCC this silently falls
back to considering the last format_arg attribute on a function
only.
* The various ad hoc cases of some machine attributes only being
understood in the __-form, or in the non-__ form, are regularised:
all attributes are understood in both forms after this patch.
There are some points about the existing code I noticed:
* Some code in the c4x back end treats the "naked" attribute as a
synonym of "interrupt", but c4x_valid_type_attribute_p doesn't
recognise "naked".
* Various targetm.valid_type_attribute functions check for TYPE_DECL
and FIELD_DECL - but those tree codes aren't types, and I don't see
how the functions could ever be called in a case where those codes
apply. I've retained the checks, but think they have probably been
useless all along.
* As discussed in other/1078, which I've sent an update to, many
target attributes are still undocumented.
Bootstrapped with no regressions on i686-pc-linux-gnu. In case this
patch counts as a major change, also cross-tested to simulators with
no regressions for powerpc-eabisim and mn10300-elf. Sanity-checked by
testing it build as far as building cc1 on crosses to alpha-dec-vms,
arc-elf, arm-elf, avr-elf, c4x-elf, h8300-elf, i386-cygwin32,
ia64-elf, m32r-elf, m68hc11-elf, mcore-elf, ns32k-netbsd, sh-elf,
stormy16-elf and v850-elf. OK to commit?
2001-09-19 Joseph S. Myers <jsm28@cam.ac.uk>
Table-driven attributes.
* c-decl.c, config/alpha/alpha.c, config/arc/arc.c,
config/arm/arm.c, config/arm/pe.c, config/avr/avr.c,
config/avr/avr.h, config/d30v/d30v.h, config/fr30/fr30.h,
config/h8300/h8300.c, config/i386/cygwin.h, config/i386/winnt.c,
config/m32r/m32r.c, config/mcore/mcore.c, config/sh/sh.c,
config/stormy16/stormy16.h, config/v850/v850.c, doc/c-tree.texi,
doc/tm.texi, ggc-common.c, integrate.c, print-tree.c, tree.c,
tree.h: Rename DECL_MACHINE_ATTRIBUTES to DECL_ATTRIBUTES.
* tree.h (struct tree_decl): Change machine_attributes to
attributes.
* doc/c-tree.texi: Document that all attributes are now attached
to decls and types.
* c-common.c (add_attribute, attrtab, attrtab_idx,
default_valid_lang_attribute, valid_lang_attribute): Remove.
(attribute_tables, attributes_initialized,
c_common_attribute_table, default_lang_attribute_table): New
variables.
(handle_packed_attribute, handle_nocommon_attribute,
handle_common_attribute, handle_noreturn_attribute,
handle_unused_attribute, handle_const_attribute,
handle_transparent_union_attribute, handle_constructor_attribute,
handle_destructor_attribute, handle_mode_attribute,
handle_section_attribute, handle_aligned_attribute,
handle_weak_attribute, handle_alias_attribute,
handle_no_instrument_function_attribute,
handle_no_check_memory_usage_attribute, handle_malloc_attribute,
handle_no_limit_stack_attribute, handle_pure_attribute): New
functions.
(init_attributes, decl_attributes): Rewrite to implement
table-driven attributes.
* c-common.h (enum attribute_flags): Move to tree.h.
* c-format.c (decl_handle_format_attribute,
decl_handle_format_arg_attribute): Rename to
handle_format_attribute and handle_format_arg_attribute. Update
for table-driven attributes.
* c-common.h (decl_handle_format_attribute,
decl_handle_format_arg_attribute): Remove prototypes.
(handle_format_attribute, handle_format_arg_attribute): Add
prototypes.
* c-decl.c (grokdeclarator): Handle attributes nested inside
declarators.
* c-parse.in (setattrs, maybe_setattrs): Remove.
(maybe_type_quals_setattrs): Rename to maybe_type_quals_attrs.
Update to handle nested attributes properly.
(maybe_resetattrs, after_type_declarator,
parm_declarator_nostarttypename, notype_declarator, absdcl1_noea,
absdcl1_ea, direct_absdcl1): Update to handle nested attributes
properly.
(make_pointer_declarator): Update to handle nested attributes
properly.
* doc/extend.texi: Update documentation of limits of attributes
syntax. Warn about problems with attribute semantics in C++.
* target.h (struct target): Remove valid_decl_attribute and
valid_type_attribute. Add attribute_table and
function_attribute_inlinable_p.
* target-def.h (TARGET_VALID_DECL_ATTRIBUTE,
TARGET_VALID_TYPE_ATTRIBUTE): Remove.
(TARGET_ATTRIBUTE_TABLE, TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P):
Add.
(TARGET_INITIALIZER): Update.
* integrate.c (FUNCTION_ATTRIBUTE_INLINABLE_P): Remove default
definition.
(function_attribute_inlinable_p): New function. Check for the
presence of any machine attributes before using
targetm.function_attribute_inlinable_p.
(function_cannot_inline_p): Update.
* Makefile.in (integrate.o): Update dependencies.
* doc/tm.texi: Update documentation of target attributes and
example definition of TARGET_VALID_TYPE_ATTRIBUTE.
* tree.c (default_valid_attribute_p, valid_machine_attribute):
Remove.
(default_target_attribute_table,
default_function_attribute_inlinable_p): New.
(lookup_attribute): Update comment to clarify handling of multiple
attributes with the same name.
(merge_attributes, attribute_list_contained): Allow multiple
attributes with the same name but different arguments to appear in
the same attribute list.
* tree.h (default_valid_attribute_p): Remove prototype.
(struct attribute_spec): New.
(default_target_attribute_table): Declare.
(enum attribute_flags): Move from c-common.h. Add
ATTR_FLAG_TYPE_IN_PLACE.
(default_function_attribute_inlinable_p): Declare.
* config/alpha/alpha.c (vms_valid_decl_attribute_p): Remove.
(TARGET_VALID_DECL_ATTRIBUTE): Don't define.
(TARGET_ATTRIBUTE_TABLE): Define.
(vms_attribute_table): New.
* config/arc/arc.c (arc_valid_decl_attribute): Remove.
(TARGET_VALID_DECL_ATTRIBUTE): Don't define.
(TARGET_ATTRIBUTE_TABLE): Define.
(arc_attribute_table, arc_handle_interrupt_attribute): New.
* config/arm/arm.c (arm_valid_type_attribute_p,
arm_valid_decl_attribute_p, arm_pe_valid_decl_attribute_p):
Remove.
(TARGET_VALID_TYPE_ATTRIBUTE, TARGET_VALID_DECL_ATTRIBUTE): Don't
define.
(TARGET_ATTRIBUTE_TABLE): Define.
(arm_attribute_table, arm_handle_fndecl_attribute,
arm_handle_isr_attribute): New.
* config/avr/avr.c (avr_valid_type_attribute,
avr_valid_decl_attribute): Remove.
(TARGET_VALID_DECL_ATTRIBUTE, TARGET_VALID_TYPE_ATTRIBUTE): Don't
define.
(TARGET_ATTRIBUTE_TABLE): Define.
(avr_attribute_table, avr_handle_progmem_attribute,
avr_handle_fndecl_attribute): New.
* config/c4x/c4x.c (c4x_valid_type_attribute_p): Remove.
(TARGET_VALID_TYPE_ATTRIBUTE): Don't define.
(TARGET_ATTRIBUTE_TABLE): Define.
(c4x_attribute_table, c4x_handle_fntype_attribute): New.
* config/h8300/h8300.c (h8300_valid_decl_attribute): Remove.
(TARGET_VALID_DECL_ATTRIBUTE): Don't define.
(TARGET_ATTRIBUTE_TABLE): Define.
(h8300_attribute_table, h8300_handle_fndecl_attribute,
h8300_handle_eightbit_data_attribute,
h8300_handle_tiny_data_attribute): New.
* config/i386/i386-protos.h (ix86_valid_type_attribute_p,
i386_pe_valid_decl_attribute_p, i386_pe_valid_type_attribute_p):
Remove prototypes.
(ix86_handle_dll_attribute, ix86_handle_shared_attribute): New
declarations.
* config/i386/i386.c (ix86_valid_type_attribute_p: Remove.
(TARGET_VALID_TYPE_ATTRIBUTE, TARGET_VALID_DECL_ATTRIBUTE): Don't
define.
(TARGET_ATTRIBUTE_TABLE): Define.
(ix86_attribute_table, ix86_handle_cdecl_attribute,
ix86_handle_regparm_attribute): New.
* config/i386/winnt.c (i386_pe_valid_decl_attribute_p,
i386_pe_valid_type_attribute_p): Remove.
(ix86_handle_dll_attribute, ix86_handle_shared_attribute): New.
* config/ia64/ia64.c (ia64_valid_type_attribute): Remove.
(TARGET_VALID_TYPE_ATTRIBUTE): Don't define.
(TARGET_ATTRIBUTE_TABLE): Define.
(ia64_attribute_table): New.
* config/m32r/m32r.c (m32r_valid_decl_attribute, interrupt_ident1,
interrupt_ident2, model_ident1, model_ident2): Remove.
(TARGET_VALID_DECL_ATTRIBUTE): Don't define.
(TARGET_ATTRIBUTE_TABLE): Define.
(init_idents): Update.
(m32r_attribute_table, m32r_handle_model_attribute): New.
* config/m68hc11/m68hc11.c (m68hc11_valid_type_attribute_p):
Remove.
(TARGET_VALID_TYPE_ATTRIBUTE): Don't define.
(TARGET_ATTRIBUTE_TABLE): Define.
(m68hc11_attribute_table, m68hc11_handle_fntype_attribute): New.
* config/mcore/mcore.c (mcore_valid_decl_attribute): Remove.
(TARGET_VALID_DECL_ATTRIBUTE): Don't define.
(TARGET_ATTRIBUTE_TABLE): Define.
(mcore_attribute_table, mcore_handle_naked_attribute): New.
* config/ns32k/ns32k.c (ns32k_valid_type_attribute_p): Remove.
(TARGET_VALID_TYPE_ATTRIBUTE): Don't define.
(TARGET_ATTRIBUTE_TABLE): Define.
(ns32k_attribute_table, ns32k_handle_fntype_attribute): New.
* config/rs6000/rs6000.c (rs6000_valid_type_attribute_p): Remove.
(TARGET_VALID_TYPE_ATTRIBUTE): Don't define.
(TARGET_ATTRIBUTE_TABLE): Define.
(rs6000_attribute_table, rs6000_handle_longcall_attribute): New.
* config/sh/sh.c (sh_valid_decl_attribute): Remove.
(TARGET_VALID_DECL_ATTRIBUTE): Don't define.
(TARGET_ATTRIBUTE_TABLE): Define.
(sh_attribute_table, sh_handle_interrupt_handler_attribute,
sh_handle_sp_switch_attribute, sh_handle_trap_exit_attribute):
New.
* config/stormy16/stormy16.c (stormy16_valid_type_attribute):
Remove.
(TARGET_VALID_TYPE_ATTRIBUTE): Don't define
(TARGET_ATTRIBUTE_TABLE): Define.
(stormy16_attribute_table, stormy16_handle_interrupt_attribute):
New.
* config/v850/v850.c (v850_valid_decl_attribute): Remove.
(TARGET_VALID_DECL_ATTRIBUTE): Don't define.
(TARGET_ATTRIBUTE_TABLE): Define.
(v850_attribute_table, v850_handle_interrupt_attribute,
v850_handle_data_area_attribute): New.
* config/v850/v850-c.c (mark_current_function_as_interrupt):
Return void. Call decl_attributes instead of
valid_machine_attribute.
cp:
2001-09-19 Joseph S. Myers <jsm28@cam.ac.uk>
Table-driven attributes.
* decl.c: Rename DECL_MACHINE_ATTRIBUTES to DECL_ATTRIBUTES.
* decl2.c (cplus_decl_attributes): Only take one attributes
parameter.
* cp-tree.c (cplus_decl_attributes): Update prototype.
* class.c (finish_struct), decl.c (start_decl, start_function),
decl2.c (grokfield), friend.c (do_friend), parse.y
(parse_bitfield): Update calls to cplus_decl_attributes.
* decl.c (grokdeclarator): Take a pointer to a single ordinary
attribute list.
* decl.h (grokdeclarator): Update prototype.
* decl2.c (grokfield): Take a single ordinary attribute list.
* friend.c (do_friend): Likewise.
* decl.c (shadow_tag, groktypename, start_decl,
start_handler_parms, grokdeclarator, grokparms, start_function,
start_method), decl2.c (grokfield, grokbitfield, grokoptypename),
parse.y (parse_field, parse_bitfield, component_decl_1), pt.c
(process_template_parm, do_decl_instantiation): Pass single
ordinary attribute lists around.
* decl.c (grokdeclarator): Correct handling of nested attributes.
Revert the patch
1998-10-18 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokdeclarator): Embedded attrs bind to the right,
not the left.
.
* cp-tree.h (cp_valid_lang_attribute): Remove declaration
(cp_attribute_table): Declare.
* decl.c (valid_lang_attribute): Don't define.
(lang_attribute_table): Define.
(init_decl_processing): Initialize lang_attribute_table instead of
valid_lang_attribute.
* tree.c (cp_valid_lang_attribute): Remove.
(handle_java_interface_attribute, handle_com_interface_attribute,
handle_init_priority_attribute): New functions.
(cp_attribute_table): New array.
* decl2.c (import_export_class): Don't use
targetm.valid_type_attribute.
testsuite:
2001-09-19 Joseph S. Myers <jsm28@cam.ac.uk>
Table-driven attributes.
* g++.dg/ext/attrib1.C: New test.
diff -rcpN gcc.orig/Makefile.in gcc/Makefile.in
*** gcc.orig/Makefile.in Fri Aug 31 19:44:17 2001
--- gcc/Makefile.in Wed Sep 5 08:12:12 2001
*************** real.o : real.c $(CONFIG_H) $(SYSTEM_H)
*** 1435,1441 ****
integrate.o : integrate.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
debug.h $(INTEGRATE_H) insn-config.h $(EXPR_H) real.h $(REGS_H) \
intl.h function.h output.h $(RECOG_H) except.h toplev.h $(LOOP_H) \
! $(PARAMS_H) $(TM_P_H)
jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h hard-reg-set.h $(REGS_H) \
insn-config.h $(RECOG_H) $(EXPR_H) real.h except.h function.h \
toplev.h $(INSN_ATTR_H) $(TM_P_H) reload.h $(PREDICT_H)
--- 1435,1441 ----
integrate.o : integrate.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
debug.h $(INTEGRATE_H) insn-config.h $(EXPR_H) real.h $(REGS_H) \
intl.h function.h output.h $(RECOG_H) except.h toplev.h $(LOOP_H) \
! $(PARAMS_H) $(TM_P_H) $(TARGET_H)
jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h hard-reg-set.h $(REGS_H) \
insn-config.h $(RECOG_H) $(EXPR_H) real.h except.h function.h \
toplev.h $(INSN_ATTR_H) $(TM_P_H) reload.h $(PREDICT_H)
diff -rcpN gcc.orig/c-common.c gcc/c-common.c
*** gcc.orig/c-common.c Fri Aug 24 18:20:43 2001
--- gcc/c-common.c Wed Sep 19 09:55:59 2001
*************** const struct fname_var_t fname_vars[] =
*** 243,252 ****
{NULL, 0, 0},
};
- static void add_attribute PARAMS ((enum attrs, const char *,
- int, int, int));
static void init_attributes PARAMS ((void));
- static int default_valid_lang_attribute PARAMS ((tree, tree, tree, tree));
static int constant_fits_type_p PARAMS ((tree, tree));
/* Keep a stack of if statements. We record the number of compound
--- 243,249 ----
*************** combine_strings (strings)
*** 640,1153 ****
return value;
}
! /* To speed up processing of attributes, we maintain an array of
! IDENTIFIER_NODES and the corresponding attribute types. */
! /* Array to hold attribute information. */
! static struct {enum attrs id; tree name; int min, max, decl_req;} attrtab[50];
! static int attrtab_idx = 0;
! /* Add an entry to the attribute table above. */
! static void
! add_attribute (id, string, min_len, max_len, decl_req)
! enum attrs id;
! const char *string;
! int min_len, max_len;
! int decl_req;
! {
! char buf[100];
!
! attrtab[attrtab_idx].id = id;
! attrtab[attrtab_idx].name = get_identifier (string);
! attrtab[attrtab_idx].min = min_len;
! attrtab[attrtab_idx].max = max_len;
! attrtab[attrtab_idx++].decl_req = decl_req;
!
! sprintf (buf, "__%s__", string);
!
! attrtab[attrtab_idx].id = id;
! attrtab[attrtab_idx].name = get_identifier (buf);
! attrtab[attrtab_idx].min = min_len;
! attrtab[attrtab_idx].max = max_len;
! attrtab[attrtab_idx++].decl_req = decl_req;
! }
! /* Initialize attribute table. */
static void
init_attributes ()
{
! add_attribute (A_PACKED, "packed", 0, 0, 0);
! add_attribute (A_NOCOMMON, "nocommon", 0, 0, 1);
! add_attribute (A_COMMON, "common", 0, 0, 1);
! add_attribute (A_NORETURN, "noreturn", 0, 0, 1);
! add_attribute (A_NORETURN, "volatile", 0, 0, 1);
! add_attribute (A_UNUSED, "unused", 0, 0, 0);
! add_attribute (A_CONST, "const", 0, 0, 1);
! add_attribute (A_T_UNION, "transparent_union", 0, 0, 0);
! add_attribute (A_CONSTRUCTOR, "constructor", 0, 0, 1);
! add_attribute (A_DESTRUCTOR, "destructor", 0, 0, 1);
! add_attribute (A_MODE, "mode", 1, 1, 1);
! add_attribute (A_SECTION, "section", 1, 1, 1);
! add_attribute (A_ALIGNED, "aligned", 0, 1, 0);
! add_attribute (A_FORMAT, "format", 3, 3, 1);
! add_attribute (A_FORMAT_ARG, "format_arg", 1, 1, 1);
! add_attribute (A_WEAK, "weak", 0, 0, 1);
! add_attribute (A_ALIAS, "alias", 1, 1, 1);
! add_attribute (A_NO_INSTRUMENT_FUNCTION, "no_instrument_function", 0, 0, 1);
! add_attribute (A_NO_CHECK_MEMORY_USAGE, "no_check_memory_usage", 0, 0, 1);
! add_attribute (A_MALLOC, "malloc", 0, 0, 1);
! add_attribute (A_NO_LIMIT_STACK, "no_stack_limit", 0, 0, 1);
! add_attribute (A_PURE, "pure", 0, 0, 1);
}
- /* Default implementation of valid_lang_attribute, below. By default, there
- are no language-specific attributes. */
-
- static int
- default_valid_lang_attribute (attr_name, attr_args, decl, type)
- tree attr_name ATTRIBUTE_UNUSED;
- tree attr_args ATTRIBUTE_UNUSED;
- tree decl ATTRIBUTE_UNUSED;
- tree type ATTRIBUTE_UNUSED;
- {
- return 0;
- }
-
- /* Return a 1 if ATTR_NAME and ATTR_ARGS denote a valid language-specific
- attribute for either declaration DECL or type TYPE and 0 otherwise. */
-
- int (*valid_lang_attribute) PARAMS ((tree, tree, tree, tree))
- = default_valid_lang_attribute;
-
/* 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.
! FLAGS gives further information, in the form of a bitwise OR of flags
! in enum attribute_flags from c-common.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
decl_attributes (node, attributes, flags)
tree *node, attributes;
! int flags ATTRIBUTE_UNUSED;
{
- tree decl = 0, type = 0;
- int is_type = 0;
tree a;
! if (attrtab_idx == 0)
init_attributes ();
- 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;
-
(*targetm.insert_attributes) (*node, &attributes);
for (a = attributes; a; a = TREE_CHAIN (a))
{
tree name = TREE_PURPOSE (a);
tree args = TREE_VALUE (a);
int i;
- enum attrs id;
! for (i = 0; i < attrtab_idx; i++)
! if (attrtab[i].name == name)
! break;
!
! if (i == attrtab_idx)
! {
! if (! valid_machine_attribute (name, args, decl, type)
! && ! (* valid_lang_attribute) (name, args, decl, type))
! warning ("`%s' attribute directive ignored",
! IDENTIFIER_POINTER (name));
! else if (decl != 0)
! type = TREE_TYPE (decl);
! continue;
}
! else if (attrtab[i].decl_req && decl == 0)
{
! warning ("`%s' attribute does not apply to types",
IDENTIFIER_POINTER (name));
continue;
}
! else if (list_length (args) < attrtab[i].min
! || list_length (args) > attrtab[i].max)
{
error ("wrong number of arguments specified for `%s' attribute",
IDENTIFIER_POINTER (name));
continue;
}
! id = attrtab[i].id;
! switch (id)
{
! case A_PACKED:
! if (is_type)
! TYPE_PACKED (type) = 1;
! else if (TREE_CODE (decl) == FIELD_DECL)
! DECL_PACKED (decl) = 1;
! /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
! used for DECL_REGISTER. It wouldn't mean anything anyway. */
! else
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! break;
!
! case A_NOCOMMON:
! if (TREE_CODE (decl) == VAR_DECL)
! DECL_COMMON (decl) = 0;
! else
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! break;
!
! case A_COMMON:
! if (TREE_CODE (decl) == VAR_DECL)
! DECL_COMMON (decl) = 1;
! else
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! break;
!
! case A_NORETURN:
! if (TREE_CODE (decl) == FUNCTION_DECL)
! TREE_THIS_VOLATILE (decl) = 1;
! else if (TREE_CODE (type) == POINTER_TYPE
! && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
! TREE_TYPE (decl) = type
! = build_pointer_type
! (build_type_variant (TREE_TYPE (type),
! TREE_READONLY (TREE_TYPE (type)), 1));
! else
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! break;
!
! case A_MALLOC:
! if (TREE_CODE (decl) == FUNCTION_DECL)
! DECL_IS_MALLOC (decl) = 1;
! /* ??? TODO: Support types. */
else
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! break;
! case A_UNUSED:
! if (is_type)
! if (decl)
! TREE_USED (decl) = 1;
! else
! TREE_USED (type) = 1;
! else if (TREE_CODE (decl) == PARM_DECL
! || TREE_CODE (decl) == VAR_DECL
! || TREE_CODE (decl) == FUNCTION_DECL
! || TREE_CODE (decl) == LABEL_DECL)
! TREE_USED (decl) = 1;
! else
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! break;
! case A_CONST:
! if (TREE_CODE (decl) == FUNCTION_DECL)
! TREE_READONLY (decl) = 1;
! else if (TREE_CODE (type) == POINTER_TYPE
! && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
! TREE_TYPE (decl) = type
! = build_pointer_type
! (build_type_variant (TREE_TYPE (type), 1,
! TREE_THIS_VOLATILE (TREE_TYPE (type))));
! else
! warning ( "`%s' attribute ignored", IDENTIFIER_POINTER (name));
! break;
! case A_PURE:
! if (TREE_CODE (decl) == FUNCTION_DECL)
! DECL_IS_PURE (decl) = 1;
! /* ??? TODO: Support types. */
! else
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! break;
! case A_T_UNION:
! if (is_type
! && TREE_CODE (type) == UNION_TYPE
! && (decl == 0
! || (TYPE_FIELDS (type) != 0
! && TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type)))))
! TYPE_TRANSPARENT_UNION (type) = 1;
! else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
! && TREE_CODE (type) == UNION_TYPE
! && TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type)))
! DECL_TRANSPARENT_UNION (decl) = 1;
else
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! break;
! case A_CONSTRUCTOR:
! if (TREE_CODE (decl) == FUNCTION_DECL
! && TREE_CODE (type) == FUNCTION_TYPE
! && decl_function_context (decl) == 0)
{
! DECL_STATIC_CONSTRUCTOR (decl) = 1;
! TREE_USED (decl) = 1;
}
- else
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- break;
! case A_DESTRUCTOR:
! if (TREE_CODE (decl) == FUNCTION_DECL
! && TREE_CODE (type) == FUNCTION_TYPE
! && decl_function_context (decl) == 0)
{
! DECL_STATIC_DESTRUCTOR (decl) = 1;
! TREE_USED (decl) = 1;
}
! else
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! break;
! case A_MODE:
! if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! else
! {
! int j;
! const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
! int len = strlen (p);
! enum machine_mode mode = VOIDmode;
! tree typefm;
! if (len > 4 && p[0] == '_' && p[1] == '_'
! && p[len - 1] == '_' && p[len - 2] == '_')
! {
! char *newp = (char *) alloca (len - 1);
! strcpy (newp, &p[2]);
! newp[len - 4] = '\0';
! p = newp;
! }
! /* Give this decl a type with the specified mode.
! First check for the special modes. */
! if (! strcmp (p, "byte"))
! mode = byte_mode;
! else if (!strcmp (p, "word"))
! mode = word_mode;
! else if (! strcmp (p, "pointer"))
! mode = ptr_mode;
! else
! for (j = 0; j < NUM_MACHINE_MODES; j++)
! if (!strcmp (p, GET_MODE_NAME (j)))
! mode = (enum machine_mode) j;
!
! if (mode == VOIDmode)
! error ("unknown machine mode `%s'", p);
! else if (0 == (typefm = type_for_mode (mode,
! TREE_UNSIGNED (type))))
! error ("no data type for mode `%s'", p);
! else
! {
! if (TYPE_PRECISION (typefm) > (TREE_UNSIGNED (type)
! ? TYPE_PRECISION(uintmax_type_node)
! : TYPE_PRECISION(intmax_type_node))
! && pedantic)
! pedwarn ("type with more precision than %s",
! TREE_UNSIGNED (type) ? "uintmax_t" : "intmax_t");
! TREE_TYPE (decl) = type = typefm;
! DECL_SIZE (decl) = DECL_SIZE_UNIT (decl) = 0;
! if (TREE_CODE (decl) != FIELD_DECL)
! layout_decl (decl, 0);
! }
! }
! break;
! case A_SECTION:
! if (targetm.have_named_sections)
! {
! if ((TREE_CODE (decl) == FUNCTION_DECL
! || TREE_CODE (decl) == VAR_DECL)
! && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
! {
! if (TREE_CODE (decl) == VAR_DECL
! && current_function_decl != NULL_TREE
! && ! TREE_STATIC (decl))
! error_with_decl (decl,
! "section attribute cannot be specified for local variables");
! /* The decl may have already been given a section attribute
! from a previous declaration. Ensure they match. */
! else if (DECL_SECTION_NAME (decl) != NULL_TREE
! && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
! TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
! error_with_decl (*node,
! "section of `%s' conflicts with previous declaration");
! else
! DECL_SECTION_NAME (decl) = TREE_VALUE (args);
! }
! else
! error_with_decl (*node,
! "section attribute not allowed for `%s'");
! }
! else
! error_with_decl (*node,
! "section attributes are not supported for this target");
! break;
!
! case A_ALIGNED:
! {
! tree align_expr
! = (args ? TREE_VALUE (args)
! : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
! int i;
!
! /* Strip any NOPs of any kind. */
! while (TREE_CODE (align_expr) == NOP_EXPR
! || TREE_CODE (align_expr) == CONVERT_EXPR
! || TREE_CODE (align_expr) == NON_LVALUE_EXPR)
! align_expr = TREE_OPERAND (align_expr, 0);
!
! if (TREE_CODE (align_expr) != INTEGER_CST)
! {
! error ("requested alignment is not a constant");
! continue;
! }
!
! if ((i = tree_log2 (align_expr)) == -1)
! error ("requested alignment is not a power of 2");
! else if (i > HOST_BITS_PER_INT - 2)
! error ("requested alignment is too large");
! else if (is_type)
! {
! /* If we have a TYPE_DECL, then copy the type, so that we
! don't accidentally modify a builtin type. See pushdecl. */
! if (decl && TREE_TYPE (decl) != error_mark_node
! && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
! {
! tree tt = TREE_TYPE (decl);
! DECL_ORIGINAL_TYPE (decl) = tt;
! tt = build_type_copy (tt);
! TYPE_NAME (tt) = decl;
! TREE_USED (tt) = TREE_USED (decl);
! TREE_TYPE (decl) = tt;
! type = tt;
! }
!
! TYPE_ALIGN (type) = (1 << i) * BITS_PER_UNIT;
! TYPE_USER_ALIGN (type) = 1;
! }
! else if (TREE_CODE (decl) != VAR_DECL
! && TREE_CODE (decl) != FIELD_DECL)
! error_with_decl (decl,
! "alignment may not be specified for `%s'");
! else
! {
! DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
! DECL_USER_ALIGN (decl) = 1;
! }
! }
! break;
!
! case A_FORMAT:
! decl_handle_format_attribute (decl, args);
! break;
!
! case A_FORMAT_ARG:
! decl_handle_format_arg_attribute (decl, args);
! break;
!
! case A_WEAK:
! declare_weak (decl);
! break;
!
! case A_ALIAS:
! if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
! || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
! error_with_decl (decl,
! "`%s' defined both normally and as an alias");
! else if (decl_function_context (decl) == 0)
! {
! tree id;
! id = TREE_VALUE (args);
! if (TREE_CODE (id) != STRING_CST)
! {
! error ("alias arg not a string");
! break;
! }
! id = get_identifier (TREE_STRING_POINTER (id));
! /* This counts as a use of the object pointed to. */
! TREE_USED (id) = 1;
! if (TREE_CODE (decl) == FUNCTION_DECL)
! DECL_INITIAL (decl) = error_mark_node;
! else
! DECL_EXTERNAL (decl) = 0;
! assemble_alias (decl, id);
! }
! else
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! break;
! case A_NO_CHECK_MEMORY_USAGE:
! if (TREE_CODE (decl) != FUNCTION_DECL)
! {
! error_with_decl (decl,
! "`%s' attribute applies only to functions",
! IDENTIFIER_POINTER (name));
! }
! else if (DECL_INITIAL (decl))
! {
! error_with_decl (decl,
! "can't set `%s' attribute after definition",
! IDENTIFIER_POINTER (name));
! }
! else
! DECL_NO_CHECK_MEMORY_USAGE (decl) = 1;
! break;
! case A_NO_INSTRUMENT_FUNCTION:
! if (TREE_CODE (decl) != FUNCTION_DECL)
! {
! error_with_decl (decl,
! "`%s' attribute applies only to functions",
! IDENTIFIER_POINTER (name));
! }
! else if (DECL_INITIAL (decl))
! {
! error_with_decl (decl,
! "can't set `%s' attribute after definition",
! IDENTIFIER_POINTER (name));
! }
! else
! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
! break;
! case A_NO_LIMIT_STACK:
! if (TREE_CODE (decl) != FUNCTION_DECL)
{
error_with_decl (decl,
! "`%s' attribute applies only to functions",
! IDENTIFIER_POINTER (name));
}
! else if (DECL_INITIAL (decl))
{
! error_with_decl (decl,
! "can't set `%s' attribute after definition",
! IDENTIFIER_POINTER (name));
}
else
! DECL_NO_LIMIT_STACK (decl) = 1;
! break;
}
}
return NULL_TREE;
}
--- 637,1630 ----
return value;
}
! /* Table of the tables of attributes (common, language, machine) searched. */
! static const struct attribute_spec *attribute_tables[3];
! static bool attributes_initialized = false;
! static tree handle_packed_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_nocommon_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_common_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_noreturn_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_unused_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_const_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_transparent_union_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_constructor_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_destructor_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_mode_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_section_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_aligned_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_weak_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_alias_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_no_instrument_function_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_no_check_memory_usage_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_malloc_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_no_limit_stack_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree handle_pure_attribute PARAMS ((tree *, tree, tree, int, bool *));
! /* Table of machine-independent attributes common to all C-like languages. */
! static const struct attribute_spec c_common_attribute_table[] =
! {
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "packed", 0, 0, false, false, false, handle_packed_attribute },
! { "nocommon", 0, 0, true, false, false, handle_nocommon_attribute },
! { "common", 0, 0, true, false, false, handle_common_attribute },
! /* FIXME: logically, noreturn attributes should be listed as
! "false, true, true" and apply to function types. But implementing this
! would require all the places in the compiler that use TREE_THIS_VOLATILE
! on a decl to identify non-returning functions to be located and fixed
! to check the function type instead. */
! { "noreturn", 0, 0, true, false, false, handle_noreturn_attribute },
! { "volatile", 0, 0, true, false, false, handle_noreturn_attribute },
! { "unused", 0, 0, false, false, false, handle_unused_attribute },
! /* The same comments as for noreturn attributes apply to const ones. */
! { "const", 0, 0, true, false, false, handle_const_attribute },
! { "transparent_union", 0, 0, false, false, false, handle_transparent_union_attribute },
! { "constructor", 0, 0, true, false, false, handle_constructor_attribute },
! { "destructor", 0, 0, true, false, false, handle_destructor_attribute },
! { "mode", 1, 1, true, false, false, handle_mode_attribute },
! { "section", 1, 1, true, false, false, handle_section_attribute },
! { "aligned", 0, 1, false, false, false, handle_aligned_attribute },
! { "format", 3, 3, true, false, false, handle_format_attribute },
! { "format_arg", 1, 1, true, false, false, handle_format_arg_attribute },
! { "weak", 0, 0, true, false, false, handle_weak_attribute },
! { "alias", 1, 1, true, false, false, handle_alias_attribute },
! { "no_instrument_function", 0, 0, true, false, false, handle_no_instrument_function_attribute },
! { "no_check_memory_usage", 0, 0, true, false, false, handle_no_check_memory_usage_attribute },
! { "malloc", 0, 0, true, false, false, handle_malloc_attribute },
! { "no_stack_limit", 0, 0, true, false, false, handle_no_limit_stack_attribute },
! { "pure", 0, 0, true, false, false, handle_pure_attribute },
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Default empty table of language attributes. */
! static const struct attribute_spec default_lang_attribute_table[] =
! {
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Table of machine-independent attributes for a particular language. */
! const struct attribute_spec *lang_attribute_table = default_lang_attribute_table;
! /* Initialize attribute tables, and make some sanity checks
! if --enable-checking. */
static void
init_attributes ()
{
! #ifdef ENABLE_CHECKING
! int i;
! #endif
! attribute_tables[0] = c_common_attribute_table;
! attribute_tables[1] = lang_attribute_table;
! attribute_tables[2] = targetm.attribute_table;
! #ifdef ENABLE_CHECKING
! /* Make some sanity checks on the attribute tables. */
! for (i = 0;
! i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
! i++)
! {
! int j;
! for (j = 0; attribute_tables[i][j].name != NULL; j++)
! {
! /* The name must not begin and end with __. */
! const char *name = attribute_tables[i][j].name;
! int len = strlen (name);
! if (name[0] == '_' && name[1] == '_'
! && name[len - 1] == '_' && name[len - 2] == '_')
! abort ();
! /* The minimum and maximum lengths must be consistent. */
! if (attribute_tables[i][j].min_length < 0)
! abort ();
! if (attribute_tables[i][j].max_length != -1
! && attribute_tables[i][j].max_length < attribute_tables[i][j].min_length)
! abort ();
! /* An attribute cannot require both a DECL and a TYPE. */
! if (attribute_tables[i][j].decl_required
! && attribute_tables[i][j].type_required)
! abort ();
! /* If an attribute requires a function type, in particular
! it requires a type. */
! if (attribute_tables[i][j].function_type_required
! && !attribute_tables[i][j].type_required)
! abort ();
! }
! }
! /* Check that each name occurs just once in each table. */
! for (i = 0;
! i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
! i++)
! {
! int j, k;
! for (j = 0; attribute_tables[i][j].name != NULL; j++)
! for (k = j + 1; attribute_tables[i][k].name != NULL; k++)
! if (!strcmp (attribute_tables[i][j].name,
! attribute_tables[i][k].name))
! abort ();
! }
! /* Check that no name occurs in more than one table. */
! for (i = 0;
! i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
! i++)
! {
! int j;
! for (j = i + 1;
! j < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
! j++)
! {
! int k, l;
! for (k = 0; attribute_tables[i][k].name != NULL; k++)
! for (l = 0; attribute_tables[j][l].name != NULL; l++)
! if (!strcmp (attribute_tables[i][k].name,
! attribute_tables[j][l].name))
! abort ();
! }
! }
! #endif
! attributes_initialized = true;
}
/* 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). */
tree
decl_attributes (node, attributes, flags)
tree *node, attributes;
! int flags;
{
tree a;
+ tree returned_attrs = NULL_TREE;
! if (!attributes_initialized)
init_attributes ();
(*targetm.insert_attributes) (*node, &attributes);
for (a = attributes; a; a = TREE_CHAIN (a))
{
tree name = TREE_PURPOSE (a);
tree args = TREE_VALUE (a);
+ tree *anode = node;
+ const struct attribute_spec *spec = NULL;
+ bool no_add_attrs = 0;
int i;
! for (i = 0;
! i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
! i++)
! {
! int j;
! for (j = 0; attribute_tables[i][j].name != NULL; j++)
! {
! if (is_attribute_p (attribute_tables[i][j].name, name))
! {
! spec = &attribute_tables[i][j];
! break;
! }
! }
! if (spec != NULL)
! break;
}
!
! if (spec == NULL)
{
! warning ("`%s' attribute directive ignored",
IDENTIFIER_POINTER (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 `%s' attribute",
IDENTIFIER_POINTER (name));
continue;
}
! 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 ("`%s' attribute does not apply to types",
! IDENTIFIER_POINTER (name));
! continue;
! }
! }
! if (spec->type_required && DECL_P (*anode))
! {
! anode = &TREE_TYPE (*anode);
! }
! 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))
! {
! if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
! *anode = build_type_copy (*anode);
! anode = &TREE_TYPE (*anode);
! }
! 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 ("`%s' attribute only applies to function types",
! IDENTIFIER_POINTER (name));
! continue;
! }
! }
+ if (spec->handler != NULL)
+ returned_attrs = chainon ((*spec->handler) (anode, name, args,
+ flags, &no_add_attrs),
+ returned_attrs);
+ if (!no_add_attrs)
+ {
+ tree old_attrs;
+ tree a;
! if (DECL_P (*anode))
! old_attrs = DECL_ATTRIBUTES (*anode);
else
! 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)
{
! /* 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);
! else
! *anode = build_type_attribute_variant (*anode,
! tree_cons (name, args,
! old_attrs));
}
! }
! }
! return returned_attrs;
! }
! /* Handle a "packed" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_packed_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags;
! bool *no_add_attrs;
! {
! tree *type = NULL;
! if (DECL_P (*node))
! {
! if (TREE_CODE (*node) == TYPE_DECL)
! type = &TREE_TYPE (*node);
! }
! else
! type = node;
! if (type)
! {
! if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
! *type = build_type_copy (*type);
! TYPE_PACKED (*type) = 1;
! }
! else if (TREE_CODE (*node) == FIELD_DECL)
! DECL_PACKED (*node) = 1;
! /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
! used for DECL_REGISTER. It wouldn't mean anything anyway. */
! else
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! return NULL_TREE;
! }
! /* Handle a "nocommon" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_nocommon_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (TREE_CODE (*node) == VAR_DECL)
! DECL_COMMON (*node) = 0;
! else
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! return NULL_TREE;
! }
! /* Handle a "common" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_common_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (TREE_CODE (*node) == VAR_DECL)
! DECL_COMMON (*node) = 1;
! else
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! return NULL_TREE;
! }
! /* Handle a "noreturn" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_noreturn_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! tree type = TREE_TYPE (*node);
! /* See FIXME comment in c_common_attribute_table. */
! if (TREE_CODE (*node) == FUNCTION_DECL)
! TREE_THIS_VOLATILE (*node) = 1;
! else if (TREE_CODE (type) == POINTER_TYPE
! && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
! TREE_TYPE (*node)
! = build_pointer_type (build_type_variant (TREE_TYPE (type),
! TREE_READONLY (TREE_TYPE (type)), 1));
! else
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
!
! return NULL_TREE;
! }
!
! /* Handle a "unused" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_unused_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags;
! bool *no_add_attrs;
! {
! if (DECL_P (*node))
! {
! tree decl = *node;
!
! if (TREE_CODE (decl) == PARM_DECL
! || TREE_CODE (decl) == VAR_DECL
! || TREE_CODE (decl) == FUNCTION_DECL
! || TREE_CODE (decl) == LABEL_DECL
! || TREE_CODE (decl) == TYPE_DECL)
! TREE_USED (decl) = 1;
! else
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! }
! else
! {
! if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
! *node = build_type_copy (*node);
! TREE_USED (*node) = 1;
! }
!
! return NULL_TREE;
! }
!
! /* Handle a "const" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_const_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! tree type = TREE_TYPE (*node);
!
! /* See FIXME comment on noreturn in c_common_attribute_table. */
! if (TREE_CODE (*node) == FUNCTION_DECL)
! TREE_READONLY (*node) = 1;
! else if (TREE_CODE (type) == POINTER_TYPE
! && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
! TREE_TYPE (*node)
! = build_pointer_type (build_type_variant (TREE_TYPE (type), 1,
! TREE_THIS_VOLATILE (TREE_TYPE (type))));
! else
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! return NULL_TREE;
! }
!
! /* Handle a "transparent_union" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_transparent_union_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags;
! bool *no_add_attrs;
! {
! tree decl = NULL_TREE;
! tree *type = NULL;
! int is_type = 0;
!
! if (DECL_P (*node))
! {
! decl = *node;
! type = &TREE_TYPE (decl);
! is_type = TREE_CODE (*node) == TYPE_DECL;
! }
! else if (TYPE_P (*node))
! type = node, is_type = 1;
!
! if (is_type
! && TREE_CODE (*type) == UNION_TYPE
! && (decl == 0
! || (TYPE_FIELDS (*type) != 0
! && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))))
! {
! if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
! *type = build_type_copy (*type);
! TYPE_TRANSPARENT_UNION (*type) = 1;
! }
! else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
! && TREE_CODE (*type) == UNION_TYPE
! && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))
! DECL_TRANSPARENT_UNION (decl) = 1;
! else
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
!
! return NULL_TREE;
! }
!
! /* Handle a "constructor" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_constructor_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! tree decl = *node;
! tree type = TREE_TYPE (decl);
!
! if (TREE_CODE (decl) == FUNCTION_DECL
! && TREE_CODE (type) == FUNCTION_TYPE
! && decl_function_context (decl) == 0)
! {
! DECL_STATIC_CONSTRUCTOR (decl) = 1;
! TREE_USED (decl) = 1;
! }
! else
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
!
! return NULL_TREE;
! }
!
! /* Handle a "destructor" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_destructor_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! tree decl = *node;
! tree type = TREE_TYPE (decl);
!
! if (TREE_CODE (decl) == FUNCTION_DECL
! && TREE_CODE (type) == FUNCTION_TYPE
! && decl_function_context (decl) == 0)
! {
! DECL_STATIC_DESTRUCTOR (decl) = 1;
! TREE_USED (decl) = 1;
! }
! else
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
!
! return NULL_TREE;
! }
!
! /* Handle a "mode" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_mode_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! tree decl = *node;
! tree type = TREE_TYPE (decl);
!
! *no_add_attrs = true;
!
! if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! else
! {
! int j;
! const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
! int len = strlen (p);
! enum machine_mode mode = VOIDmode;
! tree typefm;
!
! if (len > 4 && p[0] == '_' && p[1] == '_'
! && p[len - 1] == '_' && p[len - 2] == '_')
! {
! char *newp = (char *) alloca (len - 1);
!
! strcpy (newp, &p[2]);
! newp[len - 4] = '\0';
! p = newp;
! }
!
! /* Give this decl a type with the specified mode.
! First check for the special modes. */
! if (! strcmp (p, "byte"))
! mode = byte_mode;
! else if (!strcmp (p, "word"))
! mode = word_mode;
! else if (! strcmp (p, "pointer"))
! mode = ptr_mode;
! else
! for (j = 0; j < NUM_MACHINE_MODES; j++)
! if (!strcmp (p, GET_MODE_NAME (j)))
! mode = (enum machine_mode) j;
!
! if (mode == VOIDmode)
! error ("unknown machine mode `%s'", p);
! else if (0 == (typefm = type_for_mode (mode,
! TREE_UNSIGNED (type))))
! error ("no data type for mode `%s'", p);
! else
! {
! if (TYPE_PRECISION (typefm) > (TREE_UNSIGNED (type)
! ? TYPE_PRECISION(uintmax_type_node)
! : TYPE_PRECISION(intmax_type_node))
! && pedantic)
! pedwarn ("type with more precision than %s",
! TREE_UNSIGNED (type) ? "uintmax_t" : "intmax_t");
! TREE_TYPE (decl) = type = typefm;
! DECL_SIZE (decl) = DECL_SIZE_UNIT (decl) = 0;
! if (TREE_CODE (decl) != FIELD_DECL)
! layout_decl (decl, 0);
! }
! }
!
! return NULL_TREE;
! }
!
! /* Handle a "section" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_section_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name ATTRIBUTE_UNUSED;
! tree args;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! tree decl = *node;
!
! if (targetm.have_named_sections)
! {
! if ((TREE_CODE (decl) == FUNCTION_DECL
! || TREE_CODE (decl) == VAR_DECL)
! && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
! {
! if (TREE_CODE (decl) == VAR_DECL
! && current_function_decl != NULL_TREE
! && ! TREE_STATIC (decl))
{
error_with_decl (decl,
! "section attribute cannot be specified for local variables");
! *no_add_attrs = true;
}
! /* The decl may have already been given a section attribute
! from a previous declaration. Ensure they match. */
! else if (DECL_SECTION_NAME (decl) != NULL_TREE
! && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
! TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
{
! error_with_decl (*node,
! "section of `%s' conflicts with previous declaration");
! *no_add_attrs = true;
}
else
! DECL_SECTION_NAME (decl) = TREE_VALUE (args);
! }
! else
! {
! error_with_decl (*node,
! "section attribute not allowed for `%s'");
! *no_add_attrs = true;
! }
! }
! else
! {
! error_with_decl (*node,
! "section attributes are not supported for this target");
! *no_add_attrs = true;
! }
!
! return NULL_TREE;
! }
!
! /* Handle a "aligned" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_aligned_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name ATTRIBUTE_UNUSED;
! tree args;
! int flags;
! bool *no_add_attrs;
! {
! tree decl = NULL_TREE;
! tree *type = NULL;
! int is_type = 0;
! tree align_expr = (args ? TREE_VALUE (args)
! : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
! int i;
!
! if (DECL_P (*node))
! {
! decl = *node;
! type = &TREE_TYPE (decl);
! is_type = TREE_CODE (*node) == TYPE_DECL;
! }
! else if (TYPE_P (*node))
! type = node, is_type = 1;
!
! /* Strip any NOPs of any kind. */
! while (TREE_CODE (align_expr) == NOP_EXPR
! || TREE_CODE (align_expr) == CONVERT_EXPR
! || TREE_CODE (align_expr) == NON_LVALUE_EXPR)
! align_expr = TREE_OPERAND (align_expr, 0);
!
! if (TREE_CODE (align_expr) != INTEGER_CST)
! {
! error ("requested alignment is not a constant");
! *no_add_attrs = true;
! }
! else if ((i = tree_log2 (align_expr)) == -1)
! {
! error ("requested alignment is not a power of 2");
! *no_add_attrs = true;
! }
! else if (i > HOST_BITS_PER_INT - 2)
! {
! error ("requested alignment is too large");
! *no_add_attrs = true;
! }
! else if (is_type)
! {
! /* If we have a TYPE_DECL, then copy the type, so that we
! don't accidentally modify a builtin type. See pushdecl. */
! if (decl && TREE_TYPE (decl) != error_mark_node
! && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
! {
! tree tt = TREE_TYPE (decl);
! *type = build_type_copy (*type);
! DECL_ORIGINAL_TYPE (decl) = tt;
! TYPE_NAME (*type) = decl;
! TREE_USED (*type) = TREE_USED (decl);
! TREE_TYPE (decl) = *type;
! }
! else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
! *type = build_type_copy (*type);
!
! TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
! TYPE_USER_ALIGN (*type) = 1;
! }
! else if (TREE_CODE (decl) != VAR_DECL
! && TREE_CODE (decl) != FIELD_DECL)
! {
! error_with_decl (decl,
! "alignment may not be specified for `%s'");
! *no_add_attrs = true;
! }
! else
! {
! DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
! DECL_USER_ALIGN (decl) = 1;
! }
!
! return NULL_TREE;
! }
!
! /* Handle a "weak" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_weak_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name ATTRIBUTE_UNUSED;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs ATTRIBUTE_UNUSED;
! {
! declare_weak (*node);
!
! return NULL_TREE;
! }
!
! /* Handle an "alias" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_alias_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! tree decl = *node;
!
! if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
! || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
! {
! error_with_decl (decl,
! "`%s' defined both normally and as an alias");
! *no_add_attrs = true;
! }
! else if (decl_function_context (decl) == 0)
! {
! tree id;
!
! id = TREE_VALUE (args);
! if (TREE_CODE (id) != STRING_CST)
! {
! error ("alias arg not a string");
! *no_add_attrs = true;
! return NULL_TREE;
}
+ id = get_identifier (TREE_STRING_POINTER (id));
+ /* This counts as a use of the object pointed to. */
+ TREE_USED (id) = 1;
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ DECL_INITIAL (decl) = error_mark_node;
+ else
+ DECL_EXTERNAL (decl) = 0;
+ assemble_alias (decl, id);
+ }
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+ }
+
+ /* Handle a "no_instrument_function" attribute; arguments as in
+ struct attribute_spec.handler. */
+ static tree
+ handle_no_instrument_function_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+ {
+ tree decl = *node;
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ error_with_decl (decl,
+ "`%s' attribute applies only to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
}
+ else if (DECL_INITIAL (decl))
+ {
+ error_with_decl (decl,
+ "can't set `%s' attribute after definition",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
+
+ return NULL_TREE;
+ }
+
+ /* Handle a "no_check_memory_usage" attribute; arguments as in
+ struct attribute_spec.handler. */
+ static tree
+ handle_no_check_memory_usage_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+ {
+ tree decl = *node;
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ error_with_decl (decl,
+ "`%s' attribute applies only to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else if (DECL_INITIAL (decl))
+ {
+ error_with_decl (decl,
+ "can't set `%s' attribute after definition",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ DECL_NO_CHECK_MEMORY_USAGE (decl) = 1;
+
+ return NULL_TREE;
+ }
+
+ /* Handle a "malloc" attribute; arguments as in
+ struct attribute_spec.handler. */
+ static tree
+ handle_malloc_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+ {
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ DECL_IS_MALLOC (*node) = 1;
+ /* ??? TODO: Support types. */
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+ }
+
+ /* Handle a "no_limit_stack" attribute; arguments as in
+ struct attribute_spec.handler. */
+ static tree
+ handle_no_limit_stack_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+ {
+ tree decl = *node;
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ error_with_decl (decl,
+ "`%s' attribute applies only to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else if (DECL_INITIAL (decl))
+ {
+ error_with_decl (decl,
+ "can't set `%s' attribute after definition",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ DECL_NO_LIMIT_STACK (decl) = 1;
+
+ return NULL_TREE;
+ }
+
+ /* Handle a "pure" attribute; arguments as in
+ struct attribute_spec.handler. */
+ static tree
+ handle_pure_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+ {
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ DECL_IS_PURE (*node) = 1;
+ /* ??? TODO: Support types. */
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
return NULL_TREE;
}
diff -rcpN gcc.orig/c-common.h gcc/c-common.h
*** gcc.orig/c-common.h Wed Sep 5 07:47:51 2001
--- gcc/c-common.h Wed Sep 5 08:12:12 2001
*************** extern const char *fname_as_string PARA
*** 503,531 ****
extern tree fname_decl PARAMS ((unsigned, tree));
extern const char *fname_string PARAMS ((unsigned));
- /* Flags that may be passed in the third argument of decl_attributes. */
- enum attribute_flags
- {
- /* The type passed in is the type of a DECL, and any attributes that
- should be passed in again to be applied to the DECL rather than the
- type should be returned. */
- ATTR_FLAG_DECL_NEXT = 1,
- /* The type passed in is a function return type, and any attributes that
- should be passed in again to be applied to the function type rather
- than the return type should be returned. */
- ATTR_FLAG_FUNCTION_NEXT = 2,
- /* The type passed in is an array element type, and any attributes that
- should be passed in again to be applied to the array type rather
- than the element type should be returned. */
- ATTR_FLAG_ARRAY_NEXT = 4
- };
-
extern tree decl_attributes PARAMS ((tree *, tree, int));
extern void init_function_format_info PARAMS ((void));
extern void check_function_format PARAMS ((int *, tree, tree, tree));
extern void set_Wformat PARAMS ((int));
! extern void decl_handle_format_attribute PARAMS ((tree, tree));
! extern void decl_handle_format_arg_attribute PARAMS ((tree, tree));
extern void c_apply_type_quals_to_decl PARAMS ((int, tree));
extern tree c_sizeof PARAMS ((tree));
extern tree c_alignof PARAMS ((tree));
--- 503,516 ----
extern tree fname_decl PARAMS ((unsigned, tree));
extern const char *fname_string PARAMS ((unsigned));
extern tree decl_attributes PARAMS ((tree *, tree, int));
extern void init_function_format_info PARAMS ((void));
extern void check_function_format PARAMS ((int *, tree, tree, tree));
extern void set_Wformat PARAMS ((int));
! extern tree handle_format_attribute PARAMS ((tree *, tree, tree,
! int, bool *));
! extern tree handle_format_arg_attribute PARAMS ((tree *, tree, tree,
! int, bool *));
extern void c_apply_type_quals_to_decl PARAMS ((int, tree));
extern tree c_sizeof PARAMS ((tree));
extern tree c_alignof PARAMS ((tree));
diff -rcpN gcc.orig/c-decl.c gcc/c-decl.c
*** gcc.orig/c-decl.c Fri Aug 31 19:44:17 2001
--- gcc/c-decl.c Tue Sep 18 15:14:57 2001
*************** duplicate_decls (newdecl, olddecl, diffe
*** 1404,1410 ****
int errmsg = 0;
if (DECL_P (olddecl))
! DECL_MACHINE_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
if (TREE_CODE (newtype) == ERROR_MARK
--- 1404,1410 ----
int errmsg = 0;
if (DECL_P (olddecl))
! DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
if (TREE_CODE (newtype) == ERROR_MARK
*************** duplicate_decls (newdecl, olddecl, diffe
*** 2030,2036 ****
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
! DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
return 1;
}
--- 2030,2036 ----
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
! DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
return 1;
}
*************** grokdeclarator (declarator, declspecs, d
*** 3872,3880 ****
enum tree_code innermost_code = ERROR_MARK;
int bitfield = 0;
int size_varies = 0;
! tree decl_machine_attr = NULL_TREE;
tree array_ptr_quals = NULL_TREE;
int array_parm_static = 0;
if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
--- 3872,3881 ----
enum tree_code innermost_code = ERROR_MARK;
int bitfield = 0;
int size_varies = 0;
! tree decl_attr = NULL_TREE;
tree array_ptr_quals = NULL_TREE;
int array_parm_static = 0;
+ tree returned_attrs = NULL_TREE;
if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
*************** grokdeclarator (declarator, declspecs, d
*** 3898,3903 ****
--- 3899,3908 ----
decl = TREE_OPERAND (decl, 0);
break;
+ case TREE_LIST:
+ decl = TREE_VALUE (decl);
+ break;
+
case IDENTIFIER_NODE:
name = IDENTIFIER_POINTER (decl);
decl = 0;
*************** grokdeclarator (declarator, declspecs, d
*** 3979,3985 ****
else if (TREE_CODE (id) == TYPE_DECL)
{
type = TREE_TYPE (id);
! decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
typedef_decl = id;
}
/* Built-in types come as identifiers. */
--- 3984,3990 ----
else if (TREE_CODE (id) == TYPE_DECL)
{
type = TREE_TYPE (id);
! decl_attr = DECL_ATTRIBUTES (id);
typedef_decl = id;
}
/* Built-in types come as identifiers. */
*************** grokdeclarator (declarator, declspecs, d
*** 4292,4297 ****
--- 4297,4303 ----
/* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
an INDIRECT_REF (for *...),
a CALL_EXPR (for ...(...)),
+ a TREE_LIST (for nested attributes),
an identifier (for the name being declared)
or a null pointer (for the place in an absolute declarator
where the name was omitted).
*************** grokdeclarator (declarator, declspecs, d
*** 4313,4319 ****
array_parm_static = 0;
}
! if (TREE_CODE (declarator) == ARRAY_REF)
{
register tree itype = NULL_TREE;
register tree size = TREE_OPERAND (declarator, 1);
--- 4319,4348 ----
array_parm_static = 0;
}
! if (TREE_CODE (declarator) == TREE_LIST)
! {
! /* We encode a declarator with embedded attributes using
! a TREE_LIST. */
! tree attrs = TREE_PURPOSE (declarator);
! tree inner_decl;
! int attr_flags = 0;
! declarator = TREE_VALUE (declarator);
! inner_decl = declarator;
! while (inner_decl != NULL_TREE
! && TREE_CODE (inner_decl) == TREE_LIST)
! inner_decl = TREE_VALUE (inner_decl);
! if (inner_decl == NULL_TREE
! || TREE_CODE (inner_decl) == IDENTIFIER_NODE)
! attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
! if (TREE_CODE (inner_decl) == CALL_EXPR)
! attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
! if (TREE_CODE (inner_decl) == ARRAY_REF)
! attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
! returned_attrs = decl_attributes (&type,
! chainon (returned_attrs, attrs),
! attr_flags);
! }
! else if (TREE_CODE (declarator) == ARRAY_REF)
{
register tree itype = NULL_TREE;
register tree size = TREE_OPERAND (declarator, 1);
*************** grokdeclarator (declarator, declspecs, d
*** 4657,4662 ****
--- 4686,4692 ----
if ((specbits & (1 << (int) RID_SIGNED))
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
+ decl_attributes (&decl, returned_attrs, 0);
return decl;
}
*************** grokdeclarator (declarator, declspecs, d
*** 4687,4692 ****
--- 4717,4723 ----
pedwarn ("ISO C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
+ decl_attributes (&type, returned_attrs, 0);
return type;
}
*************** grokdeclarator (declarator, declspecs, d
*** 4711,4717 ****
or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */
{
! register tree decl;
if (decl_context == PARM)
{
--- 4742,4748 ----
or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */
{
! tree decl;
if (decl_context == PARM)
{
*************** grokdeclarator (declarator, declspecs, d
*** 4860,4866 ****
pedwarn ("invalid storage class for function `%s'", name);
decl = build_decl (FUNCTION_DECL, declarator, type);
! decl = build_decl_attribute_variant (decl, decl_machine_attr);
if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
--- 4891,4897 ----
pedwarn ("invalid storage class for function `%s'", name);
decl = build_decl (FUNCTION_DECL, declarator, type);
! decl = build_decl_attribute_variant (decl, decl_attr);
if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
*************** grokdeclarator (declarator, declspecs, d
*** 4953,4958 ****
--- 4984,4991 ----
if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
mark_addressable (decl);
+ decl_attributes (&decl, returned_attrs, 0);
+
return decl;
}
}
*************** finish_struct (t, fieldlist, attributes)
*** 5341,5347 ****
TYPE_SIZE (t) = 0;
! decl_attributes (&t, attributes, 0);
/* Nameless union parm types are useful as GCC extension. */
if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic)
--- 5374,5380 ----
TYPE_SIZE (t) = 0;
! decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
/* Nameless union parm types are useful as GCC extension. */
if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic)
*************** finish_enum (enumtype, values, attribute
*** 5705,5711 ****
if (in_parm_level_p ())
warning ("enum defined inside parms");
! decl_attributes (&enumtype, attributes, 0);
/* Calculate the maximum value of any enumerator in this type. */
--- 5738,5744 ----
if (in_parm_level_p ())
warning ("enum defined inside parms");
! decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
/* Calculate the maximum value of any enumerator in this type. */
diff -rcpN gcc.orig/c-format.c gcc/c-format.c
*** gcc.orig/c-format.c Mon Aug 27 07:45:05 2001
--- gcc/c-format.c Wed Sep 5 08:12:12 2001
*************** static void record_function_format PARAM
*** 82,95 ****
int, int));
static void record_international_format PARAMS ((tree, tree, int));
! /* Handle the format attribute (with arguments ARGS) attached to the decl
! DECL. It is already verified that DECL is a decl and ARGS contains
! exactly three arguments. */
!
! void
! decl_handle_format_attribute (decl, args)
! tree decl, args;
{
tree type = TREE_TYPE (decl);
tree format_type_id = TREE_VALUE (args);
tree format_num_expr = TREE_VALUE (TREE_CHAIN (args));
--- 82,98 ----
int, int));
static void record_international_format PARAMS ((tree, tree, int));
! /* Handle a "format" attribute; arguments as in
! struct attribute_spec.handler. */
! tree
! handle_format_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name ATTRIBUTE_UNUSED;
! tree args;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
{
+ tree decl = *node;
tree type = TREE_TYPE (decl);
tree format_type_id = TREE_VALUE (args);
tree format_num_expr = TREE_VALUE (TREE_CHAIN (args));
*************** decl_handle_format_attribute (decl, args
*** 104,116 ****
{
error_with_decl (decl,
"argument format specified for non-function `%s'");
! return;
}
if (TREE_CODE (format_type_id) != IDENTIFIER_NODE)
{
error ("unrecognized format specifier");
! return;
}
else
{
--- 107,121 ----
{
error_with_decl (decl,
"argument format specified for non-function `%s'");
! *no_add_attrs = true;
! return NULL_TREE;
}
if (TREE_CODE (format_type_id) != IDENTIFIER_NODE)
{
error ("unrecognized format specifier");
! *no_add_attrs = true;
! return NULL_TREE;
}
else
{
*************** decl_handle_format_attribute (decl, args
*** 121,127 ****
if (format_type == format_type_error)
{
warning ("`%s' is an unrecognized format function type", p);
! return;
}
}
--- 126,133 ----
if (format_type == format_type_error)
{
warning ("`%s' is an unrecognized format function type", p);
! *no_add_attrs = true;
! return NULL_TREE;
}
}
*************** decl_handle_format_attribute (decl, args
*** 143,149 ****
|| TREE_INT_CST_HIGH (first_arg_num_expr) != 0)
{
error ("format string has invalid operand number");
! return;
}
format_num = TREE_INT_CST_LOW (format_num_expr);
--- 149,156 ----
|| TREE_INT_CST_HIGH (first_arg_num_expr) != 0)
{
error ("format string has invalid operand number");
! *no_add_attrs = true;
! return NULL_TREE;
}
format_num = TREE_INT_CST_LOW (format_num_expr);
*************** decl_handle_format_attribute (decl, args
*** 151,157 ****
if (first_arg_num != 0 && first_arg_num <= format_num)
{
error ("format string arg follows the args to be formatted");
! return;
}
/* If a parameter list is specified, verify that the format_num
--- 158,165 ----
if (first_arg_num != 0 && first_arg_num <= format_num)
{
error ("format string arg follows the args to be formatted");
! *no_add_attrs = true;
! return NULL_TREE;
}
/* If a parameter list is specified, verify that the format_num
*************** decl_handle_format_attribute (decl, args
*** 170,176 ****
!= char_type_node))
{
error ("format string arg not a string type");
! return;
}
else if (first_arg_num != 0)
--- 178,185 ----
!= char_type_node))
{
error ("format string arg not a string type");
! *no_add_attrs = true;
! return NULL_TREE;
}
else if (first_arg_num != 0)
*************** decl_handle_format_attribute (decl, args
*** 183,189 ****
if (arg_num != first_arg_num)
{
error ("args to be formatted is not '...'");
! return;
}
}
}
--- 192,199 ----
if (arg_num != first_arg_num)
{
error ("args to be formatted is not '...'");
! *no_add_attrs = true;
! return NULL_TREE;
}
}
}
*************** decl_handle_format_attribute (decl, args
*** 191,212 ****
if (format_type == strftime_format_type && first_arg_num != 0)
{
error ("strftime formats cannot format arguments");
! return;
}
record_function_format (DECL_NAME (decl), DECL_ASSEMBLER_NAME (decl),
format_type, format_num, first_arg_num);
}
! /* Handle the format_arg attribute (with arguments ARGS) attached to
! the decl DECL. It is already verified that DECL is a decl and
! ARGS contains exactly one argument. */
!
! void
! decl_handle_format_arg_attribute (decl, args)
! tree decl, args;
{
tree type = TREE_TYPE (decl);
tree format_num_expr = TREE_VALUE (args);
unsigned HOST_WIDE_INT format_num;
--- 201,227 ----
if (format_type == strftime_format_type && first_arg_num != 0)
{
error ("strftime formats cannot format arguments");
! *no_add_attrs = true;
! return NULL_TREE;
}
record_function_format (DECL_NAME (decl), DECL_ASSEMBLER_NAME (decl),
format_type, format_num, first_arg_num);
+ return NULL_TREE;
}
! /* Handle a "format" attribute; arguments as in
! struct attribute_spec.handler. */
! tree
! handle_format_arg_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name ATTRIBUTE_UNUSED;
! tree args;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
{
+ tree decl = *node;
tree type = TREE_TYPE (decl);
tree format_num_expr = TREE_VALUE (args);
unsigned HOST_WIDE_INT format_num;
*************** decl_handle_format_arg_attribute (decl,
*** 217,223 ****
{
error_with_decl (decl,
"argument format specified for non-function `%s'");
! return;
}
/* Strip any conversions from the first arg number and verify it
--- 232,239 ----
{
error_with_decl (decl,
"argument format specified for non-function `%s'");
! *no_add_attrs = true;
! return NULL_TREE;
}
/* Strip any conversions from the first arg number and verify it
*************** decl_handle_format_arg_attribute (decl,
*** 231,237 ****
|| TREE_INT_CST_HIGH (format_num_expr) != 0)
{
error ("format string has invalid operand number");
! return;
}
format_num = TREE_INT_CST_LOW (format_num_expr);
--- 247,254 ----
|| TREE_INT_CST_HIGH (format_num_expr) != 0)
{
error ("format string has invalid operand number");
! *no_add_attrs = true;
! return NULL_TREE;
}
format_num = TREE_INT_CST_LOW (format_num_expr);
*************** decl_handle_format_arg_attribute (decl,
*** 252,258 ****
!= char_type_node))
{
error ("format string arg not a string type");
! return;
}
}
--- 269,276 ----
!= char_type_node))
{
error ("format string arg not a string type");
! *no_add_attrs = true;
! return NULL_TREE;
}
}
*************** decl_handle_format_arg_attribute (decl,
*** 261,271 ****
!= char_type_node))
{
error ("function does not return string type");
! return;
}
record_international_format (DECL_NAME (decl), DECL_ASSEMBLER_NAME (decl),
format_num);
}
typedef struct function_format_info
--- 279,291 ----
!= char_type_node))
{
error ("function does not return string type");
! *no_add_attrs = true;
! return NULL_TREE;
}
record_international_format (DECL_NAME (decl), DECL_ASSEMBLER_NAME (decl),
format_num);
+ return NULL_TREE;
}
typedef struct function_format_info
diff -rcpN gcc.orig/c-parse.in gcc/c-parse.in
*** gcc.orig/c-parse.in Wed Aug 22 20:36:04 2001
--- gcc/c-parse.in Tue Sep 11 21:21:12 2001
*************** end ifc
*** 173,179 ****
%type <ttype> declspecs_ts declspecs_nots
%type <ttype> declspecs_ts_nosa declspecs_nots_nosa
%type <ttype> declspecs_nosc_ts declspecs_nosc_nots declspecs_nosc declspecs
! %type <ttype> maybe_type_quals_setattrs typespec_nonattr typespec_attr
%type <ttype> typespec_reserved_nonattr typespec_reserved_attr
%type <ttype> typespec_nonreserved_nonattr
--- 173,179 ----
%type <ttype> declspecs_ts declspecs_nots
%type <ttype> declspecs_ts_nosa declspecs_nots_nosa
%type <ttype> declspecs_nosc_ts declspecs_nosc_nots declspecs_nosc declspecs
! %type <ttype> maybe_type_quals_attrs typespec_nonattr typespec_attr
%type <ttype> typespec_reserved_nonattr typespec_reserved_attr
%type <ttype> typespec_nonreserved_nonattr
*************** end ifc
*** 182,188 ****
%type <ttype> init maybeasm
%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
- %type <ttype> maybe_setattrs
%type <ttype> any_word extension
%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
--- 182,187 ----
*************** setspecs: /* empty */
*** 847,875 ****
all_prefix_attributes = prefix_attributes; }
;
- /* ??? Yuck. See maybe_setattrs. */
- setattrs: /* empty */
- { all_prefix_attributes = chainon ($<ttype>0, all_prefix_attributes); }
- ;
-
- maybe_setattrs:
- /* ??? Yuck. setattrs is a quick hack. We can't use
- prefix_attributes because $1 only applies to this
- declarator. We assume setspecs has already been done.
- setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple
- attributes could be recognized here or in `attributes').
- Properly attributes ought to be able to apply to any level of
- nested declarator, but the necessary compiler support isn't
- present, so the attributes apply to a declaration (which may be
- nested). */
- maybe_attribute setattrs
- ;
-
/* Possibly attributes after a comma, which should reset all_prefix_attributes
to prefix_attributes with these ones chained on the front. */
maybe_resetattrs:
! { all_prefix_attributes = prefix_attributes; }
! maybe_setattrs
;
decl:
--- 846,856 ----
all_prefix_attributes = prefix_attributes; }
;
/* Possibly attributes after a comma, which should reset all_prefix_attributes
to prefix_attributes with these ones chained on the front. */
maybe_resetattrs:
! maybe_attribute
! { all_prefix_attributes = chainon ($1, prefix_attributes); }
;
decl:
*************** declspecs:
*** 1347,1364 ****
| declspecs_sc_ts_sa_ea
;
! /* A (possibly empty) sequence of type qualifiers and attributes, to be
! followed by the effect of setattrs if any attributes were present. */
! maybe_type_quals_setattrs:
/* empty */
{ $$ = NULL_TREE; }
| declspecs_nosc_nots
! { tree specs, attrs;
! split_specs_attrs ($1, &specs, &attrs);
! /* ??? Yuck. See maybe_setattrs. */
! if (attrs != NULL_TREE)
! all_prefix_attributes = chainon (attrs, all_prefix_attributes);
! $$ = specs; }
;
/* A type specifier (but not a type qualifier).
--- 1328,1339 ----
| declspecs_sc_ts_sa_ea
;
! /* A (possibly empty) sequence of type qualifiers and attributes. */
! maybe_type_quals_attrs:
/* empty */
{ $$ = NULL_TREE; }
| declspecs_nosc_nots
! { $$ = $1; }
;
/* A type specifier (but not a type qualifier).
*************** declarator:
*** 1669,1676 ****
/* A declarator that is allowed only after an explicit typespec. */
after_type_declarator:
! '(' maybe_setattrs after_type_declarator ')'
! { $$ = $3; }
| after_type_declarator '(' parmlist_or_identifiers %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
/* | after_type_declarator '(' error ')' %prec '.'
--- 1644,1651 ----
/* A declarator that is allowed only after an explicit typespec. */
after_type_declarator:
! '(' maybe_attribute after_type_declarator ')'
! { $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
| after_type_declarator '(' parmlist_or_identifiers %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
/* | after_type_declarator '(' error ')' %prec '.'
*************** after_type_declarator:
*** 1678,1684 ****
poplevel (0, 0, 0); } */
| after_type_declarator array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
! | '*' maybe_type_quals_setattrs after_type_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
| TYPENAME
ifobjc
--- 1653,1659 ----
poplevel (0, 0, 0); } */
| after_type_declarator array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
! | '*' maybe_type_quals_attrs after_type_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
| TYPENAME
ifobjc
*************** parm_declarator_nostarttypename:
*** 1717,1728 ****
poplevel (0, 0, 0); } */
| parm_declarator_nostarttypename array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
! | '*' maybe_type_quals_setattrs parm_declarator_starttypename %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
! | '*' maybe_type_quals_setattrs parm_declarator_nostarttypename %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
! | '(' maybe_setattrs parm_declarator_nostarttypename ')'
! { $$ = $3; }
;
/* A declarator allowed whether or not there has been
--- 1692,1703 ----
poplevel (0, 0, 0); } */
| parm_declarator_nostarttypename array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
! | '*' maybe_type_quals_attrs parm_declarator_starttypename %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
! | '*' maybe_type_quals_attrs parm_declarator_nostarttypename %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
! | '(' maybe_attribute parm_declarator_nostarttypename ')'
! { $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
;
/* A declarator allowed whether or not there has been
*************** notype_declarator:
*** 1734,1742 ****
/* | notype_declarator '(' error ')' %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
poplevel (0, 0, 0); } */
! | '(' maybe_setattrs notype_declarator ')'
! { $$ = $3; }
! | '*' maybe_type_quals_setattrs notype_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
| notype_declarator array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
--- 1709,1717 ----
/* | notype_declarator '(' error ')' %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
poplevel (0, 0, 0); } */
! | '(' maybe_attribute notype_declarator ')'
! { $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
! | '*' maybe_type_quals_attrs notype_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
| notype_declarator array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
*************** absdcl1: /* a nonempty absolute declara
*** 1991,2010 ****
absdcl1_noea:
direct_absdcl1
! | '*' maybe_type_quals_setattrs absdcl1_noea
{ $$ = make_pointer_declarator ($2, $3); }
;
absdcl1_ea:
! '*' maybe_type_quals_setattrs
{ $$ = make_pointer_declarator ($2, NULL_TREE); }
! | '*' maybe_type_quals_setattrs absdcl1_ea
{ $$ = make_pointer_declarator ($2, $3); }
;
direct_absdcl1:
! '(' maybe_setattrs absdcl1 ')'
! { $$ = $3; }
| direct_absdcl1 '(' parmlist
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
| direct_absdcl1 array_declarator
--- 1966,1985 ----
absdcl1_noea:
direct_absdcl1
! | '*' maybe_type_quals_attrs absdcl1_noea
{ $$ = make_pointer_declarator ($2, $3); }
;
absdcl1_ea:
! '*' maybe_type_quals_attrs
{ $$ = make_pointer_declarator ($2, NULL_TREE); }
! | '*' maybe_type_quals_attrs absdcl1_ea
{ $$ = make_pointer_declarator ($2, $3); }
;
direct_absdcl1:
! '(' maybe_attribute absdcl1 ')'
! { $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
| direct_absdcl1 '(' parmlist
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
| direct_absdcl1 array_declarator
*************** yyprint (file, yychar, yyl)
*** 3906,3920 ****
/* Return something to represent absolute declarators containing a *.
TARGET is the absolute declarator that the * contains.
! TYPE_QUALS is a list of modifiers such as const or volatile
! to apply to the pointer type, represented as identifiers.
! We return an INDIRECT_REF whose "contents" are TARGET
! and whose type is the modifier list. */
tree
! make_pointer_declarator (type_quals, target)
! tree type_quals, target;
{
! return build1 (INDIRECT_REF, type_quals, target);
}
--- 3881,3901 ----
/* Return something to represent absolute declarators containing a *.
TARGET is the absolute declarator that the * contains.
! TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
! to apply to the pointer type, represented as identifiers, possible mixed
! with attributes.
! We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
! if attributes are present) and whose type is the modifier list. */
tree
! make_pointer_declarator (type_quals_attrs, target)
! tree type_quals_attrs, target;
{
! tree quals, attrs;
! tree itarget = target;
! split_specs_attrs (type_quals_attrs, &quals, &attrs);
! if (attrs != NULL_TREE)
! itarget = tree_cons (attrs, target, NULL_TREE);
! return build1 (INDIRECT_REF, quals, itarget);
}
diff -rcpN gcc.orig/config/alpha/alpha.c gcc/config/alpha/alpha.c
*** gcc.orig/config/alpha/alpha.c Wed Sep 5 07:47:53 2001
--- gcc/config/alpha/alpha.c Tue Sep 11 21:44:49 2001
*************** static int alpha_variable_issue
*** 155,167 ****
/* Initialize the GCC target structure. */
#if TARGET_ABI_OPEN_VMS
! static int vms_valid_decl_attribute_p PARAMS ((tree, tree, tree, tree));
static unsigned int vms_section_type_flags PARAMS ((tree, const char *, int));
static void vms_asm_named_section PARAMS ((const char *, unsigned int));
static void vms_asm_out_constructor PARAMS ((rtx, int));
static void vms_asm_out_destructor PARAMS ((rtx, int));
! # undef TARGET_VALID_DECL_ATTRIBUTE
! # define TARGET_VALID_DECL_ATTRIBUTE vms_valid_decl_attribute_p
# undef TARGET_SECTION_TYPE_FLAGS
# define TARGET_SECTION_TYPE_FLAGS vms_section_type_flags
#endif
--- 155,167 ----
/* Initialize the GCC target structure. */
#if TARGET_ABI_OPEN_VMS
! const struct attribute_spec vms_attribute_table[];
static unsigned int vms_section_type_flags PARAMS ((tree, const char *, int));
static void vms_asm_named_section PARAMS ((const char *, unsigned int));
static void vms_asm_out_constructor PARAMS ((rtx, int));
static void vms_asm_out_destructor PARAMS ((rtx, int));
! # undef TARGET_ATTRIBUTE_TABLE
! # define TARGET_ATTRIBUTE_TABLE vms_attribute_table
# undef TARGET_SECTION_TYPE_FLAGS
# define TARGET_SECTION_TYPE_FLAGS vms_section_type_flags
#endif
*************** alpha_using_fp ()
*** 4883,4899 ****
#if TARGET_ABI_OPEN_VMS
! static int
! vms_valid_decl_attribute_p (decl, attributes, identifier, args)
! tree decl ATTRIBUTE_UNUSED;
! tree attributes ATTRIBUTE_UNUSED;
! tree identifier;
! tree args;
{
! if (is_attribute_p ("overlaid", identifier))
! return (args == NULL_TREE);
! return 0;
! }
#endif
--- 4883,4894 ----
#if TARGET_ABI_OPEN_VMS
! const struct attribute_spec vms_attribute_table[] =
{
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "overlaid", 0, 0, true, false, false, NULL },
! { NULL, 0, 0, false, false, false, NULL }
! };
#endif
*************** vms_section_type_flags (decl, name, relo
*** 6888,6895 ****
{
unsigned int flags = default_section_type_flags (decl, name, reloc);
! if (decl && DECL_MACHINE_ATTRIBUTES (decl)
! && lookup_attribute ("overlaid", DECL_MACHINE_ATTRIBUTES (decl)))
flags |= SECTION_VMS_OVERLAY;
return flags;
--- 6883,6890 ----
{
unsigned int flags = default_section_type_flags (decl, name, reloc);
! if (decl && DECL_ATTRIBUTES (decl)
! && lookup_attribute ("overlaid", DECL_ATTRIBUTES (decl)))
flags |= SECTION_VMS_OVERLAY;
return flags;
diff -rcpN gcc.orig/config/arc/arc.c gcc/config/arc/arc.c
*** gcc.orig/config/arc/arc.c Thu Jul 12 13:51:31 2001
--- gcc/config/arc/arc.c Tue Sep 11 21:45:11 2001
*************** static int current_insn_set_cc_p;
*** 87,93 ****
static void record_cc_ref PARAMS ((rtx));
static void arc_init_reg_tables PARAMS ((void));
static int get_arc_condition_code PARAMS ((rtx));
! static int arc_valid_decl_attribute PARAMS ((tree, tree, tree, tree));
static void arc_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void arc_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
--- 87,94 ----
static void record_cc_ref PARAMS ((rtx));
static void arc_init_reg_tables PARAMS ((void));
static int get_arc_condition_code PARAMS ((rtx));
! const struct attribute_spec arc_attribute_table[];
! static tree arc_handle_interrupt_attribute PARAMS ((tree *, tree, tree, int, bool *));
static void arc_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void arc_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
*************** static void arc_output_function_epilogue
*** 96,103 ****
#define TARGET_ASM_FUNCTION_PROLOGUE arc_output_function_prologue
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE arc_output_function_epilogue
! #undef TARGET_VALID_DECL_ATTRIBUTE
! #define TARGET_VALID_DECL_ATTRIBUTE arc_valid_decl_attribute
struct gcc_target targetm = TARGET_INITIALIZER;
--- 97,104 ----
#define TARGET_ASM_FUNCTION_PROLOGUE arc_output_function_prologue
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE arc_output_function_epilogue
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE arc_attribute_table
struct gcc_target targetm = TARGET_INITIALIZER;
*************** arc_init_reg_tables ()
*** 326,351 ****
interrupt - for interrupt functions
*/
! /* Return nonzero if IDENTIFIER is a valid decl attribute. */
! static int
! arc_valid_decl_attribute (type, attributes, identifier, args)
! tree type ATTRIBUTE_UNUSED;
! tree attributes ATTRIBUTE_UNUSED;
! tree identifier;
tree args;
{
! if (identifier == get_identifier ("__interrupt__")
! && list_length (args) == 1
! && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
! {
! tree value = TREE_VALUE (args);
! if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
! || !strcmp (TREE_STRING_POINTER (value), "ilink2"))
! return 1;
}
! return 0;
}
--- 327,366 ----
interrupt - for interrupt functions
*/
! const struct attribute_spec arc_attribute_table[] =
! {
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute },
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Handle an "interrupt" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! arc_handle_interrupt_attribute (node, name, args, flags, no_add_attrs)
! tree *node ATTRIBUTE_UNUSED;
! tree name;
tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
{
! tree value = TREE_VALUE (args);
! if (TREE_CODE (value) != STRING_CST)
! {
! warning ("argument of `%s' attribute is not a string constant",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
}
! else if (strcmp (TREE_STRING_POINTER (value), "ilink1")
! && strcmp (TREE_STRING_POINTER (value), "ilink2"))
! {
! warning ("argument of `%s' attribute is not \"ilink1\" or \"ilink2\"",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
!
! return NULL_TREE;
}
*************** arc_compute_function_type (decl)
*** 956,962 ****
fn_type = ARC_FUNCTION_NORMAL;
/* Now see if this is an interrupt handler. */
! for (a = DECL_MACHINE_ATTRIBUTES (current_function_decl);
a;
a = TREE_CHAIN (a))
{
--- 971,977 ----
fn_type = ARC_FUNCTION_NORMAL;
/* Now see if this is an interrupt handler. */
! for (a = DECL_ATTRIBUTES (current_function_decl);
a;
a = TREE_CHAIN (a))
{
diff -rcpN gcc.orig/config/arm/arm.c gcc/config/arm/arm.c
*** gcc.orig/config/arm/arm.c Fri Aug 31 19:44:17 2001
--- gcc/config/arm/arm.c Wed Sep 19 12:49:03 2001
*************** static int current_file_function_o
*** 103,112 ****
static Ulong arm_compute_save_reg_mask PARAMS ((void));
static Ulong arm_isr_value PARAMS ((tree));
static Ulong arm_compute_func_type PARAMS ((void));
! static int arm_valid_type_attribute_p PARAMS ((tree, tree,
! tree, tree));
! static int arm_valid_decl_attribute_p PARAMS ((tree, tree,
! tree, tree));
static void arm_output_function_epilogue PARAMS ((FILE *,
HOST_WIDE_INT));
static void arm_output_function_prologue PARAMS ((FILE *,
--- 103,111 ----
static Ulong arm_compute_save_reg_mask PARAMS ((void));
static Ulong arm_isr_value PARAMS ((tree));
static Ulong arm_compute_func_type PARAMS ((void));
! static tree arm_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree arm_handle_isr_attribute PARAMS ((tree *, tree, tree, int, bool *));
! const struct attribute_spec arm_attribute_table[];
static void arm_output_function_epilogue PARAMS ((FILE *,
HOST_WIDE_INT));
static void arm_output_function_prologue PARAMS ((FILE *,
*************** static int arm_adjust_cost PARAMS ((rt
*** 130,145 ****
#define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
#endif
! #undef TARGET_VALID_TYPE_ATTRIBUTE
! #define TARGET_VALID_TYPE_ATTRIBUTE arm_valid_type_attribute_p
!
! #undef TARGET_VALID_DECL_ATTRIBUTE
! #ifdef ARM_PE
! static int arm_pe_valid_decl_attribute_p PARAMS ((tree, tree, tree, tree));
! # define TARGET_VALID_DECL_ATTRIBUTE arm_pe_valid_decl_attribute_p
! #else
! # define TARGET_VALID_DECL_ATTRIBUTE arm_valid_decl_attribute_p
! #endif
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue
--- 129,136 ----
#define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
#endif
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE arm_attribute_table
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue
*************** arm_compute_func_type ()
*** 845,851 ****
if (current_function_needs_context)
type |= ARM_FT_NESTED;
! attr = DECL_MACHINE_ATTRIBUTES (current_function_decl);
a = lookup_attribute ("naked", attr);
if (a != NULL_TREE)
--- 836,842 ----
if (current_function_needs_context)
type |= ARM_FT_NESTED;
! attr = DECL_ATTRIBUTES (current_function_decl);
a = lookup_attribute ("naked", attr);
if (a != NULL_TREE)
*************** arm_pr_long_calls_off (pfile)
*** 1909,1947 ****
}
! /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine
! specific attribute for TYPE. The attributes in ATTRIBUTES have
! previously been assigned to TYPE. */
! static int
! arm_valid_type_attribute_p (type, attributes, identifier, args)
! tree type;
! tree attributes ATTRIBUTE_UNUSED;
! tree identifier;
! tree args;
{
! if ( TREE_CODE (type) != FUNCTION_TYPE
! && TREE_CODE (type) != METHOD_TYPE
! && TREE_CODE (type) != FIELD_DECL
! && TREE_CODE (type) != TYPE_DECL)
! return 0;
!
/* 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. */
! if (is_attribute_p ("long_call", identifier))
! return (args == NULL_TREE);
!
/* Whereas these functions are always known to reside within the 26 bit
addressing range. */
! if (is_attribute_p ("short_call", identifier))
! return (args == NULL_TREE);
!
/* Interrupt Service Routines have special prologue and epilogue requirements. */
! if (is_attribute_p ("isr", identifier)
! || is_attribute_p ("interrupt", identifier))
! return arm_isr_value (args);
! return 0;
}
/* Return 0 if the attributes for two types are incompatible, 1 if they
--- 1900,2019 ----
}
! /* Table of machine attributes. */
! const struct attribute_spec arm_attribute_table[] =
{
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
/* 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 },
/* Whereas these functions are always known to reside within the 26 bit
addressing range. */
! { "short_call", 0, 0, false, true, true, NULL },
/* Interrupt Service Routines have special prologue and epilogue requirements. */
! { "isr", 0, 1, false, false, false, arm_handle_isr_attribute },
! { "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute },
! { "naked", 0, 0, true, false, false, arm_handle_fndecl_attribute },
! #ifdef ARM_PE
! /* ARM/PE has three new attributes:
! interfacearm - ?
! dllexport - for exporting a function/variable that will live in a dll
! dllimport - for importing a function/variable from a dll
!
! Microsoft allows multiple declspecs in one __declspec, separating
! them with spaces. We do NOT support this. Instead, use __declspec
! multiple times.
! */
! { "dllimport", 0, 0, true, false, false, NULL },
! { "dllexport", 0, 0, true, false, false, NULL },
! { "interfacearm", 0, 0, true, false, false, arm_handle_fndecl_attribute },
! #endif
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Handle an attribute requiring a FUNCTION_DECL;
! arguments as in struct attribute_spec.handler. */
! static tree
! arm_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (TREE_CODE (*node) != FUNCTION_DECL)
! {
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
!
! return NULL_TREE;
! }
!
! /* Handle an "interrupt" or "isr" attribute;
! arguments as in struct attribute_spec.handler. */
! static tree
! arm_handle_isr_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args;
! int flags;
! bool *no_add_attrs;
! {
! if (DECL_P (*node))
! {
! if (TREE_CODE (*node) != FUNCTION_DECL)
! {
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (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) == FUNCTION_TYPE
! || TREE_CODE (*node) == METHOD_TYPE)
! {
! if (arm_isr_value (args) == ARM_FT_UNKNOWN)
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (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)
! {
! *node = build_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
! {
! /* 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 ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! }
! }
! }
!
! return NULL_TREE;
}
/* Return 0 if the attributes for two types are incompatible, 1 if they
*************** multi_register_push (op, mode)
*** 4132,4216 ****
return 1;
}
- /* Routines for use with attributes. */
-
- /* Return nonzero if ATTR is a valid attribute for DECL.
- ATTRIBUTES are any existing attributes and ARGS are
- the arguments supplied with ATTR.
-
- Supported attributes:
-
- naked:
- don't output any prologue or epilogue code, the user is assumed
- to do the right thing.
-
- isr or interrupt:
- Interrupt Service Routine.
-
- interfacearm:
- Always assume that this function will be entered in ARM mode,
- not Thumb mode, and that the caller wishes to be returned to in
- ARM mode. */
- static int
- arm_valid_decl_attribute_p (decl, attributes, attr, args)
- tree decl;
- tree attributes ATTRIBUTE_UNUSED;
- tree attr;
- tree args;
- {
- /* The interrupt attribute can take args, so check for it before
- rejecting other attributes on the grounds that they did have args. */
- if (is_attribute_p ("isr", attr)
- || is_attribute_p ("interrupt", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-
- if (args != NULL_TREE)
- return 0;
-
- if (is_attribute_p ("naked", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-
- #ifdef ARM_PE
- if (is_attribute_p ("interfacearm", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
- #endif /* ARM_PE */
-
- return 0;
- }
-
- #ifdef ARM_PE
-
- /* ARM/PE has three new attributes:
- naked - for interrupt functions
- dllexport - for exporting a function/variable that will live in a dll
- dllimport - for importing a function/variable from a dll
-
- Microsoft allows multiple declspecs in one __declspec, separating
- them with spaces. We do NOT support this. Instead, use __declspec
- multiple times.
- */
-
- static int
- arm_pe_valid_decl_attribute_p (decl, attributes, attr, args)
- tree decl;
- tree attributes;
- tree attr;
- tree args;
- {
- if (args != NULL_TREE)
- return 0;
-
- if (is_attribute_p ("dllexport", attr))
- return 1;
-
- if (is_attribute_p ("dllimport", attr))
- return 1;
-
- return arm_valid_decl_attribute_p (decl, attributes, attr, args);
- }
-
- #endif /* ARM_PE */
-
/* Routines for use in generating RTL. */
rtx
arm_gen_load_multiple (base_regno, count, from, up, write_back, unchanging_p,
--- 4204,4209 ----
*************** is_called_in_ARM_mode (func)
*** 9742,9748 ****
return TRUE;
#ifdef ARM_PE
! return lookup_attribute ("interfacearm", DECL_MACHINE_ATTRIBUTES (func)) != NULL_TREE;
#else
return FALSE;
#endif
--- 9735,9741 ----
return TRUE;
#ifdef ARM_PE
! return lookup_attribute ("interfacearm", DECL_ATTRIBUTES (func)) != NULL_TREE;
#else
return FALSE;
#endif
diff -rcpN gcc.orig/config/arm/pe.c gcc/config/arm/pe.c
*** gcc.orig/config/arm/pe.c Tue Jun 26 19:14:58 2001
--- gcc/config/arm/pe.c Wed Sep 5 08:12:12 2001
***************
*** 1,5 ****
/* Routines for GCC for ARM/pe.
! Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc.
Contributed by Doug Evans (dje@cygnus.com).
This file is part of GNU CC.
--- 1,5 ----
/* Routines for GCC for ARM/pe.
! Copyright (C) 1995, 1996, 2000, 2001 Free Software Foundation, Inc.
Contributed by Doug Evans (dje@cygnus.com).
This file is part of GNU CC.
*************** arm_dllexport_p (decl)
*** 45,51 ****
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
! exp = lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl));
if (exp)
return 1;
--- 45,51 ----
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
! exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
if (exp)
return 1;
*************** arm_dllimport_p (decl)
*** 67,73 ****
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
! imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl));
if (imp)
return 1;
--- 67,73 ----
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
! imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
if (imp)
return 1;
diff -rcpN gcc.orig/config/avr/avr.c gcc/config/avr/avr.c
*** gcc.orig/config/avr/avr.c Sat Aug 11 11:44:19 2001
--- gcc/config/avr/avr.c Wed Sep 19 11:48:35 2001
*************** static int compare_sign_p PARAM
*** 58,65 ****
static int reg_was_0 PARAMS ((rtx insn, rtx op));
static int io_address_p PARAMS ((rtx x, int size));
void debug_hard_reg_set PARAMS ((HARD_REG_SET set));
! static int avr_valid_type_attribute PARAMS ((tree, tree, tree, tree));
! static int avr_valid_decl_attribute PARAMS ((tree, tree, tree, tree));
static void avr_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void avr_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
--- 58,66 ----
static int reg_was_0 PARAMS ((rtx insn, rtx op));
static int io_address_p PARAMS ((rtx x, int size));
void debug_hard_reg_set PARAMS ((HARD_REG_SET set));
! static tree avr_handle_progmem_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree avr_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
! const struct attribute_spec avr_attribute_table[];
static void avr_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void avr_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
*************** int avr_case_values_threshold = 30000;
*** 177,187 ****
#define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
! #undef TARGET_VALID_DECL_ATTRIBUTE
! #define TARGET_VALID_DECL_ATTRIBUTE avr_valid_decl_attribute
!
! #undef TARGET_VALID_TYPE_ATTRIBUTE
! #define TARGET_VALID_TYPE_ATTRIBUTE avr_valid_type_attribute
struct gcc_target targetm = TARGET_INITIALIZER;
--- 178,185 ----
#define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
struct gcc_target targetm = TARGET_INITIALIZER;
*************** avr_naked_function_p (func)
*** 310,316 ****
if (TREE_CODE (func) != FUNCTION_DECL)
abort ();
! a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
return a != NULL_TREE;
}
--- 308,314 ----
if (TREE_CODE (func) != FUNCTION_DECL)
abort ();
! a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
*************** interrupt_function_p (func)
*** 326,332 ****
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));
return a != NULL_TREE;
}
--- 324,330 ----
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
*************** signal_function_p (func)
*** 342,348 ****
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("signal", DECL_MACHINE_ATTRIBUTES (func));
return a != NULL_TREE;
}
--- 340,346 ----
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
*************** class_likely_spilled_p (c)
*** 4665,4718 ****
return (c != ALL_REGS && c != ADDW_REGS);
}
! /* Only `progmem' attribute valid for type. */
!
! static int
! avr_valid_type_attribute (type, attributes, identifier, args)
! tree type ATTRIBUTE_UNUSED;
! tree attributes ATTRIBUTE_UNUSED;
! tree identifier;
! tree args ATTRIBUTE_UNUSED;
! {
! return is_attribute_p ("progmem", identifier);
! }
!
! /* If IDENTIFIER with arguments ARGS is a valid machine specific
! attribute for DECL return 1.
! Valid attributes:
progmem - put data to program memory;
signal - make a function to be hardware interrupt. After function
prologue interrupts are disabled;
interrupt - make a function to be hardware interrupt. After function
prologue interrupts are enabled;
! naked - don't generate function prologue/epilogue and `ret' command. */
! static int
! avr_valid_decl_attribute (decl, attributes, attr, args)
! tree decl;
! tree attributes ATTRIBUTE_UNUSED;
! tree attr;
! tree args ATTRIBUTE_UNUSED;
{
! if (is_attribute_p ("interrupt", attr)
! || is_attribute_p ("signal", attr)
! || is_attribute_p ("naked", attr))
! return TREE_CODE (decl) == FUNCTION_DECL;
! if (is_attribute_p ("progmem", attr)
! && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
{
! if (DECL_INITIAL (decl) == NULL_TREE && !DECL_EXTERNAL (decl))
{
! warning ("Only initialized variables can be placed into "
! "program memory area.");
! return 0;
}
- return 1;
}
! return 0;
}
/* Look for attribute `progmem' in DECL
if found return 1, otherwise 0. */
--- 4663,4738 ----
return (c != ALL_REGS && c != ADDW_REGS);
}
! /* Valid attributes:
progmem - put data to program memory;
signal - make a function to be hardware interrupt. After function
prologue interrupts are disabled;
interrupt - make a function to be hardware interrupt. After function
prologue interrupts are enabled;
! naked - don't generate function prologue/epilogue and `ret' command.
! Only `progmem' attribute valid for type. */
!
! const struct attribute_spec avr_attribute_table[] =
{
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
! { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
! { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
! { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute },
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Handle a "progmem" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! avr_handle_progmem_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (DECL_P (*node))
{
! if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
{
! if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
! {
! warning ("Only initialized variables can be placed into "
! "program memory area.");
! *no_add_attrs = true;
! }
! }
! else
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
}
}
!
! return NULL_TREE;
}
+ /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
+ struct attribute_spec.handler. */
+ static tree
+ avr_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+ {
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning ("`%s' attribute only applies to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+ }
/* Look for attribute `progmem' in DECL
if found return 1, otherwise 0. */
*************** avr_progmem_p (decl)
*** 4727,4733 ****
return 0;
if (NULL_TREE
! != lookup_attribute ("progmem", DECL_MACHINE_ATTRIBUTES (decl)))
return 1;
a=decl;
--- 4747,4753 ----
return 0;
if (NULL_TREE
! != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl)))
return 1;
a=decl;
diff -rcpN gcc.orig/config/avr/avr.h gcc/config/avr/avr.h
*** gcc.orig/config/avr/avr.h Mon Aug 20 17:53:22 2001
--- gcc/config/avr/avr.h Wed Sep 5 08:12:12 2001
*************** enum reg_class {
*** 1110,1116 ****
FUNDECL is a C variable whose value is a tree node that describes
the function in question. Normally it is a node of type
`FUNCTION_DECL' that describes the declaration of the function.
! From this you can obtain the DECL_MACHINE_ATTRIBUTES of the
function.
FUNTYPE is a C variable whose value is a tree node that describes
--- 1110,1116 ----
FUNDECL is a C variable whose value is a tree node that describes
the function in question. Normally it is a node of type
`FUNCTION_DECL' that describes the declaration of the function.
! From this you can obtain the DECL_ATTRIBUTES of the
function.
FUNTYPE is a C variable whose value is a tree node that describes
diff -rcpN gcc.orig/config/c4x/c4x.c gcc/config/c4x/c4x.c
*** gcc.orig/config/c4x/c4x.c Mon Aug 20 17:53:22 2001
--- gcc/config/c4x/c4x.c Tue Sep 11 21:46:39 2001
*************** static int c4x_parse_pragma PARAMS ((con
*** 191,204 ****
static int c4x_r11_set_p PARAMS ((rtx));
static int c4x_rptb_valid_p PARAMS ((rtx, rtx));
static int c4x_label_ref_used_p PARAMS ((rtx, rtx));
! static int c4x_valid_type_attribute_p PARAMS ((tree, tree, tree, tree));
static void c4x_insert_attributes PARAMS ((tree, tree *));
static void c4x_asm_named_section PARAMS ((const char *, unsigned int));
static int c4x_adjust_cost PARAMS ((rtx, rtx, rtx, int));
/* Initialize the GCC target structure. */
! #undef TARGET_VALID_TYPE_ATTRIBUTE
! #define TARGET_VALID_TYPE_ATTRIBUTE c4x_valid_type_attribute_p
#undef TARGET_INSERT_ATTRIBUTES
#define TARGET_INSERT_ATTRIBUTES c4x_insert_attributes
--- 191,205 ----
static int c4x_r11_set_p PARAMS ((rtx));
static int c4x_rptb_valid_p PARAMS ((rtx, rtx));
static int c4x_label_ref_used_p PARAMS ((rtx, rtx));
! static tree c4x_handle_fntype_attribute PARAMS ((tree *, tree, tree, int, bool *));
! const struct attribute_spec c4x_attribute_table[];
static void c4x_insert_attributes PARAMS ((tree, tree *));
static void c4x_asm_named_section PARAMS ((const char *, unsigned int));
static int c4x_adjust_cost PARAMS ((rtx, rtx, rtx, int));
/* Initialize the GCC target structure. */
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE c4x_attribute_table
#undef TARGET_INSERT_ATTRIBUTES
#define TARGET_INSERT_ATTRIBUTES c4x_insert_attributes
*************** c4x_insert_attributes (decl, attributes)
*** 4761,4791 ****
}
}
! /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine
! specific attribute for TYPE. The attributes in ATTRIBUTES have
! previously been assigned to TYPE. */
!
! static int
! c4x_valid_type_attribute_p (type, attributes, identifier, args)
! tree type;
! tree attributes ATTRIBUTE_UNUSED;
! tree identifier;
tree args ATTRIBUTE_UNUSED;
{
! if (TREE_CODE (type) != FUNCTION_TYPE)
! return 0;
!
! if (is_attribute_p ("interrupt", identifier))
! return 1;
!
! if (is_attribute_p ("assembler", identifier))
! return 1;
!
! if (is_attribute_p ("leaf_pretend", identifier))
! return 1;
!
! return 0;
}
--- 4762,4797 ----
}
}
+ /* Table of valid machine attributes. */
+ const struct attribute_spec c4x_attribute_table[] =
+ {
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+ { "interrupt", 0, 0, false, true, true, c4x_handle_fntype_attribute },
+ /* FIXME: code elsewhere in this file treats "naked" as a synonym of
+ "interrupt"; should it be accepted here? */
+ { "assembler", 0, 0, false, true, true, c4x_handle_fntype_attribute },
+ { "leaf_pretend", 0, 0, false, true, true, c4x_handle_fntype_attribute },
+ { NULL, 0, 0, false, false, false, NULL }
+ };
! /* Handle an attribute requiring a FUNCTION_TYPE;
! arguments as in struct attribute_spec.handler. */
! static tree
! c4x_handle_fntype_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
{
! if (TREE_CODE (*node) != FUNCTION_TYPE)
! {
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
!
! return NULL_TREE;
}
diff -rcpN gcc.orig/config/d30v/d30v.h gcc/config/d30v/d30v.h
*** gcc.orig/config/d30v/d30v.h Mon Aug 20 17:53:23 2001
--- gcc/config/d30v/d30v.h Wed Sep 5 08:12:12 2001
*************** typedef struct d30v_stack {
*** 2272,2278 ****
FUNDECL is a C variable whose value is a tree node that describes the
function in question. Normally it is a node of type `FUNCTION_DECL' that
describes the declaration of the function. From this it is possible to
! obtain the DECL_MACHINE_ATTRIBUTES of the function.
FUNTYPE is a C variable whose value is a tree node that describes the
function in question. Normally it is a node of type `FUNCTION_TYPE' that
--- 2272,2278 ----
FUNDECL is a C variable whose value is a tree node that describes the
function in question. Normally it is a node of type `FUNCTION_DECL' that
describes the declaration of the function. From this it is possible to
! obtain the DECL_ATTRIBUTES of the function.
FUNTYPE is a C variable whose value is a tree node that describes the
function in question. Normally it is a node of type `FUNCTION_TYPE' that
diff -rcpN gcc.orig/config/fr30/fr30.h gcc/config/fr30/fr30.h
*** gcc.orig/config/fr30/fr30.h Fri Aug 3 11:42:55 2001
--- gcc/config/fr30/fr30.h Wed Sep 5 08:12:12 2001
***************
*** 1,7 ****
/*{{{ Comment. */
/* Definitions of FR30 target.
! Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
Contributed by Cygnus Solutions.
This file is part of GNU CC.
--- 1,7 ----
/*{{{ Comment. */
/* Definitions of FR30 target.
! Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Cygnus Solutions.
This file is part of GNU CC.
*************** enum reg_class
*** 824,830 ****
FUNDECL is a C variable whose value is a tree node that describes the
function in question. Normally it is a node of type `FUNCTION_DECL' that
describes the declaration of the function. From this it is possible to
! obtain the DECL_MACHINE_ATTRIBUTES of the function.
FUNTYPE is a C variable whose value is a tree node that describes the
function in question. Normally it is a node of type `FUNCTION_TYPE' that
--- 824,830 ----
FUNDECL is a C variable whose value is a tree node that describes the
function in question. Normally it is a node of type `FUNCTION_DECL' that
describes the declaration of the function. From this it is possible to
! obtain the DECL_ATTRIBUTES of the function.
FUNTYPE is a C variable whose value is a tree node that describes the
function in question. Normally it is a node of type `FUNCTION_TYPE' that
diff -rcpN gcc.orig/config/h8300/h8300.c gcc/config/h8300/h8300.c
*** gcc.orig/config/h8300/h8300.c Fri Aug 31 10:16:36 2001
--- gcc/config/h8300/h8300.c Tue Sep 11 21:46:54 2001
*************** static unsigned int compute_saved_regs P
*** 53,59 ****
static void push PARAMS ((FILE *, int));
static void pop PARAMS ((FILE *, int));
static const char *cond_string PARAMS ((enum rtx_code));
! static int h8300_valid_decl_attribute PARAMS ((tree, tree, tree, tree));
static void h8300_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void h8300_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
static void h8300_asm_named_section PARAMS ((const char *, unsigned int));
--- 53,62 ----
static void push PARAMS ((FILE *, int));
static void pop PARAMS ((FILE *, int));
static const char *cond_string PARAMS ((enum rtx_code));
! const struct attribute_spec h8300_attribute_table[];
! static tree h8300_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree h8300_handle_eightbit_data_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree h8300_handle_tiny_data_attribute PARAMS ((tree *, tree, tree, int, bool *));
static void h8300_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void h8300_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
static void h8300_asm_named_section PARAMS ((const char *, unsigned int));
*************** static const char *const h8_mov_ops[2] =
*** 98,105 ****
const char *h8_push_op, *h8_pop_op, *h8_mov_op;
/* Initialize the GCC target structure. */
! #undef TARGET_VALID_DECL_ATTRIBUTE
! #define TARGET_VALID_DECL_ATTRIBUTE h8300_valid_decl_attribute
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE h8300_output_function_prologue
--- 101,108 ----
const char *h8_push_op, *h8_pop_op, *h8_mov_op;
/* Initialize the GCC target structure. */
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE h8300_attribute_table
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE h8300_output_function_prologue
*************** h8300_interrupt_function_p (func)
*** 3094,3100 ****
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("interrupt_handler", DECL_MACHINE_ATTRIBUTES (func));
return a != NULL_TREE;
}
--- 3097,3103 ----
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
*************** h8300_os_task_function_p (func)
*** 3110,3116 ****
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("OS_Task", DECL_MACHINE_ATTRIBUTES (func));
return a != NULL_TREE;
}
--- 3113,3119 ----
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("OS_Task", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
*************** h8300_monitor_function_p (func)
*** 3126,3132 ****
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("monitor", DECL_MACHINE_ATTRIBUTES (func));
return a != NULL_TREE;
}
--- 3129,3135 ----
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("monitor", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
*************** h8300_funcvec_function_p (func)
*** 3142,3148 ****
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("function_vector", DECL_MACHINE_ATTRIBUTES (func));
return a != NULL_TREE;
}
--- 3145,3151 ----
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("function_vector", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
*************** h8300_eightbit_data_p (decl)
*** 3158,3164 ****
if (TREE_CODE (decl) != VAR_DECL)
return 0;
! a = lookup_attribute ("eightbit_data", DECL_MACHINE_ATTRIBUTES (decl));
return a != NULL_TREE;
}
--- 3161,3167 ----
if (TREE_CODE (decl) != VAR_DECL)
return 0;
! a = lookup_attribute ("eightbit_data", DECL_ATTRIBUTES (decl));
return a != NULL_TREE;
}
*************** h8300_tiny_data_p (decl)
*** 3174,3188 ****
if (TREE_CODE (decl) != VAR_DECL)
return 0;
! a = lookup_attribute ("tiny_data", DECL_MACHINE_ATTRIBUTES (decl));
return a != NULL_TREE;
}
! /* Return nonzero if ATTR is a valid attribute for DECL.
! ATTRIBUTES are any existing attributes and ARGS are the arguments
! supplied with ATTR.
!
! Supported attributes:
interrupt_handler: output a prologue and epilogue suitable for an
interrupt handler.
--- 3177,3187 ----
if (TREE_CODE (decl) != VAR_DECL)
return 0;
! a = lookup_attribute ("tiny_data", DECL_ATTRIBUTES (decl));
return a != NULL_TREE;
}
! /* Supported attributes:
interrupt_handler: output a prologue and epilogue suitable for an
interrupt handler.
*************** h8300_tiny_data_p (decl)
*** 3196,3242 ****
tiny_data: This variable lives in the tiny data area and can be
referenced with 16-bit absolute memory references. */
! static int
! h8300_valid_decl_attribute (decl, attributes, attr, args)
! tree decl;
! tree attributes ATTRIBUTE_UNUSED;
! tree attr;
! tree args;
{
! if (args != NULL_TREE)
! return 0;
! if (is_attribute_p ("interrupt_handler", attr)
! || is_attribute_p ("OS_Task", attr)
! || is_attribute_p ("monitor", attr)
! || is_attribute_p ("function_vector", attr))
! return TREE_CODE (decl) == FUNCTION_DECL;
! if (is_attribute_p ("eightbit_data", attr)
! && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
{
if (DECL_INITIAL (decl) == NULL_TREE)
{
warning ("Only initialized variables can be placed into the 8-bit area.");
! return 0;
}
! DECL_SECTION_NAME (decl) = build_string (7, ".eight");
! return 1;
}
! if (is_attribute_p ("tiny_data", attr)
! && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
{
if (DECL_INITIAL (decl) == NULL_TREE)
{
warning ("Only initialized variables can be placed into the 8-bit area.");
! return 0;
}
! DECL_SECTION_NAME (decl) = build_string (6, ".tiny");
! return 1;
}
! return 0;
}
void
--- 3195,3293 ----
tiny_data: This variable lives in the tiny data area and can be
referenced with 16-bit absolute memory references. */
! const struct attribute_spec h8300_attribute_table[] =
{
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "interrupt_handler", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
! { "OS_Task", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
! { "monitor", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
! { "function_vector", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
! { "eightbit_data", 0, 0, true, false, false, h8300_handle_eightbit_data_attribute },
! { "tiny_data", 0, 0, true, false, false, h8300_handle_tiny_data_attribute },
! { NULL, 0, 0, false, false, false, NULL }
! };
!
! /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
! struct attribute_spec.handler. */
! static tree
! h8300_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (TREE_CODE (*node) != FUNCTION_DECL)
! {
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
!
! return NULL_TREE;
! }
!
! /* Handle an "eightbit_data" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! h8300_handle_eightbit_data_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! tree decl = *node;
! if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
{
if (DECL_INITIAL (decl) == NULL_TREE)
{
warning ("Only initialized variables can be placed into the 8-bit area.");
! *no_add_attrs = true;
}
! else
! DECL_SECTION_NAME (decl) = build_string (7, ".eight");
! }
! else
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
}
! return NULL_TREE;
! }
!
! /* Handle an "tiny_data" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! h8300_handle_tiny_data_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! tree decl = *node;
!
! if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
{
if (DECL_INITIAL (decl) == NULL_TREE)
{
warning ("Only initialized variables can be placed into the 8-bit area.");
! *no_add_attrs = true;
}
! else
! DECL_SECTION_NAME (decl) = build_string (6, ".tiny");
! }
! else
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
}
! return NULL_TREE;
}
void
diff -rcpN gcc.orig/config/i386/cygwin.h gcc/config/i386/cygwin.h
*** gcc.orig/config/i386/cygwin.h Tue Aug 28 20:33:32 2001
--- gcc/config/i386/cygwin.h Wed Sep 5 08:12:12 2001
*************** union tree_node;
*** 191,197 ****
It's also used to handle dllimport override semantics. */
#if 0
#define REDO_SECTION_INFO_P(DECL) \
! ((DECL_MACHINE_ATTRIBUTES (DECL) != NULL_TREE) \
|| (TREE_CODE (DECL) == VAR_DECL && DECL_VIRTUAL_P (DECL)))
#else
#define REDO_SECTION_INFO_P(DECL) 1
--- 191,197 ----
It's also used to handle dllimport override semantics. */
#if 0
#define REDO_SECTION_INFO_P(DECL) \
! ((DECL_ATTRIBUTES (DECL) != NULL_TREE) \
|| (TREE_CODE (DECL) == VAR_DECL && DECL_VIRTUAL_P (DECL)))
#else
#define REDO_SECTION_INFO_P(DECL) 1
diff -rcpN gcc.orig/config/i386/i386-protos.h gcc/config/i386/i386-protos.h
*** gcc.orig/config/i386/i386-protos.h Thu Aug 23 17:54:48 2001
--- gcc/config/i386/i386-protos.h Sun Sep 9 15:12:51 2001
*************** extern int ix86_return_pops_args PARAMS
*** 173,181 ****
extern int ix86_data_alignment PARAMS ((tree, int));
extern int ix86_local_alignment PARAMS ((tree, int));
extern int ix86_constant_alignment PARAMS ((tree, int));
! extern int ix86_valid_type_attribute_p PARAMS ((tree, tree, tree, tree));
! extern int i386_pe_valid_decl_attribute_p PARAMS ((tree, tree, tree, tree));
! extern int i386_pe_valid_type_attribute_p PARAMS ((tree, tree, tree, tree));
extern unsigned int i386_pe_section_type_flags PARAMS ((tree, const char *,
int));
extern void i386_pe_asm_named_section PARAMS ((const char *, unsigned int));
--- 173,181 ----
extern int ix86_data_alignment PARAMS ((tree, int));
extern int ix86_local_alignment PARAMS ((tree, int));
extern int ix86_constant_alignment PARAMS ((tree, int));
! extern tree ix86_handle_dll_attribute PARAMS ((tree *, tree, tree, int, bool *));
! extern tree ix86_handle_shared_attribute PARAMS ((tree *, tree, tree, int, bool *));
!
extern unsigned int i386_pe_section_type_flags PARAMS ((tree, const char *,
int));
extern void i386_pe_asm_named_section PARAMS ((const char *, unsigned int));
diff -rcpN gcc.orig/config/i386/i386.c gcc/config/i386/i386.c
*** gcc.orig/config/i386/i386.c Mon Aug 27 07:45:16 2001
--- gcc/config/i386/i386.c Tue Sep 11 21:47:13 2001
*************** static int ix86_fp_comparison_cost PARAM
*** 620,625 ****
--- 620,628 ----
static int ix86_save_reg PARAMS ((int, int));
static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
static int ix86_comp_type_attributes PARAMS ((tree, tree));
+ const struct attribute_spec ix86_attribute_table[];
+ static tree ix86_handle_cdecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
+ static tree ix86_handle_regparm_attribute PARAMS ((tree *, tree, tree, int, bool *));
#ifdef DO_GLOBAL_CTORS_BODY
static void ix86_svr3_asm_out_constructor PARAMS ((rtx, int));
*************** static void sco_asm_out_constructor PARA
*** 630,644 ****
#endif
/* Initialize the GCC target structure. */
! #undef TARGET_VALID_TYPE_ATTRIBUTE
#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
- # define TARGET_VALID_TYPE_ATTRIBUTE i386_pe_valid_type_attribute_p
- # undef TARGET_VALID_DECL_ATTRIBUTE
- # define TARGET_VALID_DECL_ATTRIBUTE i386_pe_valid_decl_attribute_p
# undef TARGET_MERGE_DECL_ATTRIBUTES
# define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
- #else
- # define TARGET_VALID_TYPE_ATTRIBUTE ix86_valid_type_attribute_p
#endif
#undef TARGET_COMP_TYPE_ATTRIBUTES
--- 633,643 ----
#endif
/* Initialize the GCC target structure. */
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE ix86_attribute_table
#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
# undef TARGET_MERGE_DECL_ATTRIBUTES
# define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
#endif
#undef TARGET_COMP_TYPE_ATTRIBUTES
*************** optimization_options (level, size)
*** 928,983 ****
#endif
}
! /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
! attribute for TYPE. The attributes in ATTRIBUTES have previously been
! assigned to TYPE. */
!
! int
! ix86_valid_type_attribute_p (type, attributes, identifier, args)
! tree type;
! tree attributes ATTRIBUTE_UNUSED;
! tree identifier;
! tree args;
{
! if (TREE_CODE (type) != FUNCTION_TYPE
! && TREE_CODE (type) != METHOD_TYPE
! && TREE_CODE (type) != FIELD_DECL
! && TREE_CODE (type) != TYPE_DECL)
! return 0;
!
/* Stdcall attribute says callee is responsible for popping arguments
if they are not variable. */
! if (is_attribute_p ("stdcall", identifier)
! && !TARGET_64BIT)
! return (args == NULL_TREE);
!
! /* Cdecl attribute says the callee is a normal C declaration. */
! if (is_attribute_p ("cdecl", identifier)
! && !TARGET_64BIT)
! return (args == NULL_TREE);
!
/* Regparm attribute specifies how many integer arguments are to be
passed in registers. */
! if (is_attribute_p ("regparm", identifier))
{
! tree cst;
! if (! args || TREE_CODE (args) != TREE_LIST
! || TREE_CHAIN (args) != NULL_TREE
! || TREE_VALUE (args) == NULL_TREE)
! return 0;
! cst = TREE_VALUE (args);
! if (TREE_CODE (cst) != INTEGER_CST)
! return 0;
! if (compare_tree_int (cst, REGPARM_MAX) > 0)
! return 0;
! return 1;
}
! return 0;
}
#if defined (OSF_OS) || defined (TARGET_OSF1ELF)
--- 927,1020 ----
#endif
}
! /* Table of valid machine attributes. */
! const struct attribute_spec ix86_attribute_table[] =
{
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
/* Stdcall attribute says callee is responsible for popping arguments
if they are not variable. */
! { "stdcall", 0, 0, false, true, true, ix86_handle_cdecl_attribute },
! /* Cdecl attribute says the callee is a normal C declaration */
! { "cdecl", 0, 0, false, true, true, ix86_handle_cdecl_attribute },
/* Regparm attribute specifies how many integer arguments are to be
passed in registers. */
! { "regparm", 1, 1, false, true, true, ix86_handle_regparm_attribute },
! #ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
! { "dllimport", 1, 1, false, false, false, ix86_handle_dll_attribute },
! { "dllexport", 1, 1, false, false, false, ix86_handle_dll_attribute },
! { "shared", 1, 1, true, false, false, ix86_handle_shared_attribute },
! #endif
! { NULL, 0, 0, false, false, false, NULL }
! };
!
! /* Handle a "cdecl" or "stdcall" attribute;
! arguments as in struct attribute_spec.handler. */
! static tree
! ix86_handle_cdecl_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (TREE_CODE (*node) != FUNCTION_TYPE
! && TREE_CODE (*node) != METHOD_TYPE
! && TREE_CODE (*node) != FIELD_DECL
! && TREE_CODE (*node) != TYPE_DECL)
{
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! if (TARGET_64BIT)
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! return NULL_TREE;
! }
! /* Handle a "regparm" attribute;
! arguments as in struct attribute_spec.handler. */
! static tree
! ix86_handle_regparm_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args;
! int flags ATTRIBUTE_UNUSED;
! 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)
! {
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! else
! {
! tree cst;
! cst = TREE_VALUE (args);
! if (TREE_CODE (cst) != INTEGER_CST)
! {
! warning ("`%s' attribute requires an integer constant argument",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! else if (compare_tree_int (cst, REGPARM_MAX) > 0)
! {
! warning ("argument to `%s' attribute larger than %d",
! IDENTIFIER_POINTER (name), REGPARM_MAX);
! *no_add_attrs = true;
! }
}
! return NULL_TREE;
}
#if defined (OSF_OS) || defined (TARGET_OSF1ELF)
diff -rcpN gcc.orig/config/i386/winnt.c gcc/config/i386/winnt.c
*** gcc.orig/config/i386/winnt.c Mon Aug 20 17:53:23 2001
--- gcc/config/i386/winnt.c Wed Sep 19 12:01:27 2001
***************
*** 1,6 ****
/* Subroutines for insn-output.c for Windows NT.
Contributed by Douglas Rupp (drupp@cs.washington.edu)
! Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
--- 1,6 ----
/* Subroutines for insn-output.c for Windows NT.
Contributed by Douglas Rupp (drupp@cs.washington.edu)
! Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
*************** int i386_pe_dllimport_p PARAMS ((tree));
*** 49,99 ****
void i386_pe_mark_dllexport PARAMS ((tree));
void i386_pe_mark_dllimport PARAMS ((tree));
! /* Return nonzero if ATTR is a valid attribute for DECL.
! ATTRIBUTES are any existing attributes and ARGS are the arguments
! supplied with ATTR. */
!
! int
! i386_pe_valid_decl_attribute_p (decl, attributes, attr, args)
! tree decl;
! tree attributes ATTRIBUTE_UNUSED;
! tree attr;
tree args;
{
! if (args == NULL_TREE)
{
! if (is_attribute_p ("dllexport", attr))
! return 1;
! if (is_attribute_p ("dllimport", attr))
! return 1;
! if (is_attribute_p ("shared", attr))
! return TREE_CODE (decl) == VAR_DECL;
}
! return 0;
}
! /* Return nonzero if ATTR is a valid attribute for TYPE.
! ATTRIBUTES are any existing attributes and ARGS are the arguments
! supplied with ATTR. */
!
! int
! i386_pe_valid_type_attribute_p (type, attributes, attr, args)
! tree type;
! tree attributes;
! tree attr;
! tree args;
{
! if (args == NULL_TREE
! && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
{
! if (is_attribute_p ("dllexport", attr))
! return 1;
! if (is_attribute_p ("dllimport", attr))
! return 1;
}
! return ix86_valid_type_attribute_p (type, attributes, attr, args);
}
/* Return the type that we should use to determine if DECL is
--- 49,102 ----
void i386_pe_mark_dllexport PARAMS ((tree));
void i386_pe_mark_dllimport PARAMS ((tree));
! /* Handle a "dllimport" or "dllexport" attribute;
! arguments as in struct attribute_spec.handler. */
! tree
! ix86_handle_dll_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
tree args;
+ int flags;
+ bool *no_add_attrs;
{
! /* 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)
! {
! warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
}
! return NULL_TREE;
}
! /* Handle a "shared" attribute;
! arguments as in struct attribute_spec.handler. */
! tree
! ix86_handle_shared_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
{
! if (TREE_CODE (*node) != VAR_DECL)
{
! warning ("`%s' attribute only applies to variables",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
}
! return NULL_TREE;
}
/* Return the type that we should use to determine if DECL is
*************** i386_pe_dllexport_p (decl)
*** 132,138 ****
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
! exp = lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl));
if (exp)
return 1;
--- 135,141 ----
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
! exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
if (exp)
return 1;
*************** i386_pe_dllimport_p (decl)
*** 163,169 ****
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
! imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl));
if (imp)
return 1;
--- 166,172 ----
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
! imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
if (imp)
return 1;
*************** i386_pe_section_type_flags (decl, name,
*** 499,505 ****
flags = SECTION_WRITE;
if (decl && TREE_CODE (decl) == VAR_DECL
! && lookup_attribute ("shared", DECL_MACHINE_ATTRIBUTES (decl)))
flags |= SECTION_PE_SHARED;
}
--- 502,508 ----
flags = SECTION_WRITE;
if (decl && TREE_CODE (decl) == VAR_DECL
! && lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
flags |= SECTION_PE_SHARED;
}
diff -rcpN gcc.orig/config/ia64/ia64.c gcc/config/ia64/ia64.c
*** gcc.orig/config/ia64/ia64.c Fri Aug 24 18:20:43 2001
--- gcc/config/ia64/ia64.c Tue Sep 11 21:47:31 2001
*************** static rtx ia64_expand_compare_and_swap
*** 138,144 ****
static rtx ia64_expand_lock_test_and_set PARAMS ((enum machine_mode,
tree, rtx));
static rtx ia64_expand_lock_release PARAMS ((enum machine_mode, tree, rtx));
! static int ia64_valid_type_attribute PARAMS((tree, tree, tree, tree));
static void ia64_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void ia64_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
static void ia64_output_function_end_prologue PARAMS ((FILE *));
--- 138,144 ----
static rtx ia64_expand_lock_test_and_set PARAMS ((enum machine_mode,
tree, rtx));
static rtx ia64_expand_lock_release PARAMS ((enum machine_mode, tree, rtx));
! const struct attribute_spec ia64_attribute_table[];
static void ia64_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void ia64_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
static void ia64_output_function_end_prologue PARAMS ((FILE *));
*************** static rtx ia64_cycle_display PARAMS ((i
*** 156,163 ****
/* Initialize the GCC target structure. */
! #undef TARGET_VALID_TYPE_ATTRIBUTE
! #define TARGET_VALID_TYPE_ATTRIBUTE ia64_valid_type_attribute
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS ia64_init_builtins
--- 156,163 ----
/* Initialize the GCC target structure. */
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE ia64_attribute_table
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS ia64_init_builtins
*************** ia64_epilogue_uses (regno)
*** 6740,6768 ****
}
}
! /* Return true if IDENTIFIER is a valid attribute for TYPE. */
!
! static int
! ia64_valid_type_attribute (type, attributes, identifier, args)
! tree type;
! tree attributes ATTRIBUTE_UNUSED;
! tree identifier;
! tree args;
{
! /* We only support an attribute for function calls. */
!
! if (TREE_CODE (type) != FUNCTION_TYPE
! && TREE_CODE (type) != METHOD_TYPE)
! return 0;
!
! /* The "syscall_linkage" attribute says the callee is a system call entry
! point. This affects ia64_epilogue_uses. */
!
! if (is_attribute_p ("syscall_linkage", identifier))
! return args == NULL_TREE;
!
! return 0;
! }
/* For ia64, SYMBOL_REF_FLAG set means that it is a function.
--- 6740,6752 ----
}
}
! /* Table of valid machine attributes. */
! const struct attribute_spec ia64_attribute_table[] =
{
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "syscall_linkage", 0, 0, false, true, true, NULL },
! { NULL, 0, 0, false, false, false, NULL }
! };
/* For ia64, SYMBOL_REF_FLAG set means that it is a function.
diff -rcpN gcc.orig/config/m32r/m32r.c gcc/config/m32r/m32r.c
*** gcc.orig/config/m32r/m32r.c Mon Aug 20 17:53:26 2001
--- gcc/config/m32r/m32r.c Tue Sep 11 21:47:48 2001
*************** static int m32r_sched_odd_word_p;
*** 62,69 ****
static void init_reg_tables PARAMS ((void));
static void block_move_call PARAMS ((rtx, rtx, rtx));
static int m32r_is_insn PARAMS ((rtx));
! static int m32r_valid_decl_attribute PARAMS ((tree, tree,
! tree, tree));
static void m32r_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void m32r_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
--- 62,69 ----
static void init_reg_tables PARAMS ((void));
static void block_move_call PARAMS ((rtx, rtx, rtx));
static int m32r_is_insn PARAMS ((rtx));
! const struct attribute_spec m32r_attribute_table[];
! static tree m32r_handle_model_attribute PARAMS ((tree *, tree, tree, int, bool *));
static void m32r_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void m32r_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
*************** static int m32r_issue_rate PARAMS
*** 76,83 ****
/* Initialize the GCC target structure. */
! #undef TARGET_VALID_DECL_ATTRIBUTE
! #define TARGET_VALID_DECL_ATTRIBUTE m32r_valid_decl_attribute
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE m32r_output_function_prologue
--- 76,83 ----
/* Initialize the GCC target structure. */
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE m32r_attribute_table
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE m32r_output_function_prologue
*************** init_reg_tables ()
*** 250,259 ****
Grep for MODEL in m32r.h for more info.
*/
- static tree interrupt_ident1;
- static tree interrupt_ident2;
- static tree model_ident1;
- static tree model_ident2;
static tree small_ident1;
static tree small_ident2;
static tree medium_ident1;
--- 250,255 ----
*************** static tree large_ident2;
*** 264,275 ****
static void
init_idents PARAMS ((void))
{
! if (interrupt_ident1 == 0)
{
- interrupt_ident1 = get_identifier ("interrupt");
- interrupt_ident2 = get_identifier ("__interrupt__");
- model_ident1 = get_identifier ("model");
- model_ident2 = get_identifier ("__model__");
small_ident1 = get_identifier ("small");
small_ident2 = get_identifier ("__small__");
medium_ident1 = get_identifier ("medium");
--- 260,267 ----
static void
init_idents PARAMS ((void))
{
! if (small_ident1 == 0)
{
small_ident1 = get_identifier ("small");
small_ident2 = get_identifier ("__small__");
medium_ident1 = get_identifier ("medium");
*************** init_idents PARAMS ((void))
*** 279,312 ****
}
}
! /* Return nonzero if IDENTIFIER is a valid decl attribute. */
! static int
! m32r_valid_decl_attribute (type, attributes, identifier, args)
! tree type ATTRIBUTE_UNUSED;
! tree attributes ATTRIBUTE_UNUSED;
! tree identifier;
tree args;
{
! init_idents ();
! if ((identifier == interrupt_ident1
! || identifier == interrupt_ident2)
! && list_length (args) == 0)
! return 1;
! if ((identifier == model_ident1
! || identifier == model_ident2)
! && list_length (args) == 1
! && (TREE_VALUE (args) == small_ident1
! || TREE_VALUE (args) == small_ident2
! || TREE_VALUE (args) == medium_ident1
! || TREE_VALUE (args) == medium_ident2
! || TREE_VALUE (args) == large_ident1
! || TREE_VALUE (args) == large_ident2))
! return 1;
! return 0;
}
/* A C statement or statements to switch to the appropriate
--- 271,313 ----
}
}
! const struct attribute_spec m32r_attribute_table[] =
! {
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "interrupt", 0, 0, true, false, false, NULL },
! { "model", 1, 1, true, false, false, m32r_handle_model_attribute },
! { NULL, 0, 0, false, false, false, NULL }
! };
!
! /* Handle an "model" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! m32r_handle_model_attribute (node, name, args, flags, no_add_attrs)
! tree *node ATTRIBUTE_UNUSED;
! tree name;
tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
{
! tree arg;
! init_idents ();
! arg = TREE_VALUE (args);
! if (arg != small_ident1
! && arg != small_ident2
! && arg != medium_ident1
! && arg != medium_ident2
! && arg != large_ident1
! && arg != large_ident2)
! {
! warning ("invalid argument of `%s' attribute",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! return NULL_TREE;
}
/* A C statement or statements to switch to the appropriate
*************** m32r_encode_section_info (decl)
*** 370,376 ****
{
case VAR_DECL :
case FUNCTION_DECL :
! model = lookup_attribute ("model", DECL_MACHINE_ATTRIBUTES (decl));
break;
case STRING_CST :
case CONSTRUCTOR :
--- 371,377 ----
{
case VAR_DECL :
case FUNCTION_DECL :
! model = lookup_attribute ("model", DECL_ATTRIBUTES (decl));
break;
case STRING_CST :
case CONSTRUCTOR :
*************** m32r_compute_function_type (decl)
*** 1747,1753 ****
return fn_type;
/* Compute function type. */
! fn_type = (lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (current_function_decl)) != NULL_TREE
? M32R_FUNCTION_INTERRUPT
: M32R_FUNCTION_NORMAL);
--- 1748,1754 ----
return fn_type;
/* Compute function type. */
! fn_type = (lookup_attribute ("interrupt", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE
? M32R_FUNCTION_INTERRUPT
: M32R_FUNCTION_NORMAL);
diff -rcpN gcc.orig/config/m68hc11/m68hc11.c gcc/config/m68hc11/m68hc11.c
*** gcc.orig/config/m68hc11/m68hc11.c Fri Aug 10 07:30:20 2001
--- gcc/config/m68hc11/m68hc11.c Tue Sep 11 21:48:09 2001
*************** static rtx m68hc11_expand_compare PARAMS
*** 66,73 ****
static int must_parenthesize PARAMS ((rtx));
static int m68hc11_shift_cost PARAMS ((enum machine_mode, rtx, int));
static int m68hc11_auto_inc_p PARAMS ((rtx));
! static int m68hc11_valid_type_attribute_p PARAMS((tree, tree,
! tree, tree));
void create_regs_rtx PARAMS ((void));
static void m68hc11_add_gc_roots PARAMS ((void));
--- 66,73 ----
static int must_parenthesize PARAMS ((rtx));
static int m68hc11_shift_cost PARAMS ((enum machine_mode, rtx, int));
static int m68hc11_auto_inc_p PARAMS ((rtx));
! static tree m68hc11_handle_fntype_attribute PARAMS ((tree *, tree, tree, int, bool *));
! const struct attribute_spec m68hc11_attribute_table[];
void create_regs_rtx PARAMS ((void));
static void m68hc11_add_gc_roots PARAMS ((void));
*************** const char *m68hc11_soft_reg_count;
*** 209,216 ****
static int nb_soft_regs;
/* Initialize the GCC target structure. */
! #undef TARGET_VALID_TYPE_ATTRIBUTE
! #define TARGET_VALID_TYPE_ATTRIBUTE m68hc11_valid_type_attribute_p
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue
--- 209,216 ----
static int nb_soft_regs;
/* Initialize the GCC target structure. */
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE m68hc11_attribute_table
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue
*************** m68hc11_initialize_trampoline (tramp, fn
*** 1130,1159 ****
/* Declaration of types. */
! /* If defined, a C expression whose value is nonzero if IDENTIFIER
! with arguments ARGS is a valid machine specific attribute for TYPE.
! The attributes in ATTRIBUTES have previously been assigned to TYPE. */
!
! static int
! m68hc11_valid_type_attribute_p (type, attributes, identifier, args)
! tree type;
! tree attributes ATTRIBUTE_UNUSED;
! tree identifier;
! tree args;
{
! if (TREE_CODE (type) != FUNCTION_TYPE
! && TREE_CODE (type) != FIELD_DECL && TREE_CODE (type) != TYPE_DECL)
! return 0;
! if (TREE_CODE (type) == FUNCTION_TYPE)
! {
! if (is_attribute_p ("interrupt", identifier))
! return (args == NULL_TREE);
! if (is_attribute_p ("trap", identifier))
! return (args == NULL_TREE);
}
! return 0;
}
/* Define this macro if references to a symbol must be treated
--- 1130,1163 ----
/* Declaration of types. */
! const struct attribute_spec m68hc11_attribute_table[] =
{
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "interrupt", 0, 0, false, true, true, m68hc11_handle_fntype_attribute },
! { "trap", 0, 0, false, true, true, m68hc11_handle_fntype_attribute },
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Handle an attribute requiring a FUNCTION_TYPE, FIELD_DECL or TYPE_DECL;
! arguments as in struct attribute_spec.handler. */
! static tree
! m68hc11_handle_fntype_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (TREE_CODE (*node) != FUNCTION_TYPE
! && TREE_CODE (*node) != FIELD_DECL
! && TREE_CODE (*node) != TYPE_DECL)
! {
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
}
! return NULL_TREE;
}
/* Define this macro if references to a symbol must be treated
diff -rcpN gcc.orig/config/mcore/mcore.c gcc/config/mcore/mcore.c
*** gcc.orig/config/mcore/mcore.c Thu Aug 23 17:54:52 2001
--- gcc/config/mcore/mcore.c Tue Sep 11 21:48:24 2001
*************** static void mcore_mark_dllexport
*** 130,137 ****
static void mcore_mark_dllimport PARAMS ((tree));
static int mcore_dllexport_p PARAMS ((tree));
static int mcore_dllimport_p PARAMS ((tree));
! static int mcore_valid_decl_attribute PARAMS ((tree, tree,
! tree, tree));
static void mcore_asm_named_section PARAMS ((const char *,
unsigned int));
--- 130,137 ----
static void mcore_mark_dllimport PARAMS ((tree));
static int mcore_dllexport_p PARAMS ((tree));
static int mcore_dllimport_p PARAMS ((tree));
! const struct attribute_spec mcore_attribute_table[];
! static tree mcore_handle_naked_attribute PARAMS ((tree *, tree, tree, int, bool *));
static void mcore_asm_named_section PARAMS ((const char *,
unsigned int));
*************** static void mcore_asm_named_section
*** 141,148 ****
#define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
#endif
! #undef TARGET_VALID_DECL_ATTRIBUTE
! #define TARGET_VALID_DECL_ATTRIBUTE mcore_valid_decl_attribute
struct gcc_target targetm = TARGET_INITIALIZER;
--- 141,148 ----
#define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
#endif
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE mcore_attribute_table
struct gcc_target targetm = TARGET_INITIALIZER;
*************** mcore_dllexport_p (decl)
*** 3387,3393 ****
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
! return lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl)) != 0;
}
static int
--- 3387,3393 ----
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
! return lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)) != 0;
}
static int
*************** mcore_dllimport_p (decl)
*** 3398,3404 ****
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
! return lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl)) != 0;
}
/* Cover function to implement ENCODE_SECTION_INFO. */
--- 3398,3404 ----
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
! return lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)) != 0;
}
/* Cover function to implement ENCODE_SECTION_INFO. */
*************** mcore_encode_section_info (decl)
*** 3449,3472 ****
dllexport - for exporting a function/variable that will live in a dll
dllimport - for importing a function/variable from a dll
naked - do not create a function prologue/epilogue. */
- static int
- mcore_valid_decl_attribute (decl, attributes, attr, args)
- tree decl;
- tree attributes ATTRIBUTE_UNUSED;
- tree attr;
- tree args;
- {
- if (args != NULL_TREE)
- return 0;
! if (is_attribute_p ("dllexport", attr))
! return 1;
! if (is_attribute_p ("dllimport", attr))
! return 1;
!
! if (is_attribute_p ("naked", attr) &&
! TREE_CODE (decl) == FUNCTION_DECL)
{
/* PR14310 - don't complain about lack of return statement
in naked functions. The solution here is a gross hack
--- 3449,3475 ----
dllexport - for exporting a function/variable that will live in a dll
dllimport - for importing a function/variable from a dll
naked - do not create a function prologue/epilogue. */
! const struct attribute_spec mcore_attribute_table[] =
! {
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "dllexport", 0, 0, true, false, false, NULL },
! { "dllimport", 0, 0, true, false, false, NULL },
! { "naked", 0, 0, true, false, false, mcore_handle_naked_attribute },
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Handle a "naked" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! mcore_handle_naked_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (TREE_CODE (*node) == FUNCTION_DECL)
{
/* PR14310 - don't complain about lack of return statement
in naked functions. The solution here is a gross hack
*************** mcore_valid_decl_attribute (decl, attrib
*** 3483,3493 ****
}
else if (saved_warn_return_type_count)
saved_warn_return_type_count = 2;
!
! return 1;
}
! return 0;
}
/* Cover function for UNIQUE_SECTION. */
--- 3486,3500 ----
}
else if (saved_warn_return_type_count)
saved_warn_return_type_count = 2;
! }
! else
! {
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
}
! return NULL_TREE;
}
/* Cover function for UNIQUE_SECTION. */
*************** mcore_unique_section (decl, reloc)
*** 3530,3536 ****
int
mcore_naked_function_p ()
{
! return lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (current_function_decl)) != NULL_TREE;
}
static void
--- 3537,3543 ----
int
mcore_naked_function_p ()
{
! return lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
}
static void
diff -rcpN gcc.orig/config/ns32k/ns32k.c gcc/config/ns32k/ns32k.c
*** gcc.orig/config/ns32k/ns32k.c Sat Jul 7 15:05:12 2001
--- gcc/config/ns32k/ns32k.c Wed Sep 19 12:21:26 2001
*************** Boston, MA 02111-1307, USA. */
*** 37,42 ****
--- 37,43 ----
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
+ #include "toplev.h"
#ifdef OSF_OS
int ns32k_num_files = 0;
*************** const char *const ns32k_out_reg_names[]
*** 64,76 ****
static rtx gen_indexed_expr PARAMS ((rtx, rtx, rtx));
static const char *singlemove_string PARAMS ((rtx *));
static void move_tail PARAMS ((rtx[], int, int));
! static int ns32k_valid_type_attribute_p PARAMS ((tree, tree, tree, tree));
static void ns32k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void ns32k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
/* Initialize the GCC target structure. */
! #undef TARGET_VALID_TYPE_ATTRIBUTE
! #define TARGET_VALID_TYPE_ATTRIBUTE ns32k_valid_type_attribute_p
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE ns32k_output_function_prologue
--- 65,78 ----
static rtx gen_indexed_expr PARAMS ((rtx, rtx, rtx));
static const char *singlemove_string PARAMS ((rtx *));
static void move_tail PARAMS ((rtx[], int, int));
! static tree ns32k_handle_fntype_attribute PARAMS ((tree *, tree, tree, int, bool *));
! const struct attribute_spec ns32k_attribute_table[];
static void ns32k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void ns32k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
/* Initialize the GCC target structure. */
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE ns32k_attribute_table
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE ns32k_output_function_prologue
*************** symbolic_reference_mentioned_p (op)
*** 1008,1039 ****
return 0;
}
! /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
! attribute for TYPE. The attributes in ATTRIBUTES have previously been
! assigned to TYPE. */
!
! static int
! ns32k_valid_type_attribute_p (type, attributes, identifier, args)
! tree type;
! tree attributes ATTRIBUTE_UNUSED;
! tree identifier;
! tree args;
! {
! if (TREE_CODE (type) != FUNCTION_TYPE
! && TREE_CODE (type) != FIELD_DECL
! && TREE_CODE (type) != TYPE_DECL)
! return 0;
/* Stdcall attribute says callee is responsible for popping arguments
if they are not variable. */
! if (is_attribute_p ("stdcall", identifier))
! return (args == NULL_TREE);
!
/* Cdecl attribute says the callee is a normal C declaration */
! if (is_attribute_p ("cdecl", identifier))
! return (args == NULL_TREE);
! return 0;
}
--- 1010,1048 ----
return 0;
}
! /* Table of machine-specific attributes. */
+ const struct attribute_spec ns32k_attribute_table[] =
+ {
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
/* Stdcall attribute says callee is responsible for popping arguments
if they are not variable. */
! { "stdcall", 0, 0, false, true, true, ns32k_handle_fntype_attribute },
/* Cdecl attribute says the callee is a normal C declaration */
! { "cdecl", 0, 0, false, true, true, ns32k_handle_fntype_attribute },
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Handle an attribute requiring a FUNCTION_TYPE, FIELD_DECL or TYPE_DECL;
! arguments as in struct attribute_spec.handler. */
! static tree
! ns32k_handle_fntype_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (TREE_CODE (*node) != FUNCTION_TYPE
! && TREE_CODE (*node) != FIELD_DECL
! && TREE_CODE (*node) != TYPE_DECL)
! {
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
!
! return NULL_TREE;
}
diff -rcpN gcc.orig/config/rs6000/rs6000.c gcc/config/rs6000/rs6000.c
*** gcc.orig/config/rs6000/rs6000.c Tue Aug 28 07:08:07 2001
--- gcc/config/rs6000/rs6000.c Tue Sep 11 21:48:58 2001
*************** static int constant_pool_expr_1 PARAMS (
*** 127,133 ****
static void rs6000_free_machine_status PARAMS ((struct function *));
static void rs6000_init_machine_status PARAMS ((struct function *));
static int rs6000_ra_ever_killed PARAMS ((void));
! static int rs6000_valid_type_attribute_p PARAMS ((tree, tree, tree, tree));
static void rs6000_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void rs6000_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
static rtx rs6000_emit_set_long_const PARAMS ((rtx,
--- 127,134 ----
static void rs6000_free_machine_status PARAMS ((struct function *));
static void rs6000_init_machine_status PARAMS ((struct function *));
static int rs6000_ra_ever_killed PARAMS ((void));
! static tree rs6000_handle_longcall_attribute PARAMS ((tree *, tree, tree, int, bool *));
! const struct attribute_spec rs6000_attribute_table[];
static void rs6000_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void rs6000_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
static rtx rs6000_emit_set_long_const PARAMS ((rtx,
*************** static char alt_reg_names[][8] =
*** 184,191 ****
#endif
/* Initialize the GCC target structure. */
! #undef TARGET_VALID_TYPE_ATTRIBUTE
! #define TARGET_VALID_TYPE_ATTRIBUTE rs6000_valid_type_attribute_p
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE rs6000_output_function_prologue
--- 185,192 ----
#endif
/* Initialize the GCC target structure. */
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE rs6000_attribute_table
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE rs6000_output_function_prologue
*************** rs6000_initialize_trampoline (addr, fnad
*** 8124,8151 ****
}
! /* If defined, a C expression whose value is nonzero if IDENTIFIER
! with arguments ARGS is a valid machine specific attribute for TYPE.
! The attributes in ATTRIBUTES have previously been assigned to TYPE. */
!
! static int
! rs6000_valid_type_attribute_p (type, attributes, identifier, args)
! tree type;
! tree attributes ATTRIBUTE_UNUSED;
! tree identifier;
! tree args;
! {
! if (TREE_CODE (type) != FUNCTION_TYPE
! && TREE_CODE (type) != FIELD_DECL
! && TREE_CODE (type) != TYPE_DECL)
! return 0;
! /* Longcall attribute says that the function is not within 2**26 bytes
! of the current function, and to do an indirect call. */
! if (is_attribute_p ("longcall", identifier))
! return (args == NULL_TREE);
! return 0;
}
/* Return a reference suitable for calling a function with the
--- 8125,8158 ----
}
! /* Table of valid machine attributes. */
! const struct attribute_spec rs6000_attribute_table[] =
! {
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Handle a "longcall" attribute;
! arguments as in struct attribute_spec.handler. */
! static tree
! rs6000_handle_longcall_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (TREE_CODE (*node) != FUNCTION_TYPE
! && TREE_CODE (*node) != FIELD_DECL
! && TREE_CODE (*node) != TYPE_DECL)
! {
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! return NULL_TREE;
}
/* Return a reference suitable for calling a function with the
diff -rcpN gcc.orig/config/sh/sh.c gcc/config/sh/sh.c
*** gcc.orig/config/sh/sh.c Fri Aug 31 19:44:17 2001
--- gcc/config/sh/sh.c Wed Sep 19 12:28:06 2001
*************** static int calc_live_regs PARAMS ((int *
*** 154,168 ****
static void mark_use PARAMS ((rtx, rtx *));
static HOST_WIDE_INT rounded_frame_size PARAMS ((int));
static rtx mark_constant_pool_use PARAMS ((rtx));
! static int sh_valid_decl_attribute PARAMS ((tree, tree, tree, tree));
static void sh_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
static void sh_insert_attributes PARAMS ((tree, tree *));
static void sh_asm_named_section PARAMS ((const char *, unsigned int));
static int sh_adjust_cost PARAMS ((rtx, rtx, rtx, int));
/* Initialize the GCC target structure. */
! #undef TARGET_VALID_DECL_ATTRIBUTE
! #define TARGET_VALID_DECL_ATTRIBUTE sh_valid_decl_attribute
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE sh_output_function_epilogue
--- 154,171 ----
static void mark_use PARAMS ((rtx, rtx *));
static HOST_WIDE_INT rounded_frame_size PARAMS ((int));
static rtx mark_constant_pool_use PARAMS ((rtx));
! const struct attribute_spec sh_attribute_table[];
! static tree sh_handle_interrupt_handler_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree sh_handle_sp_switch_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree sh_handle_trap_exit_attribute PARAMS ((tree *, tree, tree, int, bool *));
static void sh_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
static void sh_insert_attributes PARAMS ((tree, tree *));
static void sh_asm_named_section PARAMS ((const char *, unsigned int));
static int sh_adjust_cost PARAMS ((rtx, rtx, rtx, int));
/* Initialize the GCC target structure. */
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE sh_attribute_table
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE sh_output_function_epilogue
*************** print_operand (stream, x, code)
*** 269,275 ****
if ((lookup_attribute
("interrupt_handler",
! DECL_MACHINE_ATTRIBUTES (current_function_decl)))
!= NULL_TREE)
interrupt_handler = 1;
else
--- 272,278 ----
if ((lookup_attribute
("interrupt_handler",
! DECL_ATTRIBUTES (current_function_decl)))
!= NULL_TREE)
interrupt_handler = 1;
else
*************** calc_live_regs (count_ptr, live_regs_mas
*** 3952,3958 ****
if ((lookup_attribute
("interrupt_handler",
! DECL_MACHINE_ATTRIBUTES (current_function_decl)))
!= NULL_TREE)
interrupt_handler = 1;
else
--- 3955,3961 ----
if ((lookup_attribute
("interrupt_handler",
! DECL_ATTRIBUTES (current_function_decl)))
!= NULL_TREE)
interrupt_handler = 1;
else
*************** sh_expand_prologue ()
*** 4040,4046 ****
current_function_interrupt
= lookup_attribute ("interrupt_handler",
! DECL_MACHINE_ATTRIBUTES (current_function_decl))
!= NULL_TREE;
/* We have pretend args if we had an object sent partially in registers
--- 4043,4049 ----
current_function_interrupt
= lookup_attribute ("interrupt_handler",
! DECL_ATTRIBUTES (current_function_decl))
!= NULL_TREE;
/* We have pretend args if we had an object sent partially in registers
*************** sh_insert_attributes (node, attributes)
*** 4638,4648 ****
return;
}
! /* Return nonzero if ATTR is a valid attribute for DECL.
! ATTRIBUTES are any existing attributes and ARGS are the arguments
! supplied with ATTR.
!
! Supported attributes:
interrupt_handler -- specifies this function is an interrupt handler.
--- 4641,4647 ----
return;
}
! /* Supported attributes:
interrupt_handler -- specifies this function is an interrupt handler.
*************** sh_insert_attributes (node, attributes)
*** 4652,4710 ****
trap_exit -- use a trapa to exit an interrupt function instead of
an rte instruction. */
! static int
! sh_valid_decl_attribute (decl, attributes, attr, args)
! tree decl;
! tree attributes ATTRIBUTE_UNUSED;
! tree attr;
! tree args;
{
! if (TREE_CODE (decl) != FUNCTION_DECL)
! return 0;
! if (is_attribute_p ("interrupt_handler", attr))
{
! return 1;
}
!
! if (is_attribute_p ("sp_switch", attr))
{
/* The sp_switch attribute only has meaning for interrupt functions. */
! if (!pragma_interrupt)
! return 0;
!
! /* sp_switch must have an argument. */
! if (!args || TREE_CODE (args) != TREE_LIST)
! return 0;
!
/* The argument must be a constant string. */
! if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
! return 0;
!
sp_switch = gen_rtx_SYMBOL_REF (VOIDmode,
TREE_STRING_POINTER (TREE_VALUE (args)));
- return 1;
}
! if (is_attribute_p ("trap_exit", attr))
{
/* The trap_exit attribute only has meaning for interrupt functions. */
! if (!pragma_interrupt)
! return 0;
!
! /* trap_exit must have an argument. */
! if (!args || TREE_CODE (args) != TREE_LIST)
! return 0;
!
/* The argument must be a constant integer. */
! if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
! return 0;
!
trap_exit = TREE_INT_CST_LOW (TREE_VALUE (args));
- return 1;
}
! return 0;
}
--- 4651,4760 ----
trap_exit -- use a trapa to exit an interrupt function instead of
an rte instruction. */
! const struct attribute_spec sh_attribute_table[] =
{
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "interrupt_handler", 0, 0, true, false, false, sh_handle_interrupt_handler_attribute },
! { "sp_switch", 1, 1, true, false, false, sh_handle_sp_switch_attribute },
! { "trap_exit", 1, 1, true, false, false, sh_handle_trap_exit_attribute },
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Handle an "interrupt_handler" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! sh_handle_interrupt_handler_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (TREE_CODE (*node) != FUNCTION_DECL)
! {
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
!
! return NULL_TREE;
! }
!
! /* Handle an "sp_switch" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! sh_handle_sp_switch_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (TREE_CODE (*node) != FUNCTION_DECL)
{
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
}
! else if (!pragma_interrupt)
{
/* The sp_switch attribute only has meaning for interrupt functions. */
! warning ("`%s' attribute only applies to interrupt functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
! {
/* The argument must be a constant string. */
! warning ("`%s' attribute argument not a string constant",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! else
! {
sp_switch = gen_rtx_SYMBOL_REF (VOIDmode,
TREE_STRING_POINTER (TREE_VALUE (args)));
}
! return NULL_TREE;
! }
!
! /* Handle an "trap_exit" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! sh_handle_trap_exit_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (TREE_CODE (*node) != FUNCTION_DECL)
! {
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! else if (!pragma_interrupt)
{
/* The trap_exit attribute only has meaning for interrupt functions. */
! warning ("`%s' attribute only applies to interrupt functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! else if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
! {
/* The argument must be a constant integer. */
! warning ("`%s' attribute argument not an integer constant",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! else
! {
trap_exit = TREE_INT_CST_LOW (TREE_VALUE (args));
}
! return NULL_TREE;
}
diff -rcpN gcc.orig/config/stormy16/stormy16.c gcc/config/stormy16/stormy16.c
*** gcc.orig/config/stormy16/stormy16.c Fri Aug 31 19:44:17 2001
--- gcc/config/stormy16/stormy16.c Sat Sep 8 23:31:34 2001
*************** stormy16_interrupt_function_p ()
*** 1909,1938 ****
return lookup_attribute ("interrupt", attributes) != NULL_TREE;
}
! /* If defined, a C function which returns nonzero if IDENTIFIER
! with arguments ARGS is a valid machine specific attribute for TYPE.
! The attributes in ATTRIBUTES have previously been assigned to TYPE. */
! #undef TARGET_VALID_TYPE_ATTRIBUTE
! #define TARGET_VALID_TYPE_ATTRIBUTE stormy16_valid_type_attribute
! static int stormy16_valid_type_attribute PARAMS ((tree TYPE,
! tree ATTRIBUTES,
! tree IDENTIFIER,
! tree ARGS));
! static int
! stormy16_valid_type_attribute (type, attributes, identifier, args)
! tree type;
! tree attributes ATTRIBUTE_UNUSED;
! tree identifier;
tree args ATTRIBUTE_UNUSED;
{
! if (TREE_CODE (type) != FUNCTION_TYPE)
! return 0;
!
! if (is_attribute_p ("interrupt", identifier))
! return 1;
! return 0;
}
struct gcc_target targetm = TARGET_INITIALIZER;
--- 1909,1942 ----
return lookup_attribute ("interrupt", attributes) != NULL_TREE;
}
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE stormy16_attribute_table
! static tree stormy16_handle_interrupt_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static const struct attribute_spec stormy16_attribute_table[] =
! {
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "interrupt", 0, 0, false, true, true, stormy16_handle_interrupt_attribute },
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Handle an "interrupt" attribute;
! arguments as in struct attribute_spec.handler. */
! static tree
! stormy16_handle_interrupt_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
{
! if (TREE_CODE (*node) != FUNCTION_TYPE)
! {
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
! return NULL_TREE;
}
struct gcc_target targetm = TARGET_INITIALIZER;
diff -rcpN gcc.orig/config/stormy16/stormy16.h gcc/config/stormy16/stormy16.h
*** gcc.orig/config/stormy16/stormy16.h Mon Sep 3 21:07:25 2001
--- gcc/config/stormy16/stormy16.h Wed Sep 5 08:15:25 2001
*************** enum reg_class
*** 1975,1981 ****
FUNDECL is a C variable whose value is a tree node that describes the
function in question. Normally it is a node of type `FUNCTION_DECL' that
describes the declaration of the function. From this it is possible to
! obtain the DECL_MACHINE_ATTRIBUTES of the function.
FUNTYPE is a C variable whose value is a tree node that describes the
function in question. Normally it is a node of type `FUNCTION_TYPE' that
--- 1975,1981 ----
FUNDECL is a C variable whose value is a tree node that describes the
function in question. Normally it is a node of type `FUNCTION_DECL' that
describes the declaration of the function. From this it is possible to
! obtain the DECL_ATTRIBUTES of the function.
FUNTYPE is a C variable whose value is a tree node that describes the
function in question. Normally it is a node of type `FUNCTION_TYPE' that
diff -rcpN gcc.orig/config/v850/v850-c.c gcc/config/v850/v850-c.c
*** gcc.orig/config/v850/v850-c.c Sat Nov 25 00:43:32 2000
--- gcc/config/v850/v850-c.c Wed Sep 19 12:41:30 2001
*************** Boston, MA 02111-1307, USA. */
*** 35,41 ****
static int pop_data_area PARAMS ((v850_data_area));
static int push_data_area PARAMS ((v850_data_area));
! static int mark_current_function_as_interrupt PARAMS ((void));
/* Push a data area onto the stack. */
--- 35,41 ----
static int pop_data_area PARAMS ((v850_data_area));
static int push_data_area PARAMS ((v850_data_area));
! static void mark_current_function_as_interrupt PARAMS ((void));
/* Push a data area onto the stack. */
*************** pop_data_area (data_area)
*** 85,91 ****
/* Set the machine specific 'interrupt' attribute on the current function. */
! static int
mark_current_function_as_interrupt ()
{
tree name;
--- 85,91 ----
/* Set the machine specific 'interrupt' attribute on the current function. */
! static void
mark_current_function_as_interrupt ()
{
tree name;
*************** mark_current_function_as_interrupt ()
*** 104,111 ****
return 0;
}
! return valid_machine_attribute
! (name, NULL_TREE, current_function_decl, NULL_TREE);
}
--- 104,111 ----
return 0;
}
! decl_attributes (¤t_function_decl,
! tree_cons (name, NULL_TREE, NULL_TREE), 0);
}
diff -rcpN gcc.orig/config/v850/v850.c gcc/config/v850/v850.c
*** gcc.orig/config/v850/v850.c Thu Jul 26 10:03:41 2001
--- gcc/config/v850/v850.c Tue Sep 11 21:49:43 2001
*************** static int const_costs_int PAR
*** 53,59 ****
static void substitute_ep_register PARAMS ((rtx, rtx, int, int, rtx *, rtx *));
static int ep_memory_offset PARAMS ((enum machine_mode, int));
static void v850_set_data_area PARAMS ((tree, v850_data_area));
! static int v850_valid_decl_attribute PARAMS ((tree, tree, tree, tree));
static void v850_insert_attributes PARAMS ((tree, tree *));
/* True if the current function has anonymous arguments. */
--- 53,61 ----
static void substitute_ep_register PARAMS ((rtx, rtx, int, int, rtx *, rtx *));
static int ep_memory_offset PARAMS ((enum machine_mode, int));
static void v850_set_data_area PARAMS ((tree, v850_data_area));
! const struct attribute_spec v850_attribute_table[];
! static tree v850_handle_interrupt_attribute PARAMS ((tree *, tree, tree, int, bool *));
! static tree v850_handle_data_area_attribute PARAMS ((tree *, tree, tree, int, bool *));
static void v850_insert_attributes PARAMS ((tree, tree *));
/* True if the current function has anonymous arguments. */
*************** static int v850_interrupt_cache_p = FALS
*** 84,91 ****
static int v850_interrupt_p = FALSE;
/* Initialize the GCC target structure. */
! #undef TARGET_VALID_DECL_ATTRIBUTE
! #define TARGET_VALID_DECL_ATTRIBUTE v850_valid_decl_attribute
#undef TARGET_INSERT_ATTRIBUTES
#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes
--- 86,93 ----
static int v850_interrupt_p = FALSE;
/* Initialize the GCC target structure. */
! #undef TARGET_ATTRIBUTE_TABLE
! #define TARGET_ATTRIBUTE_TABLE v850_attribute_table
#undef TARGET_INSERT_ATTRIBUTES
#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes
*************** v850_data_area
*** 1978,1990 ****
v850_get_data_area (decl)
tree decl;
{
! if (lookup_attribute ("sda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_SDA;
! if (lookup_attribute ("tda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_TDA;
! if (lookup_attribute ("zda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_ZDA;
return DATA_AREA_NORMAL;
--- 1980,1992 ----
v850_get_data_area (decl)
tree decl;
{
! if (lookup_attribute ("sda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_SDA;
! if (lookup_attribute ("tda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_TDA;
! if (lookup_attribute ("zda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_ZDA;
return DATA_AREA_NORMAL;
*************** v850_set_data_area (decl, data_area)
*** 2008,2069 ****
return;
}
! DECL_MACHINE_ATTRIBUTES (decl) = tree_cons
! (name, NULL, DECL_MACHINE_ATTRIBUTES (decl));
}
! /* Return nonzero if ATTR is a valid attribute for DECL.
! ARGS are the arguments supplied with ATTR. */
! static int
! v850_valid_decl_attribute (decl, unused, attr, args)
! tree decl;
! tree unused ATTRIBUTE_UNUSED;
! tree attr;
! tree args;
{
v850_data_area data_area;
v850_data_area area;
!
! if (args != NULL_TREE)
! return 0;
!
! if (is_attribute_p ("interrupt_handler", attr)
! || is_attribute_p ("interrupt", attr))
! return TREE_CODE (decl) == FUNCTION_DECL;
/* Implement data area attribute. */
! if (is_attribute_p ("sda", attr))
data_area = DATA_AREA_SDA;
! else if (is_attribute_p ("tda", attr))
data_area = DATA_AREA_TDA;
! else if (is_attribute_p ("zda", attr))
data_area = DATA_AREA_ZDA;
else
! return 0;
switch (TREE_CODE (decl))
{
case VAR_DECL:
if (current_function_decl != NULL_TREE)
! error_with_decl (decl, "\
a data area attribute cannot be specified for local variables");
!
/* Drop through. */
case FUNCTION_DECL:
area = v850_get_data_area (decl);
if (area != DATA_AREA_NORMAL && data_area != area)
! error_with_decl (decl, "\
data area of '%s' conflicts with previous declaration");
!
! return 1;
default:
break;
}
!
! return 0;
}
--- 2010,2101 ----
return;
}
! DECL_ATTRIBUTES (decl) = tree_cons
! (name, NULL, DECL_ATTRIBUTES (decl));
}
! const struct attribute_spec v850_attribute_table[] =
! {
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "interrupt_handler", 0, 0, true, false, false, v850_handle_interrupt_attribute },
! { "interrupt", 0, 0, true, false, false, v850_handle_interrupt_attribute },
! { "sda", 0, 0, true, false, false, v850_handle_data_area_attribute },
! { "tda", 0, 0, true, false, false, v850_handle_data_area_attribute },
! { "zda", 0, 0, true, false, false, v850_handle_data_area_attribute },
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Handle an "interrupt" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! v850_handle_interrupt_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! if (TREE_CODE (*node) != FUNCTION_DECL)
! {
! warning ("`%s' attribute only applies to functions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! }
!
! return NULL_TREE;
! }
!
! /* Handle a "sda", "tda" or "zda" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! v850_handle_data_area_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
{
v850_data_area data_area;
v850_data_area area;
! tree decl = *node;
/* Implement data area attribute. */
! if (is_attribute_p ("sda", name))
data_area = DATA_AREA_SDA;
! else if (is_attribute_p ("tda", name))
data_area = DATA_AREA_TDA;
! else if (is_attribute_p ("zda", name))
data_area = DATA_AREA_ZDA;
else
! abort ();
switch (TREE_CODE (decl))
{
case VAR_DECL:
if (current_function_decl != NULL_TREE)
! {
! error_with_decl (decl, "\
a data area attribute cannot be specified for local variables");
! *no_add_attrs = true;
! }
!
/* Drop through. */
case FUNCTION_DECL:
area = v850_get_data_area (decl);
if (area != DATA_AREA_NORMAL && data_area != area)
! {
! error_with_decl (decl, "\
data area of '%s' conflicts with previous declaration");
! *no_add_attrs = true;
! }
! break;
default:
break;
}
!
! return NULL_TREE;
}
*************** v850_interrupt_function_p (func)
*** 2083,2095 ****
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("interrupt_handler", DECL_MACHINE_ATTRIBUTES (func));
if (a != NULL_TREE)
ret = 1;
else
{
! a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));
ret = a != NULL_TREE;
}
--- 2115,2127 ----
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
! a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
if (a != NULL_TREE)
ret = 1;
else
{
! a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
ret = a != NULL_TREE;
}
diff -rcpN gcc.orig/cp/class.c gcc/cp/class.c
*** gcc.orig/cp/class.c Fri Aug 31 10:16:37 2001
--- gcc/cp/class.c Tue Sep 18 15:15:55 2001
*************** finish_struct (t, attributes)
*** 5282,5288 ****
as necessary. */
unreverse_member_declarations (t);
! cplus_decl_attributes (&t, attributes, NULL_TREE, 0);
/* Nadger the current location so that diagnostics point to the start of
the struct, not the end. */
--- 5282,5288 ----
as necessary. */
unreverse_member_declarations (t);
! cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
/* Nadger the current location so that diagnostics point to the start of
the struct, not the end. */
diff -rcpN gcc.orig/cp/cp-tree.h gcc/cp/cp-tree.h
*** gcc.orig/cp/cp-tree.h Fri Aug 24 18:20:44 2001
--- gcc/cp/cp-tree.h Wed Sep 5 09:36:21 2001
*************** extern tree grokbitfield PARAMS ((tree
*** 3733,3739 ****
extern tree groktypefield PARAMS ((tree, tree));
extern tree grokoptypename PARAMS ((tree, tree));
extern int copy_assignment_arg_p PARAMS ((tree, int));
! extern void cplus_decl_attributes PARAMS ((tree *, tree, tree, int));
extern tree constructor_name_full PARAMS ((tree));
extern tree constructor_name PARAMS ((tree));
extern void defer_fn PARAMS ((tree));
--- 3733,3739 ----
extern tree groktypefield PARAMS ((tree, tree));
extern tree grokoptypename PARAMS ((tree, tree));
extern int copy_assignment_arg_p PARAMS ((tree, int));
! extern void cplus_decl_attributes PARAMS ((tree *, tree, int));
extern tree constructor_name_full PARAMS ((tree));
extern tree constructor_name PARAMS ((tree));
extern void defer_fn PARAMS ((tree));
*************** extern tree walk_tree_without_duplicates
*** 4207,4213 ****
walk_tree_fn,
void *));
extern tree copy_tree_r PARAMS ((tree *, int *, void *));
! extern int cp_valid_lang_attribute PARAMS ((tree, tree, tree, tree));
extern tree make_ptrmem_cst PARAMS ((tree, tree));
extern tree cp_build_qualified_type_real PARAMS ((tree, int, int));
extern void remap_save_expr PARAMS ((tree *, splay_tree, tree, int *));
--- 4207,4213 ----
walk_tree_fn,
void *));
extern tree copy_tree_r PARAMS ((tree *, int *, void *));
! extern const struct attribute_spec cp_attribute_table[];
extern tree make_ptrmem_cst PARAMS ((tree, tree));
extern tree cp_build_qualified_type_real PARAMS ((tree, int, int));
extern void remap_save_expr PARAMS ((tree *, splay_tree, tree, int *));
diff -rcpN gcc.orig/cp/decl.c gcc/cp/decl.c
*** gcc.orig/cp/decl.c Wed Sep 5 07:47:53 2001
--- gcc/cp/decl.c Tue Sep 18 16:00:54 2001
*************** Boston, MA 02111-1307, USA. */
*** 45,51 ****
#include "tm_p.h"
#include "target.h"
! extern int (*valid_lang_attribute) PARAMS ((tree, tree, tree, tree));
#ifndef BOOL_TYPE_SIZE
/* `bool' has size and alignment `1', on all platforms. */
--- 45,51 ----
#include "tm_p.h"
#include "target.h"
! extern const struct attribute_spec *lang_attribute_table;
#ifndef BOOL_TYPE_SIZE
/* `bool' has size and alignment `1', on all platforms. */
*************** duplicate_decls (newdecl, olddecl)
*** 3438,3444 ****
/* Copy all the DECL_... slots specified in the new decl
except for any that we copy here from the old type. */
! DECL_MACHINE_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
--- 3438,3444 ----
/* Copy all the DECL_... slots specified in the new decl
except for any that we copy here from the old type. */
! DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
*************** duplicate_decls (newdecl, olddecl)
*** 3746,3752 ****
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
! DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
return 1;
}
--- 3746,3752 ----
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
! DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
return 1;
}
*************** init_decl_processing ()
*** 6493,6499 ****
/* Show we use EH for cleanups. */
using_eh_for_cleanups ();
! valid_lang_attribute = cp_valid_lang_attribute;
/* Maintain consistency. Perhaps we should just complain if they
say -fwritable-strings? */
--- 6493,6499 ----
/* Show we use EH for cleanups. */
using_eh_for_cleanups ();
! lang_attribute_table = cp_attribute_table;
/* Maintain consistency. Perhaps we should just complain if they
say -fwritable-strings? */
*************** shadow_tag (declspecs)
*** 6986,6992 ****
if (TYPE_FIELDS (t))
{
tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
! NULL_TREE);
finish_anon_union (decl);
}
}
--- 6986,6992 ----
if (TYPE_FIELDS (t))
{
tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
! NULL);
finish_anon_union (decl);
}
}
*************** groktypename (typename)
*** 7002,7008 ****
return typename;
return grokdeclarator (TREE_VALUE (typename),
TREE_PURPOSE (typename),
! TYPENAME, 0, NULL_TREE);
}
/* Decode a declarator in an ordinary declaration or data definition.
--- 7002,7008 ----
return typename;
return grokdeclarator (TREE_VALUE (typename),
TREE_PURPOSE (typename),
! TYPENAME, 0, NULL);
}
/* Decode a declarator in an ordinary declaration or data definition.
*************** start_decl (declarator, declspecs, initi
*** 7031,7037 ****
tree context;
extern int have_extern_spec;
extern int used_extern_spec;
- tree attrlist;
#if 0
/* See code below that used this. */
--- 7031,7036 ----
*************** start_decl (declarator, declspecs, initi
*** 7046,7058 ****
used_extern_spec = 1;
}
! if (attributes || prefix_attributes)
! attrlist = build_tree_list (attributes, prefix_attributes);
! else
! attrlist = NULL_TREE;
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
! attrlist);
if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
return NULL_TREE;
--- 7045,7054 ----
used_extern_spec = 1;
}
! attributes = chainon (attributes, prefix_attributes);
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
! &attributes);
if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
return NULL_TREE;
*************** start_decl (declarator, declspecs, initi
*** 7119,7125 ****
}
/* Set attributes here so if duplicate decl, will have proper attributes. */
! cplus_decl_attributes (&decl, attributes, prefix_attributes, 0);
if (context && COMPLETE_TYPE_P (complete_type (context)))
{
--- 7115,7121 ----
}
/* Set attributes here so if duplicate decl, will have proper attributes. */
! cplus_decl_attributes (&decl, attributes, 0);
if (context && COMPLETE_TYPE_P (complete_type (context)))
{
*************** start_handler_parms (declspecs, declarat
*** 8482,8488 ****
if (declspecs)
{
decl = grokdeclarator (declarator, declspecs, CATCHPARM,
! 1, NULL_TREE);
if (decl == NULL_TREE)
error ("invalid catch parameter");
}
--- 8478,8484 ----
if (declspecs)
{
decl = grokdeclarator (declarator, declspecs, CATCHPARM,
! 1, NULL);
if (decl == NULL_TREE)
error ("invalid catch parameter");
}
*************** check_special_function_return_type (sfk,
*** 9425,9432 ****
BITFIELD for a field with specified width.
INITIALIZED is 1 if the decl has an initializer.
! ATTRLIST is a TREE_LIST node with prefix attributes in TREE_VALUE and
! normal attributes in TREE_PURPOSE, or NULL_TREE.
In the TYPENAME case, DECLARATOR is really an abstract declarator.
It may also be so in the PARM case, for a prototype where the
--- 9421,9429 ----
BITFIELD for a field with specified width.
INITIALIZED is 1 if the decl has an initializer.
! ATTRLIST is a pointer to the list of attributes, which may be NULL
! if there are none; *ATTRLIST may be modified if attributes from inside
! the declarator should be applied to the declaration.
In the TYPENAME case, DECLARATOR is really an abstract declarator.
It may also be so in the PARM case, for a prototype where the
*************** grokdeclarator (declarator, declspecs, d
*** 9464,9470 ****
tree declarator;
enum decl_context decl_context;
int initialized;
! tree attrlist;
{
RID_BIT_TYPE specbits;
int nclasses = 0;
--- 9461,9467 ----
tree declarator;
enum decl_context decl_context;
int initialized;
! tree *attrlist;
{
RID_BIT_TYPE specbits;
int nclasses = 0;
*************** grokdeclarator (declarator, declspecs, d
*** 9487,9493 ****
int bitfield = 0;
#if 0
/* See the code below that used this. */
! tree decl_machine_attr = NULL_TREE;
#endif
/* Set this to error_mark_node for FIELD_DECLs we could not handle properly.
All FIELD_DECLs we build here have `init' put into their DECL_INITIAL. */
--- 9484,9490 ----
int bitfield = 0;
#if 0
/* See the code below that used this. */
! tree decl_attr = NULL_TREE;
#endif
/* Set this to error_mark_node for FIELD_DECLs we could not handle properly.
All FIELD_DECLs we build here have `init' put into their DECL_INITIAL. */
*************** grokdeclarator (declarator, declspecs, d
*** 9506,9513 ****
tree raises = NULL_TREE;
int template_count = 0;
tree in_namespace = NULL_TREE;
! tree inner_attrs;
! int ignore_attrs;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
--- 9503,9509 ----
tree raises = NULL_TREE;
int template_count = 0;
tree in_namespace = NULL_TREE;
! tree returned_attrs = NULL_TREE;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
*************** grokdeclarator (declarator, declspecs, d
*** 9598,9621 ****
cp_finish_decl so we can get the variable
initialized... */
! tree attributes, prefix_attributes;
*next = TREE_OPERAND (decl, 0);
init = CALL_DECLARATOR_PARMS (decl);
if (attrlist)
{
! attributes = TREE_PURPOSE (attrlist);
! prefix_attributes = TREE_VALUE (attrlist);
}
else
{
attributes = NULL_TREE;
- prefix_attributes = NULL_TREE;
}
decl = start_decl (declarator, declspecs, 1,
! attributes, prefix_attributes);
decl_type_access_control (decl);
if (decl)
{
--- 9594,9615 ----
cp_finish_decl so we can get the variable
initialized... */
! tree attributes;
*next = TREE_OPERAND (decl, 0);
init = CALL_DECLARATOR_PARMS (decl);
if (attrlist)
{
! attributes = *attrlist;
}
else
{
attributes = NULL_TREE;
}
decl = start_decl (declarator, declspecs, 1,
! attributes, NULL_TREE);
decl_type_access_control (decl);
if (decl)
{
*************** grokdeclarator (declarator, declspecs, d
*** 9953,9959 ****
type = TREE_TYPE (t);
#if 0
/* See the code below that used this. */
! decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
#endif
typedef_decl = t;
}
--- 9947,9953 ----
type = TREE_TYPE (t);
#if 0
/* See the code below that used this. */
! decl_attr = DECL_ATTRIBUTES (id);
#endif
typedef_decl = t;
}
*************** grokdeclarator (declarator, declspecs, d
*** 10312,10320 ****
Descend through it, creating more complex types, until we reach
the declared identifier (or NULL_TREE, in an absolute declarator). */
- inner_attrs = NULL_TREE;
- ignore_attrs = 0;
-
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
&& TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
{
--- 10306,10311 ----
*************** grokdeclarator (declarator, declspecs, d
*** 10363,10390 ****
}
}
- /* See the comment for the TREE_LIST case, below. */
- if (ignore_attrs)
- ignore_attrs = 0;
- else if (inner_attrs)
- {
- decl_attributes (&type, inner_attrs, 0);
- inner_attrs = NULL_TREE;
- }
-
switch (TREE_CODE (declarator))
{
case TREE_LIST:
{
/* We encode a declarator with embedded attributes using
! a TREE_LIST. The attributes apply to the declarator
! directly inside them, so we have to skip an iteration
! before applying them to the type. If the declarator just
! inside is the declarator-id, we apply the attrs to the
! decl itself. */
! inner_attrs = TREE_PURPOSE (declarator);
! ignore_attrs = 1;
declarator = TREE_VALUE (declarator);
}
break;
--- 10354,10383 ----
}
}
switch (TREE_CODE (declarator))
{
case TREE_LIST:
{
/* We encode a declarator with embedded attributes using
! a TREE_LIST. */
! tree attrs = TREE_PURPOSE (declarator);
! tree inner_decl;
declarator = TREE_VALUE (declarator);
+ inner_decl = declarator;
+ while (inner_decl != NULL_TREE
+ && TREE_CODE (inner_decl) == TREE_LIST)
+ inner_decl = TREE_VALUE (inner_decl);
+ int attr_flags = 0;
+ if (inner_decl == NULL_TREE
+ || TREE_CODE (inner_decl) == IDENTIFIER_NODE)
+ attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
+ if (TREE_CODE (inner_decl) == CALL_EXPR)
+ attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
+ if (TREE_CODE (inner_decl) == ARRAY_REF)
+ attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+ returned_attrs = decl_attributes (&type,
+ chainon (returned_attrs, attrs),
+ attr_flags);
}
break;
*************** grokdeclarator (declarator, declspecs, d
*** 10883,10897 ****
}
}
! /* See the comment for the TREE_LIST case, above. */
! if (inner_attrs)
{
! if (! ignore_attrs)
! decl_attributes (&type, inner_attrs, 0);
! else if (attrlist)
! TREE_VALUE (attrlist) = chainon (inner_attrs, TREE_VALUE (attrlist));
else
! attrlist = build_tree_list (NULL_TREE, inner_attrs);
}
/* Now TYPE has the actual type. */
--- 10876,10887 ----
}
}
! if (returned_attrs)
{
! if (attrlist)
! *attrlist = chainon (returned_attrs, *attrlist);
else
! attrlist = &returned_attrs;
}
/* Now TYPE has the actual type. */
*************** friend declaration requires class-key, i
*** 11302,11309 ****
return decl;
#if 0
/* This clobbers the attrs stored in `decl' from `attrlist'. */
! /* The decl and setting of decl_machine_attr is also turned off. */
! decl = build_decl_attribute_variant (decl, decl_machine_attr);
#endif
/* [class.conv.ctor]
--- 11292,11299 ----
return decl;
#if 0
/* This clobbers the attrs stored in `decl' from `attrlist'. */
! /* The decl and setting of decl_attr is also turned off. */
! decl = build_decl_attribute_variant (decl, decl_attr);
#endif
/* [class.conv.ctor]
*************** friend declaration requires class-key, i
*** 11401,11407 ****
}
t = do_friend (ctype, declarator, decl,
! last_function_parms, attrlist, flags, quals,
funcdef_flag);
}
if (t && funcdef_flag)
--- 11391,11397 ----
}
t = do_friend (ctype, declarator, decl,
! last_function_parms, *attrlist, flags, quals,
funcdef_flag);
}
if (t && funcdef_flag)
*************** grokparms (first_parm)
*** 11838,11844 ****
break;
decl = grokdeclarator (TREE_VALUE (decl), TREE_PURPOSE (decl),
! PARM, init != NULL_TREE, NULL_TREE);
if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
--- 11828,11834 ----
break;
decl = grokdeclarator (TREE_VALUE (decl), TREE_PURPOSE (decl),
! PARM, init != NULL_TREE, NULL);
if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
*************** start_function (declspecs, declarator, a
*** 13269,13275 ****
}
else
{
! decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL_TREE);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0;
--- 13259,13265 ----
}
else
{
! decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0;
*************** start_function (declspecs, declarator, a
*** 13554,13560 ****
pushlevel (0);
current_binding_level->parm_flag = 1;
! cplus_decl_attributes (&decl1, NULL_TREE, attrs, 0);
/* Promote the value to int before returning it. */
if (c_promoting_integer_type_p (restype))
--- 13544,13550 ----
pushlevel (0);
current_binding_level->parm_flag = 1;
! cplus_decl_attributes (&decl1, attrs, 0);
/* Promote the value to int before returning it. */
if (c_promoting_integer_type_p (restype))
*************** start_method (declspecs, declarator, att
*** 14056,14062 ****
tree declarator, declspecs, attrlist;
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
! attrlist);
/* Something too ugly to handle. */
if (fndecl == NULL_TREE)
--- 14046,14052 ----
tree declarator, declspecs, attrlist;
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
! &attrlist);
/* Something too ugly to handle. */
if (fndecl == NULL_TREE)
diff -rcpN gcc.orig/cp/decl.h gcc/cp/decl.h
*** gcc.orig/cp/decl.h Wed Jan 26 20:51:34 2000
--- gcc/cp/decl.h Wed Sep 5 08:43:53 2001
*************** enum decl_context
*** 31,37 ****
};
/* We need this in here to get the decl_context definition. */
! extern tree grokdeclarator PARAMS ((tree, tree, enum decl_context, int, tree));
/* Parsing a function declarator leaves a list of parameter names
or a chain or parameter decls here. */
--- 31,37 ----
};
/* We need this in here to get the decl_context definition. */
! extern tree grokdeclarator PARAMS ((tree, tree, enum decl_context, int, tree *));
/* Parsing a function declarator leaves a list of parameter names
or a chain or parameter decls here. */
diff -rcpN gcc.orig/cp/decl2.c gcc/cp/decl2.c
*** gcc.orig/cp/decl2.c Wed Sep 5 07:47:55 2001
--- gcc/cp/decl2.c Wed Sep 19 09:39:03 2001
*************** grokfield (declarator, declspecs, init,
*** 1531,1537 ****
&& TREE_CHAIN (init) == NULL_TREE)
init = NULL_TREE;
! value = grokdeclarator (declarator, declspecs, FIELD, init != 0, attrlist);
if (! value || value == error_mark_node)
/* friend or constructor went bad. */
return value;
--- 1531,1537 ----
&& TREE_CHAIN (init) == NULL_TREE)
init = NULL_TREE;
! value = grokdeclarator (declarator, declspecs, FIELD, init != 0, &attrlist);
if (! value || value == error_mark_node)
/* friend or constructor went bad. */
return value;
*************** grokfield (declarator, declspecs, init,
*** 1628,1635 ****
value = push_template_decl (value);
if (attrlist)
! cplus_decl_attributes (&value, TREE_PURPOSE (attrlist),
! TREE_VALUE (attrlist), 0);
if (TREE_CODE (value) == VAR_DECL)
{
--- 1628,1634 ----
value = push_template_decl (value);
if (attrlist)
! cplus_decl_attributes (&value, attrlist, 0);
if (TREE_CODE (value) == VAR_DECL)
{
*************** grokbitfield (declarator, declspecs, wid
*** 1679,1685 ****
tree declarator, declspecs, width;
{
register tree value = grokdeclarator (declarator, declspecs, BITFIELD,
! 0, NULL_TREE);
if (! value) return NULL_TREE; /* friends went bad. */
--- 1678,1684 ----
tree declarator, declspecs, width;
{
register tree value = grokdeclarator (declarator, declspecs, BITFIELD,
! 0, NULL);
if (! value) return NULL_TREE; /* friends went bad. */
*************** tree
*** 1735,1741 ****
grokoptypename (declspecs, declarator)
tree declspecs, declarator;
{
! tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE);
return mangle_conv_op_name_for_type (t);
}
--- 1734,1740 ----
grokoptypename (declspecs, declarator)
tree declspecs, declarator;
{
! tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL);
return mangle_conv_op_name_for_type (t);
}
*************** grok_function_init (decl, init)
*** 1824,1831 ****
}
void
! cplus_decl_attributes (decl, attributes, prefix_attributes, flags)
! tree *decl, attributes, prefix_attributes;
int flags;
{
if (*decl == NULL_TREE || *decl == void_type_node)
--- 1823,1830 ----
}
void
! cplus_decl_attributes (decl, attributes, flags)
! tree *decl, attributes;
int flags;
{
if (*decl == NULL_TREE || *decl == void_type_node)
*************** cplus_decl_attributes (decl, attributes,
*** 1834,1840 ****
if (TREE_CODE (*decl) == TEMPLATE_DECL)
decl = &DECL_TEMPLATE_RESULT (*decl);
! decl_attributes (decl, chainon (attributes, prefix_attributes), flags);
if (TREE_CODE (*decl) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
--- 1833,1839 ----
if (TREE_CODE (*decl) == TEMPLATE_DECL)
decl = &DECL_TEMPLATE_RESULT (*decl);
! decl_attributes (decl, attributes, flags);
if (TREE_CODE (*decl) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
*************** import_export_class (ctype)
*** 2371,2387 ****
if (CLASSTYPE_INTERFACE_ONLY (ctype))
return;
! if ((*targetm.valid_type_attribute) (ctype,
! TYPE_ATTRIBUTES (ctype),
! get_identifier ("dllimport"),
! NULL_TREE)
! && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype)))
import_export = -1;
! else if ((*targetm.valid_type_attribute) (ctype,
! TYPE_ATTRIBUTES (ctype),
! get_identifier ("dllexport"),
! NULL_TREE)
! && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
import_export = 1;
/* If we got -fno-implicit-templates, we import template classes that
--- 2370,2378 ----
if (CLASSTYPE_INTERFACE_ONLY (ctype))
return;
! if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype)))
import_export = -1;
! else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
import_export = 1;
/* If we got -fno-implicit-templates, we import template classes that
diff -rcpN gcc.orig/cp/friend.c gcc/cp/friend.c
*** gcc.orig/cp/friend.c Fri Jul 13 20:06:43 2001
--- gcc/cp/friend.c Wed Sep 5 09:38:04 2001
*************** do_friend (ctype, declarator, decl, parm
*** 309,315 ****
int funcdef_flag;
{
int is_friend_template = 0;
- tree prefix_attributes, attributes;
/* Every decl that gets here is a friend of something. */
DECL_FRIEND_P (decl) = 1;
--- 309,314 ----
*************** do_friend (ctype, declarator, decl, parm
*** 435,453 ****
handle them in start_decl_1, but since this is a friend decl start_decl_1
never gets to see it. */
- if (attrlist)
- {
- attributes = TREE_PURPOSE (attrlist);
- prefix_attributes = TREE_VALUE (attrlist);
- }
- else
- {
- attributes = NULL_TREE;
- prefix_attributes = NULL_TREE;
- }
-
/* Set attributes here so if duplicate decl, will have proper attributes. */
! cplus_decl_attributes (&decl, attributes, prefix_attributes, 0);
return decl;
}
--- 434,441 ----
handle them in start_decl_1, but since this is a friend decl start_decl_1
never gets to see it. */
/* Set attributes here so if duplicate decl, will have proper attributes. */
! cplus_decl_attributes (&decl, attrlist, 0);
return decl;
}
diff -rcpN gcc.orig/cp/parse.y gcc/cp/parse.y
*** gcc.orig/cp/parse.y Fri Aug 24 18:20:44 2001
--- gcc/cp/parse.y Wed Sep 5 09:38:19 2001
*************** parse_field (declarator, attributes, asm
*** 164,170 ****
tree declarator, attributes, asmspec, init;
{
tree d = grokfield (declarator, current_declspecs, init, asmspec,
! build_tree_list (attributes, prefix_attributes));
decl_type_access_control (d);
return d;
}
--- 164,170 ----
tree declarator, attributes, asmspec, init;
{
tree d = grokfield (declarator, current_declspecs, init, asmspec,
! chainon (attributes, prefix_attributes));
decl_type_access_control (d);
return d;
}
*************** parse_bitfield (declarator, attributes,
*** 182,188 ****
tree declarator, attributes, width;
{
tree d = grokbitfield (declarator, current_declspecs, width);
! cplus_decl_attributes (&d, attributes, prefix_attributes, 0);
decl_type_access_control (d);
return d;
}
--- 182,188 ----
tree declarator, attributes, width;
{
tree d = grokbitfield (declarator, current_declspecs, width);
! cplus_decl_attributes (&d, chainon (attributes, prefix_attributes), 0);
decl_type_access_control (d);
return d;
}
*************** component_decl_1:
*** 2639,2649 ****
$$ = NULL_TREE;
}
| notype_declarator maybeasm maybe_attribute maybe_init
! { $$ = grokfield ($$, NULL_TREE, $4, $2,
! build_tree_list ($3, NULL_TREE)); }
| constructor_declarator maybeasm maybe_attribute maybe_init
! { $$ = grokfield ($$, NULL_TREE, $4, $2,
! build_tree_list ($3, NULL_TREE)); }
| ':' expr_no_commas
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
| error
--- 2639,2647 ----
$$ = NULL_TREE;
}
| notype_declarator maybeasm maybe_attribute maybe_init
! { $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
| constructor_declarator maybeasm maybe_attribute maybe_init
! { $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
| ':' expr_no_commas
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
| error
*************** component_decl_1:
*** 2661,2670 ****
{ tree specs, attrs;
split_specs_attrs ($1.t, &specs, &attrs);
$$ = grokfield ($2, specs, $5, $3,
! build_tree_list ($4, attrs)); }
| component_constructor_declarator maybeasm maybe_attribute maybe_init
! { $$ = grokfield ($$, NULL_TREE, $4, $2,
! build_tree_list ($3, NULL_TREE)); }
| using_decl
{ $$ = do_class_using_decl ($1); }
--- 2659,2667 ----
{ tree specs, attrs;
split_specs_attrs ($1.t, &specs, &attrs);
$$ = grokfield ($2, specs, $5, $3,
! chainon ($4, attrs)); }
| component_constructor_declarator maybeasm maybe_attribute maybe_init
! { $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
| using_decl
{ $$ = do_class_using_decl ($1); }
diff -rcpN gcc.orig/cp/pt.c gcc/cp/pt.c
*** gcc.orig/cp/pt.c Wed Sep 5 07:47:55 2001
--- gcc/cp/pt.c Wed Sep 5 09:35:43 2001
*************** process_template_parm (list, next)
*** 1929,1935 ****
my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
/* is a const-param */
parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
! PARM, 0, NULL_TREE);
/* [temp.param]
--- 1929,1935 ----
my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
/* is a const-param */
parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
! PARM, 0, NULL);
/* [temp.param]
*************** void
*** 9357,9363 ****
do_decl_instantiation (declspecs, declarator, storage)
tree declspecs, declarator, storage;
{
! tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL_TREE);
tree result = NULL_TREE;
int extern_p = 0;
--- 9357,9363 ----
do_decl_instantiation (declspecs, declarator, storage)
tree declspecs, declarator, storage;
{
! tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL);
tree result = NULL_TREE;
int extern_p = 0;
diff -rcpN gcc.orig/cp/tree.c gcc/cp/tree.c
*** gcc.orig/cp/tree.c Mon Aug 27 07:45:26 2001
--- gcc/cp/tree.c Wed Sep 19 10:13:30 2001
*************** static tree verify_stmt_tree_r PARAMS ((
*** 50,55 ****
--- 50,59 ----
static tree find_tree_r PARAMS ((tree *, int *, void *));
extern int cp_statement_code_p PARAMS ((enum tree_code));
+ static tree handle_java_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
+ static tree handle_com_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
+ static tree handle_init_priority_attribute PARAMS ((tree *, tree, tree, int, bool *));
+
/* If REF is an lvalue, returns the kind of lvalue that REF is.
Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
non-zero, rvalues of class type are considered lvalues. */
*************** pod_type_p (t)
*** 2182,2289 ****
return 1;
}
! /* Return a 1 if ATTR_NAME and ATTR_ARGS denote a valid C++-specific
! attribute for either declaration DECL or type TYPE and 0 otherwise.
! Plugged into valid_lang_attribute. */
! int
! cp_valid_lang_attribute (attr_name, attr_args, decl, type)
! tree attr_name;
! tree attr_args ATTRIBUTE_UNUSED;
! tree decl ATTRIBUTE_UNUSED;
! tree type ATTRIBUTE_UNUSED;
! {
! if (is_attribute_p ("java_interface", attr_name))
! {
! if (attr_args != NULL_TREE
! || decl != NULL_TREE
! || ! CLASS_TYPE_P (type)
! || ! TYPE_FOR_JAVA (type))
! {
! error ("`java_interface' attribute can only be applied to Java class definitions");
! return 0;
! }
! TYPE_JAVA_INTERFACE (type) = 1;
! return 1;
}
! if (is_attribute_p ("com_interface", attr_name))
! {
! static int warned;
! if (attr_args != NULL_TREE
! || decl != NULL_TREE
! || ! CLASS_TYPE_P (type)
! || type != TYPE_MAIN_VARIANT (type))
! {
! warning ("`com_interface' attribute can only be applied to class definitions");
! return 0;
! }
! if (! warned++)
! warning ("\
! `com_interface' is obsolete; g++ vtables are now COM-compatible by default");
! return 1;
! }
! else if (is_attribute_p ("init_priority", attr_name))
{
! tree initp_expr = (attr_args ? TREE_VALUE (attr_args): NULL_TREE);
! int pri;
! if (initp_expr)
! STRIP_NOPS (initp_expr);
! if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
! {
! error ("requested init_priority is not an integer constant");
! return 0;
! }
! pri = TREE_INT_CST_LOW (initp_expr);
! type = strip_array_types (type);
! if (decl == NULL_TREE
! || TREE_CODE (decl) != VAR_DECL
! || ! TREE_STATIC (decl)
! || DECL_EXTERNAL (decl)
! || (TREE_CODE (type) != RECORD_TYPE
! && TREE_CODE (type) != UNION_TYPE)
! /* Static objects in functions are initialized the
! first time control passes through that
! function. This is not precise enough to pin down an
! init_priority value, so don't allow it. */
! || current_function_decl)
! {
! error ("can only use init_priority attribute on file-scope definitions of objects of class type");
! return 0;
! }
!
! if (pri > MAX_INIT_PRIORITY || pri <= 0)
! {
! error ("requested init_priority is out of range");
! return 0;
! }
! /* Check for init_priorities that are reserved for
! language and runtime support implementations.*/
! if (pri <= MAX_RESERVED_INIT_PRIORITY)
! {
! warning
! ("requested init_priority is reserved for internal use");
! }
! if (SUPPORTS_INIT_PRIORITY)
! {
! DECL_INIT_PRIORITY (decl) = pri;
! return 1;
! }
! else
! {
! error ("init_priority attribute is not supported on this platform");
! return 0;
! }
}
! return 0;
}
/* Return a new PTRMEM_CST of the indicated TYPE. The MEMBER is the
--- 2186,2330 ----
return 1;
}
! /* Table of valid C++ attributes. */
! const struct attribute_spec cp_attribute_table[] =
! {
! /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
! { "java_interface", 0, 0, false, false, false, handle_java_interface_attribute },
! { "com_interface", 0, 0, false, false, false, handle_com_interface_attribute },
! { "init_priority", 1, 1, true, false, false, handle_init_priority_attribute },
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Handle a "java_interface" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_java_interface_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags;
! bool *no_add_attrs;
! {
! if (DECL_P (*node)
! || !CLASS_TYPE_P (*node)
! || !TYPE_FOR_JAVA (*node))
! {
! error ("`%s' attribute can only be applied to Java class definitions",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! return NULL_TREE;
}
! if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
! *node = build_type_copy (*node);
! TYPE_JAVA_INTERFACE (*node) = 1;
! return NULL_TREE;
! }
!
! /* Handle a "com_interface" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_com_interface_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args ATTRIBUTE_UNUSED;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! static int warned;
!
! *no_add_attrs = true;
!
! if (DECL_P (*node)
! || !CLASS_TYPE_P (*node)
! || *node != TYPE_MAIN_VARIANT (*node))
{
! warning ("`%s' attribute can only be applied to class definitions",
! IDENTIFIER_POINTER (name));
! return NULL_TREE;
! }
!
! if (!warned++)
! warning ("`%s' is obsolete; g++ vtables are now COM-compatible by default",
! IDENTIFIER_POINTER (name));
!
! return NULL_TREE;
! }
!
! /* Handle an "init_priority" attribute; arguments as in
! struct attribute_spec.handler. */
! static tree
! handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
! tree *node;
! tree name;
! tree args;
! int flags ATTRIBUTE_UNUSED;
! bool *no_add_attrs;
! {
! tree initp_expr = TREE_VALUE (args);
! tree decl = *node;
! tree type = TREE_TYPE (decl);
! int pri;
! STRIP_NOPS (initp_expr);
! if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
! {
! error ("requested init_priority is not an integer constant");
! *no_add_attrs = true;
! return NULL_TREE;
! }
! pri = TREE_INT_CST_LOW (initp_expr);
! type = strip_array_types (type);
! if (decl == NULL_TREE
! || TREE_CODE (decl) != VAR_DECL
! || !TREE_STATIC (decl)
! || DECL_EXTERNAL (decl)
! || (TREE_CODE (type) != RECORD_TYPE
! && TREE_CODE (type) != UNION_TYPE)
! /* Static objects in functions are initialized the
! first time control passes through that
! function. This is not precise enough to pin down an
! init_priority value, so don't allow it. */
! || current_function_decl)
! {
! error ("can only use `%s' attribute on file-scope definitions of objects of class type",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! return NULL_TREE;
! }
! if (pri > MAX_INIT_PRIORITY || pri <= 0)
! {
! error ("requested init_priority is out of range");
! *no_add_attrs = true;
! return NULL_TREE;
! }
! /* Check for init_priorities that are reserved for
! language and runtime support implementations.*/
! if (pri <= MAX_RESERVED_INIT_PRIORITY)
! {
! warning
! ("requested init_priority is reserved for internal use");
}
! if (SUPPORTS_INIT_PRIORITY)
! {
! DECL_INIT_PRIORITY (decl) = pri;
! return NULL_TREE;
! }
! else
! {
! error ("`%s' attribute is not supported on this platform",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
! return NULL_TREE;
! }
}
/* Return a new PTRMEM_CST of the indicated TYPE. The MEMBER is the
diff -rcpN gcc.orig/doc/c-tree.texi gcc/doc/c-tree.texi
*** gcc.orig/doc/c-tree.texi Fri Aug 3 11:43:06 2001
--- gcc/doc/c-tree.texi Wed Sep 5 08:12:12 2001
*************** to the same declaration or type, or @cod
*** 1660,1673 ****
further attributes in the list.
Attributes may be attached to declarations and to types; these
! attributes may be accessed with the following macros. At present only
! machine-dependent attributes are stored in this way (other attributes
! cause changes to the declaration or type or to other internal compiler
! data structures, but are not themselves stored along with the
! declaration or type), but in future all attributes may be stored like
! this.
! @deftypefn {Tree Macro} tree DECL_MACHINE_ATTRIBUTES (tree @var{decl})
This macro returns the attributes on the declaration @var{decl}.
@end deftypefn
--- 1660,1670 ----
further attributes in the list.
Attributes may be attached to declarations and to types; these
! attributes may be accessed with the following macros. All attributes
! are stored in this way, and many also cause other changes to the
! declaration or type or to other internal compiler data structures.
! @deftypefn {Tree Macro} tree DECL_ATTRIBUTES (tree @var{decl})
This macro returns the attributes on the declaration @var{decl}.
@end deftypefn
diff -rcpN gcc.orig/doc/extend.texi gcc/doc/extend.texi
*** gcc.orig/doc/extend.texi Mon Aug 20 17:53:29 2001
--- gcc/doc/extend.texi Mon Sep 10 21:32:38 2001
*************** language. Some details may vary for C++
*** 2449,2454 ****
--- 2449,2462 ----
infelicities in the grammar for attributes, some forms described here
may not be successfully parsed in all cases.
+ There are some problems with the semantics of attributes in C++. For
+ example, there are no manglings for attributes, although they may affect
+ code generation, so problems may arise when attributed types are used in
+ conjunction with templates or overloading. Similarly, @code{typeid}
+ does not distinguish between types with different attributes. Support
+ for attributes in C++ may be restricted in future to attributes on
+ declarations only, but not on nested declarators.
+
@xref{Function Attributes}, for details of the semantics of attributes
applying to functions. @xref{Variable Attributes}, for details of the
semantics of attributes applying to variables. @xref{Type Attributes},
*************** defined is not complete until after the
*** 2520,2528 ****
Otherwise, an attribute specifier appears as part of a declaration,
counting declarations of unnamed parameters and type names, and relates
to that declaration (which may be nested in another declaration, for
! example in the case of a parameter declaration). In future, attribute
! specifiers in some places may however apply to a particular declarator
! within a declaration instead; these cases are noted below. Where an
attribute specifier is applied to a parameter declared as a function or
an array, it should apply to the function or array rather than the
pointer to which the parameter is implicitly converted, but this is not
--- 2528,2535 ----
Otherwise, an attribute specifier appears as part of a declaration,
counting declarations of unnamed parameters and type names, and relates
to that declaration (which may be nested in another declaration, for
! example in the case of a parameter declaration), or to a particular declarator
! within a declaration. Where an
attribute specifier is applied to a parameter declared as a function or
an array, it should apply to the function or array rather than the
pointer to which the parameter is implicitly converted, but this is not
*************** ignored.
*** 2597,2607 ****
An attribute specifier list may appear at the start of a nested
declarator. At present, there are some limitations in this usage: the
! attributes apply to the identifier declared, rather than to a specific
! declarator. When attribute specifiers follow the @code{*} of a pointer
declarator, they may be mixed with any type qualifiers present.
! The following describes intended future
! semantics which make this syntax more useful only. It will make the
most sense if you are familiar with the formal specification of
declarators in the ISO C standard.
--- 2604,2614 ----
An attribute specifier list may appear at the start of a nested
declarator. At present, there are some limitations in this usage: the
! attributes correctly apply to the declarator, but for most individual
! attributes the semantics this implies are not implemented.
! When attribute specifiers follow the @code{*} of a pointer
declarator, they may be mixed with any type qualifiers present.
! The following describes the formal semantics of this syntax. It will make the
most sense if you are familiar with the formal specification of
declarators in the ISO C standard.
*************** char *__attribute__((aligned(8))) *f;
*** 2642,2649 ****
@noindent
specifies the type ``pointer to 8-byte-aligned pointer to @code{char}''.
! Note again that this describes intended future semantics, not current
! implementation.
@node Function Prototypes
@section Prototypes and Old-Style Function Definitions
--- 2649,2674 ----
@noindent
specifies the type ``pointer to 8-byte-aligned pointer to @code{char}''.
! Note again that this does not work with most attributes; for example,
! the usage of @samp{aligned} and @samp{noreturn} attributes given above
! is not yet supported.
!
! For compatibility with existing code written for compiler versions that
! did not implement attributes on nested declarators, some laxity is
! allowed in the placing of attributes. If an attribute that only applies
! to types is applied to a declaration, it will be treated as applying to
! the type of that declaration. If an attribute that only applies to
! declarations is applied to the type of a declaration, it will be treated
! as applying to that declaration; and, for compatibility with code
! placing the attributes immediately before the identifier declared, such
! an attribute applied to a function return type will be treated as
! applying to the function type, and such an attribute applied to an array
! element type will be treated as applying to the array type. If an
! attribute that only applies to function types is applied to a
! pointer-to-function type, it will be treated as applying to the pointer
! target type; if such an attribute is applied to a function return type
! that is not a pointer-to-function type, it will be treated as applying
! to the function type.
@node Function Prototypes
@section Prototypes and Old-Style Function Definitions
diff -rcpN gcc.orig/doc/tm.texi gcc/doc/tm.texi
*** gcc.orig/doc/tm.texi Fri Aug 31 10:16:46 2001
--- gcc/doc/tm.texi Tue Sep 18 15:29:25 2001
*************** through the macros defined in the @file{
*** 48,53 ****
--- 48,54 ----
* Debugging Info:: Defining the format of debugging output.
* Cross-compilation:: Handling floating point for cross-compilers.
* Mode Switching:: Insertion of mode-switching instructions.
+ * Target Attributes:: Defining target-specific uses of @code{__attribute__}.
* Misc:: Everything else.
@end menu
*************** macros for which the default definition
*** 70,77 ****
/* @r{Initialize the GCC target structure.} */
! #undef TARGET_VALID_TYPE_ATTRIBUTE
! #define TARGET_VALID_TYPE_ATTRIBUTE @var{machine}_valid_type_attribute_p
struct gcc_target targetm = TARGET_INITIALIZER;
@end smallexample
--- 71,78 ----
/* @r{Initialize the GCC target structure.} */
! #undef TARGET_COMP_TYPE_ATTRIBUTES
! #define TARGET_COMP_TYPE_ATTRIBUTES @var{machine}_comp_type_attributes
struct gcc_target targetm = TARGET_INITIALIZER;
@end smallexample
*************** This describes the stack layout and call
*** 2528,2534 ****
* Caller Saves::
* Function Entry::
* Profiling::
! * Inlining and Tail Calls::
@end menu
@node Frame Layout
--- 2529,2535 ----
* Caller Saves::
* Function Entry::
* Profiling::
! * Tail Calls::
@end menu
@node Frame Layout
*************** after the function returns.
*** 3222,3228 ****
@var{fundecl} is a C variable whose value is a tree node that describes
the function in question. Normally it is a node of type
@code{FUNCTION_DECL} that describes the declaration of the function.
! From this you can obtain the @code{DECL_MACHINE_ATTRIBUTES} of the function.
@var{funtype} is a C variable whose value is a tree node that
describes the function in question. Normally it is a node of type
--- 3223,3229 ----
@var{fundecl} is a C variable whose value is a tree node that describes
the function in question. Normally it is a node of type
@code{FUNCTION_DECL} that describes the declaration of the function.
! From this you can obtain the @code{DECL_ATTRIBUTES} of the function.
@var{funtype} is a C variable whose value is a tree node that
describes the function in question. Normally it is a node of type
*************** profiling when the frame pointer is omit
*** 4204,4221 ****
@end table
! @node Inlining and Tail Calls
! @subsection Permitting inlining and tail calls
! @cindex inlining
@table @code
- @findex FUNCTION_ATTRIBUTE_INLINABLE_P
- @item FUNCTION_ATTRIBUTE_INLINABLE_P (@var{decl})
- A C expression that evaluates to true if it is ok to inline @var{decl}
- into the current function, despite its having target-specific
- attributes. By default, if a function has a target specific attribute
- attached to it, it will not be inlined.
-
@findex FUNCTION_OK_FOR_SIBCALL
@item FUNCTION_OK_FOR_SIBCALL (@var{decl})
A C expression that evaluates to true if it is ok to perform a sibling
--- 4205,4215 ----
@end table
! @node Tail Calls
! @subsection Permitting tail calls
! @cindex tail calls
@table @code
@findex FUNCTION_OK_FOR_SIBCALL
@item FUNCTION_OK_FOR_SIBCALL (@var{decl})
A C expression that evaluates to true if it is ok to perform a sibling
*************** Generate one or more insns to set @var{e
*** 8030,8035 ****
--- 8024,8108 ----
the insn(s) are to be inserted.
@end table
+ @node Target Attributes
+ @section Defining target-specific uses of @code{__attribute__}
+ @cindex target attributes
+ @cindex machine attributes
+ @cindex attributes, target-specific
+
+ Target-specific attributes may be defined for functions, data and types.
+ These are described using the following target hooks; they also need to
+ be documented in @file{extend.texi}.
+
+ @deftypevr {Target Hook} {const struct attribute_spec *} TARGET_ATTRIBUTE_TABLE
+ If defined, this target hook points to an array of @samp{struct
+ attribute_spec} (defined in @file{tree.h}) specifying the machine
+ specific attributes for this target and some of the restrictions on the
+ entities to which these attributes are applied and the arguments they
+ take.
+ @end deftypevr
+
+ @deftypefn {Target Hook} int TARGET_COMP_TYPE_ATTRIBUTES (tree @var{type1}, tree @var{type2})
+ If defined, this target hook is a function which returns zero if the attributes on
+ @var{type1} and @var{type2} are incompatible, one if they are compatible,
+ and two if they are nearly compatible (which causes a warning to be
+ generated). If this is not defined, machine-specific attributes are
+ supposed always to be compatible.
+ @end deftypefn
+
+ @deftypefn {Target Hook} void TARGET_SET_DEFAULT_TYPE_ATTRIBUTES (tree @var{type})
+ If defined, this target hook is a function which assigns default attributes to
+ newly defined @var{type}.
+ @end deftypefn
+
+ @deftypefn {Target Hook} tree TARGET_MERGE_TYPE_ATTRIBUTES (tree @var{type1}, tree @var{type2})
+ Define this target hook if the merging of type attributes needs special
+ handling. If defined, the result is a list of the combined
+ @code{TYPE_ATTRIBUTES} of @var{type1} and @var{type2}. It is assumed
+ that @code{comptypes} has already been called and returned 1. This
+ function may call @code{merge_attributes} to handle machine-independent
+ merging.
+ @end deftypefn
+
+ @deftypefn {Target Hook} tree TARGET_MERGE_DECL_ATTRIBUTES (tree @var{olddecl}, tree @var{newdecl})
+ Define this target hook if the merging of decl attributes needs special
+ handling. If defined, the result is a list of the combined
+ @code{DECL_ATTRIBUTES} of @var{olddecl} and @var{newdecl}.
+ @var{newdecl} is a duplicate declaration of @var{olddecl}. Examples of
+ when this is needed are when one attribute overrides another, or when an
+ attribute is nullified by a subsequent definition. This function may
+ call @code{merge_attributes} to handle machine-independent merging.
+
+ @findex TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ If the only target-specific handling you require is @samp{dllimport} for
+ Windows targets, you should define the macro
+ @code{TARGET_DLLIMPORT_DECL_ATTRIBUTES}. This links in a function
+ called @code{merge_dllimport_decl_attributes} which can then be defined
+ as the expansion of @code{TARGET_MERGE_DECL_ATTRIBUTES}. This is done
+ in @file{i386/cygwin.h} and @file{i386/i386.c}, for example.
+ @end deftypefn
+
+ @deftypefn {Target Hook} void TARGET_INSERT_ATTRIBUTES (tree @var{node}, tree *@var{attr_ptr})
+ Define this target hook if you want to be able to add attributes to a decl
+ when it is being created. This is normally useful for back ends which
+ wish to implement a pragma by using the attributes which correspond to
+ the pragma's effect. The @var{node} argument is the decl which is being
+ created. The @var{attr_ptr} argument is a pointer to the attribute list
+ for this decl. The list itself should not be modified, since it may be
+ shared with other decls, but attributes may be chained on the head of
+ the list and @code{*@var{attr_ptr}} modified to point to the new
+ attributes, or a copy of the list may be made if further changes are
+ needed.
+ @end deftypefn
+
+ @deftypefn {Target Hook} bool TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P (tree @var{fndecl})
+ @cindex inlining
+ This target hook returns @code{true} if it is ok to inline @var{fndecl}
+ into the current function, despite its having target-specific
+ attributes, @code{false} otherwise. By default, if a function has a
+ target specific attribute attached to it, it will not be inlined.
+ @end deftypefn
+
@node Misc
@section Miscellaneous Parameters
@cindex parameters, miscellaneous
*************** other compilers for the same target. In
*** 8403,8409 ****
definition of target-specific pragmas for GCC@.
If the pragma can be implemented by attributes then you should consider
! defining @samp{INSERT_ATTRIBUTES} as well.
Preprocessor macros that appear on pragma lines are not expanded. All
@samp{#pragma} directives that do not match any registered pragma are
--- 8476,8482 ----
definition of target-specific pragmas for GCC@.
If the pragma can be implemented by attributes then you should consider
! defining the target hook @samp{TARGET_INSERT_ATTRIBUTES} as well.
Preprocessor macros that appear on pragma lines are not expanded. All
@samp{#pragma} directives that do not match any registered pragma are
*************** pack value of zero resets the behaviour
*** 8483,8556 ****
invocations of this pragma cause the previous values to be stacked, so
that invocations of @samp{#pragma pack(pop)} will return to the previous
value.
- @end table
-
- @deftypefn {Target Hook} int TARGET_VALID_DECL_ATTRIBUTE (tree @var{decl}, tree @var{attributes}, tree @var{identifier}, tree @var{args})
- If defined, this target hook is a function which returns nonzero if @var{identifier} with
- arguments @var{args} is a valid machine specific attribute for @var{decl}.
- The attributes in @var{attributes} have previously been assigned to @var{decl}.
- @end deftypefn
-
- @deftypefn {Target Hook} int TARGET_VALID_TYPE_ATTRIBUTE (tree @var{type}, tree @var{attributes}, tree @var{identifier}, tree @var{args})
- If defined, this target hook is a function which returns nonzero if @var{identifier} with
- arguments @var{args} is a valid machine specific attribute for @var{type}.
- The attributes in @var{attributes} have previously been assigned to @var{type}.
- @end deftypefn
-
- @deftypefn {Target Hook} int TARGET_COMP_TYPE_ATTRIBUTES (tree @var{type1}, tree @var{type2})
- If defined, this target hook is a function which returns zero if the attributes on
- @var{type1} and @var{type2} are incompatible, one if they are compatible,
- and two if they are nearly compatible (which causes a warning to be
- generated). If this is not defined, machine-specific attributes are
- supposed always to be compatible.
- @end deftypefn
-
- @deftypefn {Target Hook} void TARGET_SET_DEFAULT_TYPE_ATTRIBUTES (tree @var{type})
- If defined, this target hook is a function which assigns default attributes to
- newly defined @var{type}.
- @end deftypefn
- @deftypefn {Target Hook} tree TARGET_MERGE_TYPE_ATTRIBUTES (tree @var{type1}, tree @var{type2})
- Define this target hook if the merging of type attributes needs special
- handling. If defined, the result is a list of the combined
- @code{TYPE_ATTRIBUTES} of @var{type1} and @var{type2}. It is assumed
- that @code{comptypes} has already been called and returned 1. This
- function may call @code{merge_attributes} to handle machine-independent
- merging.
- @end deftypefn
-
- @deftypefn {Target Hook} tree TARGET_MERGE_DECL_ATTRIBUTES (tree @var{olddecl}, tree @var{newdecl})
- Define this target hook if the merging of decl attributes needs special
- handling. If defined, the result is a list of the combined
- @code{DECL_MACHINE_ATTRIBUTES} of @var{olddecl} and @var{newdecl}.
- @var{newdecl} is a duplicate declaration of @var{olddecl}. Examples of
- when this is needed are when one attribute overrides another, or when an
- attribute is nullified by a subsequent definition. This function may
- call @code{merge_attributes} to handle machine-independent merging.
-
- @findex TARGET_DLLIMPORT_DECL_ATTRIBUTES
- If the only target-specific handling you require is @samp{dllimport} for
- Windows targets, you should define the macro
- @code{TARGET_DLLIMPORT_DECL_ATTRIBUTES}. This links in a function
- called @code{merge_dllimport_decl_attributes} which can then be defined
- as the expansion of @code{TARGET_MERGE_DECL_ATTRIBUTES}. This is done
- in @file{i386/cygwin.h} and @file{i386/i386.c}, for example.
- @end deftypefn
-
- @deftypefn {Target Hook} void TARGET_INSERT_ATTRIBUTES (tree @var{node}, tree *@var{attr_ptr})
- Define this target hook if you want to be able to add attributes to a decl
- when it is being created. This is normally useful for back ends which
- wish to implement a pragma by using the attributes which correspond to
- the pragma's effect. The @var{node} argument is the decl which is being
- created. The @var{attr_ptr} argument is a pointer to the attribute list
- for this decl. The list itself should not be modified, since it may be
- shared with other decls, but attributes may be chained on the head of
- the list and @code{*@var{attr_ptr}} modified to point to the new
- attributes, or a copy of the list may be made if further changes are
- needed.
- @end deftypefn
-
- @table @code
@findex DOLLARS_IN_IDENTIFIERS
@item DOLLARS_IN_IDENTIFIERS
Define this macro to control use of the character @samp{$} in identifier
--- 8556,8562 ----
diff -rcpN gcc.orig/ggc-common.c gcc/ggc-common.c
*** gcc.orig/ggc-common.c Sat Sep 1 09:49:53 2001
--- gcc/ggc-common.c Wed Sep 5 08:12:12 2001
*************** ggc_mark_trees ()
*** 374,380 ****
ggc_mark_tree (DECL_INITIAL (t));
ggc_mark_tree (DECL_ABSTRACT_ORIGIN (t));
ggc_mark_tree (DECL_SECTION_NAME (t));
! ggc_mark_tree (DECL_MACHINE_ATTRIBUTES (t));
if (DECL_RTL_SET_P (t))
ggc_mark_rtx (DECL_RTL (t));
ggc_mark_rtx (DECL_LIVE_RANGE_RTL (t));
--- 374,380 ----
ggc_mark_tree (DECL_INITIAL (t));
ggc_mark_tree (DECL_ABSTRACT_ORIGIN (t));
ggc_mark_tree (DECL_SECTION_NAME (t));
! ggc_mark_tree (DECL_ATTRIBUTES (t));
if (DECL_RTL_SET_P (t))
ggc_mark_rtx (DECL_RTL (t));
ggc_mark_rtx (DECL_LIVE_RANGE_RTL (t));
diff -rcpN gcc.orig/integrate.c gcc/integrate.c
*** gcc.orig/integrate.c Sat Sep 1 09:49:53 2001
--- gcc/integrate.c Wed Sep 5 08:12:12 2001
*************** Software Foundation, 59 Temple Place - S
*** 42,47 ****
--- 42,48 ----
#include "loop.h"
#include "params.h"
#include "ggc.h"
+ #include "target.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
*************** extern struct obstack *function_maybeper
*** 63,74 ****
? (1 + (3 * list_length (DECL_ARGUMENTS (DECL))) / 2) \
: (8 * (8 + list_length (DECL_ARGUMENTS (DECL)))))
#endif
-
- /* Decide whether a function with a target specific attribute
- attached can be inlined. By default we disallow this. */
- #ifndef FUNCTION_ATTRIBUTE_INLINABLE_P
- #define FUNCTION_ATTRIBUTE_INLINABLE_P(FNDECL) 0
- #endif
/* Private type used by {get/has}_func_hard_reg_initial_val. */
--- 64,69 ----
*************** typedef struct initial_value_struct {
*** 82,87 ****
--- 77,84 ----
initial_value_pair *entries;
} initial_value_struct;
+ static bool function_attribute_inlinable_p PARAMS ((tree));
+
static void setup_initial_hard_reg_value_integration PARAMS ((struct function *, struct inline_remap *));
static rtvec initialize_for_inline PARAMS ((tree));
*************** get_label_from_map (map, i)
*** 130,135 ****
--- 127,164 ----
return x;
}
+ /* Return false if the function FNDECL cannot be inlined on account of its
+ attributes, true otherwise. */
+ static bool
+ function_attribute_inlinable_p (fndecl)
+ tree fndecl;
+ {
+ bool has_machine_attr = false;
+ tree a;
+
+ for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
+ {
+ tree name = TREE_PURPOSE (a);
+ int i;
+
+ for (i = 0; targetm.attribute_table[i].name != NULL; i++)
+ {
+ if (is_attribute_p (targetm.attribute_table[i].name, name))
+ {
+ has_machine_attr = true;
+ break;
+ }
+ }
+ if (has_machine_attr)
+ break;
+ }
+
+ if (has_machine_attr)
+ return (*targetm.function_attribute_inlinable_p) (fndecl);
+ else
+ return true;
+ }
+
/* Zero if the current function (whose FUNCTION_DECL is FNDECL)
is safe and reasonable to integrate into other functions.
Nonzero means value is a warning msgid with a single %s
*************** function_cannot_inline_p (fndecl)
*** 250,258 ****
/* If the function has a target specific attribute attached to it,
then we assume that we should not inline it. This can be overriden
! by the target if it defines FUNCTION_ATTRIBUTE_INLINABLE_P. */
! if (DECL_MACHINE_ATTRIBUTES (fndecl)
! && ! FUNCTION_ATTRIBUTE_INLINABLE_P (fndecl))
return N_("function with target specific attribute(s) cannot be inlined");
return NULL;
--- 279,286 ----
/* If the function has a target specific attribute attached to it,
then we assume that we should not inline it. This can be overriden
! by the target if it defines TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P. */
! if (!function_attribute_inlinable_p (fndecl))
return N_("function with target specific attribute(s) cannot be inlined");
return NULL;
diff -rcpN gcc.orig/print-tree.c gcc/print-tree.c
*** gcc.orig/print-tree.c Wed Aug 22 20:36:35 2001
--- gcc/print-tree.c Wed Sep 5 08:12:12 2001
***************
*** 1,5 ****
/* Prints out tree in human readable form - GNU C-compiler
! Copyright (C) 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
Free Software Foundation, Inc.
This file is part of GCC.
--- 1,5 ----
/* Prints out tree in human readable form - GNU C-compiler
! Copyright (C) 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This file is part of GCC.
*************** print_node (file, prefix, node, indent)
*** 433,440 ****
}
print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4);
! print_node_brief (file, "machine_attributes",
! DECL_MACHINE_ATTRIBUTES (node), indent + 4);
print_node_brief (file, "abstract_origin",
DECL_ABSTRACT_ORIGIN (node), indent + 4);
--- 433,440 ----
}
print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4);
! print_node_brief (file, "attributes",
! DECL_ATTRIBUTES (node), indent + 4);
print_node_brief (file, "abstract_origin",
DECL_ABSTRACT_ORIGIN (node), indent + 4);
diff -rcpN gcc.orig/target-def.h gcc/target-def.h
*** gcc.orig/target-def.h Fri Aug 31 10:16:31 2001
--- gcc/target-def.h Wed Sep 5 22:14:16 2001
*************** Foundation, 59 Temple Place - Suite 330,
*** 107,117 ****
/* All in tree.c. */
#define TARGET_MERGE_DECL_ATTRIBUTES merge_decl_attributes
#define TARGET_MERGE_TYPE_ATTRIBUTES merge_type_attributes
! #define TARGET_VALID_DECL_ATTRIBUTE default_valid_attribute_p
! #define TARGET_VALID_TYPE_ATTRIBUTE default_valid_attribute_p
#define TARGET_COMP_TYPE_ATTRIBUTES default_comp_type_attributes
#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES default_set_default_type_attributes
#define TARGET_INSERT_ATTRIBUTES default_insert_attributes
/* In builtins.c. */
#define TARGET_INIT_BUILTINS default_init_builtins
--- 107,117 ----
/* All in tree.c. */
#define TARGET_MERGE_DECL_ATTRIBUTES merge_decl_attributes
#define TARGET_MERGE_TYPE_ATTRIBUTES merge_type_attributes
! #define TARGET_ATTRIBUTE_TABLE default_target_attribute_table
#define TARGET_COMP_TYPE_ATTRIBUTES default_comp_type_attributes
#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES default_set_default_type_attributes
#define TARGET_INSERT_ATTRIBUTES default_insert_attributes
+ #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P default_function_attribute_inlinable_p
/* In builtins.c. */
#define TARGET_INIT_BUILTINS default_init_builtins
*************** Foundation, 59 Temple Place - Suite 330,
*** 129,139 ****
TARGET_SCHED, \
TARGET_MERGE_DECL_ATTRIBUTES, \
TARGET_MERGE_TYPE_ATTRIBUTES, \
! TARGET_VALID_DECL_ATTRIBUTE, \
! TARGET_VALID_TYPE_ATTRIBUTE, \
TARGET_COMP_TYPE_ATTRIBUTES, \
TARGET_SET_DEFAULT_TYPE_ATTRIBUTES, \
TARGET_INSERT_ATTRIBUTES, \
TARGET_INIT_BUILTINS, \
TARGET_EXPAND_BUILTIN, \
TARGET_SECTION_TYPE_FLAGS, \
--- 129,139 ----
TARGET_SCHED, \
TARGET_MERGE_DECL_ATTRIBUTES, \
TARGET_MERGE_TYPE_ATTRIBUTES, \
! TARGET_ATTRIBUTE_TABLE, \
TARGET_COMP_TYPE_ATTRIBUTES, \
TARGET_SET_DEFAULT_TYPE_ATTRIBUTES, \
TARGET_INSERT_ATTRIBUTES, \
+ TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P, \
TARGET_INIT_BUILTINS, \
TARGET_EXPAND_BUILTIN, \
TARGET_SECTION_TYPE_FLAGS, \
diff -rcpN gcc.orig/target.h gcc/target.h
*** gcc.orig/target.h Fri Aug 31 10:16:31 2001
--- gcc/target.h Wed Sep 5 22:14:34 2001
*************** struct gcc_target
*** 121,137 ****
/* Given two types, merge their attributes and return the result. */
tree (* merge_type_attributes) PARAMS ((tree, tree));
! /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine
! specific attribute for DECL. The attributes in ATTRIBUTES have
! previously been assigned to DECL. */
! int (* valid_decl_attribute) PARAMS ((tree decl, tree attributes,
! tree identifier, tree args));
!
! /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine
! specific attribute for TYPE. The attributes in ATTRIBUTES have
! previously been assigned to TYPE. */
! int (* valid_type_attribute) PARAMS ((tree type, tree attributes,
! tree identifier, tree args));
/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
one if they are compatible and two if they are nearly compatible
--- 121,128 ----
/* Given two types, merge their attributes and return the result. */
tree (* merge_type_attributes) PARAMS ((tree, tree));
! /* Table of machine attributes and functions to handle them. */
! const struct attribute_spec *attribute_table;
/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
one if they are compatible and two if they are nearly compatible
*************** struct gcc_target
*** 143,148 ****
--- 134,143 ----
/* Insert attributes on the newly created DECL. */
void (* insert_attributes) PARAMS ((tree decl, tree *attributes));
+
+ /* Return true if FNDECL (which has at least one machine attribute)
+ can be inlined despite its machine attributes, false otherwise. */
+ bool (* function_attribute_inlinable_p) PARAMS ((tree fndecl));
/* Set up target-specific built-in functions. */
void (* init_builtins) PARAMS ((void));
diff -rcpN gcc.orig/testsuite/g++.dg/ext/attrib1.C gcc/testsuite/g++.dg/ext/attrib1.C
*** gcc.orig/testsuite/g++.dg/ext/attrib1.C Thu Jan 1 00:00:00 1970
--- gcc/testsuite/g++.dg/ext/attrib1.C Tue Sep 18 12:41:08 2001
***************
*** 0 ****
--- 1,10 ----
+ // Test for interpretation of attribute immediately before function name.
+ // Origin: Joseph Myers <jsm28@cam.ac.uk>
+ // { dg-do compile }
+
+ // An attribute immediately before the function name should in this
+ // case properly apply to the return type, but compatibility with
+ // existing code using this form requires it to apply to the function
+ // type instead in the case of attributes applying to function types,
+ // and to the declaration in the case of attributes applying to declarations.
+ int ****__attribute__((format(printf, 1, 2))) foo(const char *, ...);
diff -rcpN gcc.orig/tree.c gcc/tree.c
*** gcc.orig/tree.c Wed Aug 29 09:24:22 2001
--- gcc/tree.c Wed Sep 5 22:15:38 2001
*************** build_expr_wfl (node, file, line, col)
*** 2622,2635 ****
return wfl;
}
! /* Return a declaration like DDECL except that its DECL_MACHINE_ATTRIBUTE
is ATTRIBUTE. */
tree
build_decl_attribute_variant (ddecl, attribute)
tree ddecl, attribute;
{
! DECL_MACHINE_ATTRIBUTES (ddecl) = attribute;
return ddecl;
}
--- 2622,2635 ----
return wfl;
}
! /* Return a declaration like DDECL except that its DECL_ATTRIBUTES
is ATTRIBUTE. */
tree
build_decl_attribute_variant (ddecl, attribute)
tree ddecl, attribute;
{
! DECL_ATTRIBUTES (ddecl) = attribute;
return ddecl;
}
*************** build_type_attribute_variant (ttype, att
*** 2687,2705 ****
return ttype;
}
- /* Default value of targetm.valid_decl_attribute_p and
- targetm.valid_type_attribute_p that always returns false. */
-
- int
- default_valid_attribute_p (attr_name, attr_args, decl, type)
- tree attr_name ATTRIBUTE_UNUSED;
- tree attr_args ATTRIBUTE_UNUSED;
- tree decl ATTRIBUTE_UNUSED;
- tree type ATTRIBUTE_UNUSED;
- {
- return 0;
- }
-
/* Default value of targetm.comp_type_attributes that always returns 1. */
int
--- 2687,2692 ----
*************** default_insert_attributes (decl, attr_pt
*** 2727,2842 ****
{
}
! /* Return 1 if ATTR_NAME and ATTR_ARGS is valid for either declaration
! DECL or type TYPE and 0 otherwise. Validity is determined the
! target functions valid_decl_attribute and valid_machine_attribute. */
!
! int
! valid_machine_attribute (attr_name, attr_args, decl, type)
! tree attr_name;
! tree attr_args;
! tree decl;
! tree type;
{
! tree type_attrs;
!
! if (TREE_CODE (attr_name) != IDENTIFIER_NODE)
! abort ();
!
! if (decl)
! {
! tree decl_attrs = DECL_MACHINE_ATTRIBUTES (decl);
!
! if ((*targetm.valid_decl_attribute) (decl, decl_attrs, attr_name,
! attr_args))
! {
! tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
! decl_attrs);
!
! if (attr != NULL_TREE)
! {
! /* Override existing arguments. Declarations are unique
! so we can modify this in place. */
! TREE_VALUE (attr) = attr_args;
! }
! else
! {
! decl_attrs = tree_cons (attr_name, attr_args, decl_attrs);
! decl = build_decl_attribute_variant (decl, decl_attrs);
! }
!
! /* Don't apply the attribute to both the decl and the type. */
! return 1;
! }
! }
!
! type_attrs = TYPE_ATTRIBUTES (type);
! if ((*targetm.valid_type_attribute) (type, type_attrs, attr_name,
! attr_args))
! {
! tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
! type_attrs);
! if (attr != NULL_TREE)
! {
! /* Override existing arguments. ??? This currently
! works since attribute arguments are not included in
! `attribute_hash_list'. Something more complicated
! may be needed in the future. */
! TREE_VALUE (attr) = attr_args;
! }
! else
! {
! /* If this is part of a declaration, create a type variant,
! otherwise, this is part of a type definition, so add it
! to the base type. */
! type_attrs = tree_cons (attr_name, attr_args, type_attrs);
! if (decl != 0)
! type = build_type_attribute_variant (type, type_attrs);
! else
! TYPE_ATTRIBUTES (type) = type_attrs;
! }
!
! if (decl)
! TREE_TYPE (decl) = type;
!
! return 1;
! }
! /* Handle putting a type attribute on pointer-to-function-type
! by putting the attribute on the function type. */
! else if (POINTER_TYPE_P (type)
! && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
! && (*targetm.valid_type_attribute) (TREE_TYPE (type), type_attrs,
! attr_name, attr_args))
! {
! tree inner_type = TREE_TYPE (type);
! tree inner_attrs = TYPE_ATTRIBUTES (inner_type);
! tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
! type_attrs);
!
! if (attr != NULL_TREE)
! TREE_VALUE (attr) = attr_args;
! else
! {
! inner_attrs = tree_cons (attr_name, attr_args, inner_attrs);
! inner_type = build_type_attribute_variant (inner_type,
! inner_attrs);
! }
!
! if (decl)
! TREE_TYPE (decl) = build_pointer_type (inner_type);
! else
! {
! /* Clear TYPE_POINTER_TO for the old inner type, since
! `type' won't be pointing to it anymore. */
! TYPE_POINTER_TO (TREE_TYPE (type)) = NULL_TREE;
! TREE_TYPE (type) = inner_type;
! }
!
! return 1;
! }
!
! return 0;
}
/* Return non-zero if IDENT is a valid name for attribute ATTR,
--- 2714,2733 ----
{
}
! /* Default value of targetm.attribute_table that is empty. */
! const struct attribute_spec default_target_attribute_table[] =
{
! { NULL, 0, 0, false, false, false, NULL }
! };
! /* Default value of targetm.function_attribute_inlinable_p that always
! returns false. */
! bool
! default_function_attribute_inlinable_p (fndecl)
! tree fndecl ATTRIBUTE_UNUSED;
! {
! /* By default, functions with machine attributes cannot be inlined. */
! return false;
}
/* Return non-zero if IDENT is a valid name for attribute ATTR,
*************** is_attribute_p (attr, ident)
*** 2890,2896 ****
/* Given an attribute name and a list of attributes, return a pointer to the
attribute's list element if the attribute is part of the list, or NULL_TREE
! if not found. */
tree
lookup_attribute (attr_name, list)
--- 2781,2789 ----
/* Given an attribute name and a list of attributes, return a pointer to the
attribute's list element if the attribute is part of the list, or NULL_TREE
! if not found. If the attribute appears more than once, this only
! returns the first occurance; the TREE_CHAIN of the return value should
! be passed back in if further occurances are wanted. */
tree
lookup_attribute (attr_name, list)
*************** merge_attributes (a1, a2)
*** 2932,2950 ****
else
{
/* Pick the longest list, and hang on the other list. */
- /* ??? For the moment we punt on the issue of attrs with args. */
if (list_length (a1) < list_length (a2))
attributes = a2, a2 = a1;
for (; a2 != 0; a2 = TREE_CHAIN (a2))
! if (lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
! attributes) == NULL_TREE)
! {
! a1 = copy_node (a2);
! TREE_CHAIN (a1) = attributes;
! attributes = a1;
! }
}
}
return attributes;
--- 2825,2853 ----
else
{
/* Pick the longest list, and hang on the other list. */
if (list_length (a1) < list_length (a2))
attributes = a2, a2 = a1;
for (; a2 != 0; a2 = TREE_CHAIN (a2))
! {
! tree a;
! for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
! attributes);
! a != NULL_TREE;
! a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
! TREE_CHAIN (a)))
! {
! if (simple_cst_equal (TREE_VALUE (a), TREE_VALUE (a2)) == 1)
! break;
! }
! if (a == NULL_TREE)
! {
! a1 = copy_node (a2);
! TREE_CHAIN (a1) = attributes;
! attributes = a1;
! }
! }
}
}
return attributes;
*************** tree
*** 2968,2975 ****
merge_decl_attributes (olddecl, newdecl)
tree olddecl, newdecl;
{
! return merge_attributes (DECL_MACHINE_ATTRIBUTES (olddecl),
! DECL_MACHINE_ATTRIBUTES (newdecl));
}
#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
--- 2871,2878 ----
merge_decl_attributes (olddecl, newdecl)
tree olddecl, newdecl;
{
! return merge_attributes (DECL_ATTRIBUTES (olddecl),
! DECL_ATTRIBUTES (newdecl));
}
#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
*************** merge_dllimport_decl_attributes (old, ne
*** 2991,2998 ****
tree a;
int delete_dllimport_p;
! old = DECL_MACHINE_ATTRIBUTES (old);
! new = DECL_MACHINE_ATTRIBUTES (new);
/* What we need to do here is remove from `old' dllimport if it doesn't
appear in `new'. dllimport behaves like extern: if a declaration is
--- 2894,2901 ----
tree a;
int delete_dllimport_p;
! old = DECL_ATTRIBUTES (old);
! new = DECL_ATTRIBUTES (new);
/* What we need to do here is remove from `old' dllimport if it doesn't
appear in `new'. dllimport behaves like extern: if a declaration is
*************** attribute_list_contained (l1, l2)
*** 3368,3375 ****
for (; t2 != 0; t2 = TREE_CHAIN (t2))
{
! tree attr
! = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
if (attr == 0)
return 0;
--- 3271,3285 ----
for (; t2 != 0; t2 = TREE_CHAIN (t2))
{
! tree attr;
! for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
! attr != NULL_TREE;
! attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
! TREE_CHAIN (attr)))
! {
! if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1)
! break;
! }
if (attr == 0)
return 0;
diff -rcpN gcc.orig/tree.h gcc/tree.h
*** gcc.orig/tree.h Sat Sep 1 09:49:53 2001
--- gcc/tree.h Tue Sep 18 15:04:54 2001
***************
*** 1,5 ****
/* Front-end tree definitions for GNU compiler.
! Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
Free Software Foundation, Inc.
This file is part of GCC.
--- 1,5 ----
/* Front-end tree definitions for GNU compiler.
! Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This file is part of GCC.
*************** struct tree_type
*** 1339,1347 ****
type, or NULL_TREE if the given decl has "file scope". */
#define DECL_CONTEXT(NODE) (DECL_CHECK (NODE)->decl.context)
#define DECL_FIELD_CONTEXT(NODE) (FIELD_DECL_CHECK (NODE)->decl.context)
! /* In a DECL this is the field where configuration dependent machine
! attributes are store */
! #define DECL_MACHINE_ATTRIBUTES(NODE) (DECL_CHECK (NODE)->decl.machine_attributes)
/* In a FIELD_DECL, this is the field position, counting in bytes, of the
byte containing the bit closest to the beginning of the structure. */
#define DECL_FIELD_OFFSET(NODE) (FIELD_DECL_CHECK (NODE)->decl.arguments)
--- 1339,1346 ----
type, or NULL_TREE if the given decl has "file scope". */
#define DECL_CONTEXT(NODE) (DECL_CHECK (NODE)->decl.context)
#define DECL_FIELD_CONTEXT(NODE) (FIELD_DECL_CHECK (NODE)->decl.context)
! /* In a DECL this is the field where attributes are stored. */
! #define DECL_ATTRIBUTES(NODE) (DECL_CHECK (NODE)->decl.attributes)
/* In a FIELD_DECL, this is the field position, counting in bytes, of the
byte containing the bit closest to the beginning of the structure. */
#define DECL_FIELD_OFFSET(NODE) (FIELD_DECL_CHECK (NODE)->decl.arguments)
*************** struct tree_decl
*** 1756,1762 ****
tree abstract_origin;
tree assembler_name;
tree section_name;
! tree machine_attributes;
rtx rtl; /* RTL representation for object. */
rtx live_range_rtl;
--- 1755,1761 ----
tree abstract_origin;
tree assembler_name;
tree section_name;
! tree attributes;
rtx rtl; /* RTL representation for object. */
rtx live_range_rtl;
*************** extern tree make_tree PARAMS ((tree, r
*** 2071,2084 ****
extern tree build_type_attribute_variant PARAMS ((tree, tree));
extern tree build_decl_attribute_variant PARAMS ((tree, tree));
/* Default versions of target-overridable functions. */
extern tree merge_decl_attributes PARAMS ((tree, tree));
extern tree merge_type_attributes PARAMS ((tree, tree));
- extern int default_valid_attribute_p PARAMS ((tree, tree, tree, tree));
extern int default_comp_type_attributes PARAMS ((tree, tree));
extern void default_set_default_type_attributes PARAMS ((tree));
extern void default_insert_attributes PARAMS ((tree, tree *));
/* Split a list of declspecs and attributes into two. */
--- 2070,2151 ----
extern tree build_type_attribute_variant PARAMS ((tree, tree));
extern tree build_decl_attribute_variant PARAMS ((tree, tree));
+ /* Structure describing an attribute and a function to handle it. */
+ struct attribute_spec
+ {
+ /* The name of the attribute (without any leading or trailing __),
+ or NULL to mark the end of a table of attributes. */
+ const char *name;
+ /* The minimum length of the list of arguments of the attribute. */
+ int min_length;
+ /* The maximum length of the list of arguments of the attribute
+ (-1 for no maximum). */
+ int max_length;
+ /* Whether this attribute requires a DECL. If it does, it will be passed
+ from types of DECLs, function return types and array element types to
+ the DECLs, function types and array types respectively; but when
+ applied to a type in any other circumstances, it will be ignored with
+ a warning. (If greater control is desired for a given attribute,
+ this should be false, and the flags argument to the handler may be
+ used to gain greater control in that case.) */
+ bool decl_required;
+ /* Whether this attribute requires a type. If it does, it will be passed
+ from a DECL to the type of that DECL. */
+ bool type_required;
+ /* Whether this attribute requires a function (or method) type. If it does,
+ it will be passed from a function pointer type to the target type,
+ and from a function return type (which is not itself a function
+ pointer type) to the function type. */
+ bool function_type_required;
+ /* Function to handle this attribute. NODE points to the node to which
+ the attribute is to be applied. If a DECL, it should be modified in
+ place; if a TYPE, a copy should be created. NAME is the name of the
+ attribute (possibly with leading or trailing __). ARGS is the TREE_LIST
+ of the arguments (which may be NULL). FLAGS gives further information
+ about the context of the attribute. Afterwards, the attributes will
+ be added to the DECL_ATTRIBUTES or TYPE_ATTRIBUTES, as appropriate,
+ unless *NO_ADD_ATTRS is set to true (which should be done on error,
+ as well as in any other cases when the attributes should not be added
+ to the DECL or TYPE). Depending on FLAGS, any attributes to be
+ applied to another type or DECL later may be returned;
+ 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) PARAMS ((tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs));
+ };
+
+ extern const struct attribute_spec default_target_attribute_table[];
+
+ /* Flags that may be passed in the third argument of decl_attributes, and
+ to handler functions for attributes. */
+ enum attribute_flags
+ {
+ /* The type passed in is the type of a DECL, and any attributes that
+ should be passed in again to be applied to the DECL rather than the
+ type should be returned. */
+ ATTR_FLAG_DECL_NEXT = 1,
+ /* The type passed in is a function return type, and any attributes that
+ should be passed in again to be applied to the function type rather
+ than the return type should be returned. */
+ ATTR_FLAG_FUNCTION_NEXT = 2,
+ /* The type passed in is an array element type, and any attributes that
+ should be passed in again to be applied to the array type rather
+ than the element type should be returned. */
+ ATTR_FLAG_ARRAY_NEXT = 4,
+ /* The type passed in is a structure, union or enumeration type being
+ created, and should be modified in place. */
+ ATTR_FLAG_TYPE_IN_PLACE = 8
+ };
+
/* Default versions of target-overridable functions. */
extern tree merge_decl_attributes PARAMS ((tree, tree));
extern tree merge_type_attributes PARAMS ((tree, tree));
extern int default_comp_type_attributes PARAMS ((tree, tree));
extern void default_set_default_type_attributes PARAMS ((tree));
extern void default_insert_attributes PARAMS ((tree, tree *));
+ extern bool default_function_attribute_inlinable_p PARAMS ((tree));
/* Split a list of declspecs and attributes into two. */
--
Joseph S. Myers
jsm28@cam.ac.uk