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:
	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:
	Table-driven attributes.
	* g++.dg/ext/attrib1.C: New test.

From-SVN: r45718
This commit is contained in:
Joseph Myers 2001-09-21 02:27:06 +01:00 committed by Joseph Myers
parent 3007d592bf
commit 91d231cb91
54 changed files with 2642 additions and 1656 deletions

View File

@ -1,3 +1,185 @@
2001-09-21 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.
Fri Sep 21 01:49:41 2001 J"orn Rennecke <amylaar@redhat.com>
* sh-protos.h (sh_pr_n_sets): Declare.

View File

@ -1436,7 +1436,7 @@ real.o : real.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) toplev.h $(TM_P_H)
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)
$(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)

File diff suppressed because it is too large Load Diff

View File

@ -503,29 +503,14 @@ extern const char *fname_as_string PARAMS ((int));
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 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));

View File

@ -1404,7 +1404,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
int errmsg = 0;
if (DECL_P (olddecl))
DECL_MACHINE_ATTRIBUTES (newdecl)
DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
if (TREE_CODE (newtype) == ERROR_MARK
@ -2030,7 +2030,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
return 1;
}
@ -3872,9 +3872,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
enum tree_code innermost_code = ERROR_MARK;
int bitfield = 0;
int size_varies = 0;
tree decl_machine_attr = NULL_TREE;
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;
@ -3898,6 +3899,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
decl = TREE_OPERAND (decl, 0);
break;
case TREE_LIST:
decl = TREE_VALUE (decl);
break;
case IDENTIFIER_NODE:
name = IDENTIFIER_POINTER (decl);
decl = 0;
@ -3979,7 +3984,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
else if (TREE_CODE (id) == TYPE_DECL)
{
type = TREE_TYPE (id);
decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
decl_attr = DECL_ATTRIBUTES (id);
typedef_decl = id;
}
/* Built-in types come as identifiers. */
@ -4292,6 +4297,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
/* 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).
@ -4313,7 +4319,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
array_parm_static = 0;
}
if (TREE_CODE (declarator) == ARRAY_REF)
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);
@ -4657,6 +4686,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
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;
}
@ -4687,6 +4717,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
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;
}
@ -4711,7 +4742,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */
{
register tree decl;
tree decl;
if (decl_context == PARM)
{
@ -4860,7 +4891,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
pedwarn ("invalid storage class for function `%s'", name);
decl = build_decl (FUNCTION_DECL, declarator, type);
decl = build_decl_attribute_variant (decl, decl_machine_attr);
decl = build_decl_attribute_variant (decl, decl_attr);
if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
@ -4953,6 +4984,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
mark_addressable (decl);
decl_attributes (&decl, returned_attrs, 0);
return decl;
}
}
@ -5341,7 +5374,7 @@ finish_struct (t, fieldlist, attributes)
TYPE_SIZE (t) = 0;
decl_attributes (&t, attributes, 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)
@ -5705,7 +5738,7 @@ finish_enum (enumtype, values, attributes)
if (in_parm_level_p ())
warning ("enum defined inside parms");
decl_attributes (&enumtype, attributes, 0);
decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
/* Calculate the maximum value of any enumerator in this type. */

View File

@ -82,14 +82,17 @@ static void record_function_format PARAMS ((tree, tree, enum format_type,
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;
/* 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));
@ -104,13 +107,15 @@ decl_handle_format_attribute (decl, args)
{
error_with_decl (decl,
"argument format specified for non-function `%s'");
return;
*no_add_attrs = true;
return NULL_TREE;
}
if (TREE_CODE (format_type_id) != IDENTIFIER_NODE)
{
error ("unrecognized format specifier");
return;
*no_add_attrs = true;
return NULL_TREE;
}
else
{
@ -121,7 +126,8 @@ decl_handle_format_attribute (decl, args)
if (format_type == format_type_error)
{
warning ("`%s' is an unrecognized format function type", p);
return;
*no_add_attrs = true;
return NULL_TREE;
}
}
@ -143,7 +149,8 @@ decl_handle_format_attribute (decl, args)
|| TREE_INT_CST_HIGH (first_arg_num_expr) != 0)
{
error ("format string has invalid operand number");
return;
*no_add_attrs = true;
return NULL_TREE;
}
format_num = TREE_INT_CST_LOW (format_num_expr);
@ -151,7 +158,8 @@ decl_handle_format_attribute (decl, args)
if (first_arg_num != 0 && first_arg_num <= format_num)
{
error ("format string arg follows the args to be formatted");
return;
*no_add_attrs = true;
return NULL_TREE;
}
/* If a parameter list is specified, verify that the format_num
@ -170,7 +178,8 @@ decl_handle_format_attribute (decl, args)
!= char_type_node))
{
error ("format string arg not a string type");
return;
*no_add_attrs = true;
return NULL_TREE;
}
else if (first_arg_num != 0)
@ -183,7 +192,8 @@ decl_handle_format_attribute (decl, args)
if (arg_num != first_arg_num)
{
error ("args to be formatted is not '...'");
return;
*no_add_attrs = true;
return NULL_TREE;
}
}
}
@ -191,22 +201,27 @@ decl_handle_format_attribute (decl, args)
if (format_type == strftime_format_type && first_arg_num != 0)
{
error ("strftime formats cannot format arguments");
return;
*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 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;
/* 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;
@ -217,7 +232,8 @@ decl_handle_format_arg_attribute (decl, args)
{
error_with_decl (decl,
"argument format specified for non-function `%s'");
return;
*no_add_attrs = true;
return NULL_TREE;
}
/* Strip any conversions from the first arg number and verify it
@ -231,7 +247,8 @@ decl_handle_format_arg_attribute (decl, args)
|| TREE_INT_CST_HIGH (format_num_expr) != 0)
{
error ("format string has invalid operand number");
return;
*no_add_attrs = true;
return NULL_TREE;
}
format_num = TREE_INT_CST_LOW (format_num_expr);
@ -252,7 +269,8 @@ decl_handle_format_arg_attribute (decl, args)
!= char_type_node))
{
error ("format string arg not a string type");
return;
*no_add_attrs = true;
return NULL_TREE;
}
}
@ -261,11 +279,13 @@ decl_handle_format_arg_attribute (decl, args)
!= char_type_node))
{
error ("function does not return string type");
return;
*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

View File

@ -173,7 +173,7 @@ end ifc
%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> maybe_type_quals_attrs typespec_nonattr typespec_attr
%type <ttype> typespec_reserved_nonattr typespec_reserved_attr
%type <ttype> typespec_nonreserved_nonattr
@ -182,7 +182,6 @@ end ifc
%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
@ -847,29 +846,11 @@ setspecs: /* empty */
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
maybe_attribute
{ all_prefix_attributes = chainon ($1, prefix_attributes); }
;
decl:
@ -1347,18 +1328,12 @@ declspecs:
| 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:
/* A (possibly empty) sequence of type qualifiers and attributes. */
maybe_type_quals_attrs:
/* 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; }
{ $$ = $1; }
;
/* A type specifier (but not a type qualifier).
@ -1669,8 +1644,8 @@ declarator:
/* A declarator that is allowed only after an explicit typespec. */
after_type_declarator:
'(' maybe_setattrs after_type_declarator ')'
{ $$ = $3; }
'(' 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 '.'
@ -1678,7 +1653,7 @@ after_type_declarator:
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
| '*' maybe_type_quals_attrs after_type_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
| TYPENAME
ifobjc
@ -1717,12 +1692,12 @@ parm_declarator_nostarttypename:
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
| '*' maybe_type_quals_attrs parm_declarator_starttypename %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
| '*' maybe_type_quals_setattrs parm_declarator_nostarttypename %prec UNARY
| '*' maybe_type_quals_attrs parm_declarator_nostarttypename %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
| '(' maybe_setattrs parm_declarator_nostarttypename ')'
{ $$ = $3; }
| '(' maybe_attribute parm_declarator_nostarttypename ')'
{ $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
;
/* A declarator allowed whether or not there has been
@ -1734,9 +1709,9 @@ notype_declarator:
/* | 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
| '(' 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); }
@ -1991,20 +1966,20 @@ absdcl1: /* a nonempty absolute declarator */
absdcl1_noea:
direct_absdcl1
| '*' maybe_type_quals_setattrs absdcl1_noea
| '*' maybe_type_quals_attrs absdcl1_noea
{ $$ = make_pointer_declarator ($2, $3); }
;
absdcl1_ea:
'*' maybe_type_quals_setattrs
'*' maybe_type_quals_attrs
{ $$ = make_pointer_declarator ($2, NULL_TREE); }
| '*' maybe_type_quals_setattrs absdcl1_ea
| '*' maybe_type_quals_attrs absdcl1_ea
{ $$ = make_pointer_declarator ($2, $3); }
;
direct_absdcl1:
'(' maybe_setattrs absdcl1 ')'
{ $$ = $3; }
'(' 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
@ -3904,15 +3879,21 @@ yyprint (file, yychar, yyl)
/* 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.
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
and whose type is the modifier list. */
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, target)
tree type_quals, target;
make_pointer_declarator (type_quals_attrs, target)
tree type_quals_attrs, target;
{
return build1 (INDIRECT_REF, type_quals, 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);
}

View File

@ -181,13 +181,13 @@ static int unicosmk_need_dex PARAMS ((rtx));
/* Initialize the GCC target structure. */
#if TARGET_ABI_OPEN_VMS
static int vms_valid_decl_attribute_p PARAMS ((tree, tree, tree, tree));
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_VALID_DECL_ATTRIBUTE
# define TARGET_VALID_DECL_ATTRIBUTE vms_valid_decl_attribute_p
# 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
@ -5732,17 +5732,12 @@ alpha_using_fp ()
#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;
const struct attribute_spec vms_attribute_table[] =
{
if (is_attribute_p ("overlaid", identifier))
return (args == NULL_TREE);
return 0;
}
/* { 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
@ -7895,8 +7890,8 @@ vms_section_type_flags (decl, name, reloc)
{
unsigned int flags = default_section_type_flags (decl, name, reloc);
if (decl && DECL_MACHINE_ATTRIBUTES (decl)
&& lookup_attribute ("overlaid", DECL_MACHINE_ATTRIBUTES (decl)))
if (decl && DECL_ATTRIBUTES (decl)
&& lookup_attribute ("overlaid", DECL_ATTRIBUTES (decl)))
flags |= SECTION_VMS_OVERLAY;
return flags;

View File

@ -87,7 +87,8 @@ static int current_insn_set_cc_p;
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));
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));
@ -96,8 +97,8 @@ static void arc_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
#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
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE arc_attribute_table
struct gcc_target targetm = TARGET_INITIALIZER;
@ -326,26 +327,40 @@ arc_init_reg_tables ()
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;
const struct attribute_spec arc_attribute_table[] =
{
if (identifier == get_identifier ("__interrupt__")
&& list_length (args) == 1
&& TREE_CODE (TREE_VALUE (args)) == STRING_CST)
{
tree value = TREE_VALUE (args);
/* { 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 }
};
if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
|| !strcmp (TREE_STRING_POINTER (value), "ilink2"))
return 1;
/* 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;
}
return 0;
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;
}
@ -956,7 +971,7 @@ arc_compute_function_type (decl)
fn_type = ARC_FUNCTION_NORMAL;
/* Now see if this is an interrupt handler. */
for (a = DECL_MACHINE_ATTRIBUTES (current_function_decl);
for (a = DECL_ATTRIBUTES (current_function_decl);
a;
a = TREE_CHAIN (a))
{

View File

@ -103,10 +103,9 @@ static int current_file_function_operand PARAMS ((rtx));
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 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 *,
@ -130,16 +129,8 @@ static int arm_adjust_cost PARAMS ((rtx, rtx, rtx, int));
#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_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE arm_attribute_table
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue
@ -845,7 +836,7 @@ arm_compute_func_type ()
if (current_function_needs_context)
type |= ARM_FT_NESTED;
attr = DECL_MACHINE_ATTRIBUTES (current_function_decl);
attr = DECL_ATTRIBUTES (current_function_decl);
a = lookup_attribute ("naked", attr);
if (a != NULL_TREE)
@ -1909,39 +1900,120 @@ arm_pr_long_calls_off (pfile)
}
/* 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;
/* Table of machine attributes. */
const struct attribute_spec arm_attribute_table[] =
{
if ( TREE_CODE (type) != FUNCTION_TYPE
&& TREE_CODE (type) != METHOD_TYPE
&& TREE_CODE (type) != FIELD_DECL
&& TREE_CODE (type) != TYPE_DECL)
return 0;
/* { 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. */
if (is_attribute_p ("long_call", identifier))
return (args == NULL_TREE);
{ "long_call", 0, 0, false, true, true, NULL },
/* 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);
{ "short_call", 0, 0, false, true, true, NULL },
/* 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);
{ "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
return 0;
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
@ -4132,85 +4204,6 @@ multi_register_push (op, mode)
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,
@ -9742,7 +9735,7 @@ is_called_in_ARM_mode (func)
return TRUE;
#ifdef ARM_PE
return lookup_attribute ("interfacearm", DECL_MACHINE_ATTRIBUTES (func)) != NULL_TREE;
return lookup_attribute ("interfacearm", DECL_ATTRIBUTES (func)) != NULL_TREE;
#else
return FALSE;
#endif

View File

@ -1,5 +1,5 @@
/* Routines for GCC for ARM/pe.
Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 2000, 2001 Free Software Foundation, Inc.
Contributed by Doug Evans (dje@cygnus.com).
This file is part of GNU CC.
@ -45,7 +45,7 @@ arm_dllexport_p (decl)
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
exp = lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl));
exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
if (exp)
return 1;
@ -67,7 +67,7 @@ arm_dllimport_p (decl)
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl));
imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
if (imp)
return 1;

View File

@ -58,8 +58,9 @@ static int compare_sign_p PARAMS ((rtx insn));
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 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));
@ -177,11 +178,8 @@ int avr_case_values_threshold = 30000;
#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
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE avr_attribute_table
struct gcc_target targetm = TARGET_INITIALIZER;
@ -310,7 +308,7 @@ avr_naked_function_p (func)
if (TREE_CODE (func) != FUNCTION_DECL)
abort ();
a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
@ -326,7 +324,7 @@ interrupt_function_p (func)
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));
a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
@ -342,7 +340,7 @@ signal_function_p (func)
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
a = lookup_attribute ("signal", DECL_MACHINE_ATTRIBUTES (func));
a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
@ -4665,54 +4663,76 @@ class_likely_spilled_p (c)
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:
/* 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. */
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;
Only `progmem' attribute valid for type. */
const struct attribute_spec avr_attribute_table[] =
{
if (is_attribute_p ("interrupt", attr)
|| is_attribute_p ("signal", attr)
|| is_attribute_p ("naked", attr))
return TREE_CODE (decl) == FUNCTION_DECL;
/* { 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 }
};
if (is_attribute_p ("progmem", attr)
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
/* 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 (DECL_INITIAL (decl) == NULL_TREE && !DECL_EXTERNAL (decl))
if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
{
warning ("Only initialized variables can be placed into "
"program memory area.");
return 0;
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 1;
}
return 0;
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. */
@ -4727,7 +4747,7 @@ avr_progmem_p (decl)
return 0;
if (NULL_TREE
!= lookup_attribute ("progmem", DECL_MACHINE_ATTRIBUTES (decl)))
!= lookup_attribute ("progmem", DECL_ATTRIBUTES (decl)))
return 1;
a=decl;

View File

@ -1110,7 +1110,7 @@ enum reg_class {
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
From this you can obtain the DECL_ATTRIBUTES of the
function.
FUNTYPE is a C variable whose value is a tree node that describes

View File

@ -191,14 +191,15 @@ static int c4x_parse_pragma PARAMS ((const char *, tree *, tree *));
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 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_VALID_TYPE_ATTRIBUTE
#define TARGET_VALID_TYPE_ATTRIBUTE c4x_valid_type_attribute_p
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE c4x_attribute_table
#undef TARGET_INSERT_ATTRIBUTES
#define TARGET_INSERT_ATTRIBUTES c4x_insert_attributes
@ -4761,31 +4762,36 @@ c4x_insert_attributes (decl, attributes)
}
}
/* 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;
/* Table of valid machine attributes. */
const struct attribute_spec c4x_attribute_table[] =
{
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;
/* { 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;
}

View File

@ -2272,7 +2272,7 @@ typedef struct d30v_stack {
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.
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

View File

@ -1,7 +1,7 @@
/*{{{ Comment. */
/* Definitions of FR30 target.
Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Cygnus Solutions.
This file is part of GNU CC.
@ -824,7 +824,7 @@ enum reg_class
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.
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

View File

@ -53,7 +53,10 @@ static unsigned int compute_saved_regs PARAMS ((void));
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));
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));
@ -98,8 +101,8 @@ static const char *const h8_mov_ops[2] = { "mov.w", "mov.l" };
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_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE h8300_attribute_table
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE h8300_output_function_prologue
@ -3102,7 +3105,7 @@ h8300_interrupt_function_p (func)
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
a = lookup_attribute ("interrupt_handler", DECL_MACHINE_ATTRIBUTES (func));
a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
@ -3118,7 +3121,7 @@ h8300_os_task_function_p (func)
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
a = lookup_attribute ("OS_Task", DECL_MACHINE_ATTRIBUTES (func));
a = lookup_attribute ("OS_Task", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
@ -3134,7 +3137,7 @@ h8300_monitor_function_p (func)
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
a = lookup_attribute ("monitor", DECL_MACHINE_ATTRIBUTES (func));
a = lookup_attribute ("monitor", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
@ -3150,7 +3153,7 @@ h8300_funcvec_function_p (func)
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
a = lookup_attribute ("function_vector", DECL_MACHINE_ATTRIBUTES (func));
a = lookup_attribute ("function_vector", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
@ -3166,7 +3169,7 @@ h8300_eightbit_data_p (decl)
if (TREE_CODE (decl) != VAR_DECL)
return 0;
a = lookup_attribute ("eightbit_data", DECL_MACHINE_ATTRIBUTES (decl));
a = lookup_attribute ("eightbit_data", DECL_ATTRIBUTES (decl));
return a != NULL_TREE;
}
@ -3182,15 +3185,11 @@ h8300_tiny_data_p (decl)
if (TREE_CODE (decl) != VAR_DECL)
return 0;
a = lookup_attribute ("tiny_data", DECL_MACHINE_ATTRIBUTES (decl));
a = lookup_attribute ("tiny_data", DECL_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:
/* Supported attributes:
interrupt_handler: output a prologue and epilogue suitable for an
interrupt handler.
@ -3204,47 +3203,99 @@ h8300_tiny_data_p (decl)
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;
const struct attribute_spec h8300_attribute_table[] =
{
if (args != NULL_TREE)
return 0;
/* { 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 }
};
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)))
/* 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.");
return 0;
*no_add_attrs = true;
}
DECL_SECTION_NAME (decl) = build_string (7, ".eight");
return 1;
else
DECL_SECTION_NAME (decl) = build_string (7, ".eight");
}
else
{
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
if (is_attribute_p ("tiny_data", attr)
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
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.");
return 0;
*no_add_attrs = true;
}
DECL_SECTION_NAME (decl) = build_string (6, ".tiny");
return 1;
else
DECL_SECTION_NAME (decl) = build_string (6, ".tiny");
}
else
{
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
return 0;
return NULL_TREE;
}
void

View File

@ -191,7 +191,7 @@ union tree_node;
It's also used to handle dllimport override semantics. */
#if 0
#define REDO_SECTION_INFO_P(DECL) \
((DECL_MACHINE_ATTRIBUTES (DECL) != NULL_TREE) \
((DECL_ATTRIBUTES (DECL) != NULL_TREE) \
|| (TREE_CODE (DECL) == VAR_DECL && DECL_VIRTUAL_P (DECL)))
#else
#define REDO_SECTION_INFO_P(DECL) 1

View File

@ -173,9 +173,9 @@ extern int ix86_return_pops_args PARAMS ((tree, tree, int));
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 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));

View File

@ -657,6 +657,9 @@ static int ix86_fp_comparison_cost PARAMS ((enum rtx_code code));
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));
@ -667,15 +670,11 @@ static void sco_asm_out_constructor PARAMS ((rtx, int));
#endif
/* Initialize the GCC target structure. */
#undef TARGET_VALID_TYPE_ATTRIBUTE
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE ix86_attribute_table
#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
@ -977,56 +976,94 @@ optimization_options (level, size)
#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;
/* Table of valid machine attributes. */
const struct attribute_spec ix86_attribute_table[] =
{
if (TREE_CODE (type) != FUNCTION_TYPE
&& TREE_CODE (type) != METHOD_TYPE
&& TREE_CODE (type) != FIELD_DECL
&& TREE_CODE (type) != TYPE_DECL)
return 0;
/* { 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. */
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);
{ "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. */
if (is_attribute_p ("regparm", identifier))
{ "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;
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;
{
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 0;
return NULL_TREE;
}
#if defined (OSF_OS) || defined (TARGET_OSF1ELF)

View File

@ -1,6 +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.
Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@ -49,51 +49,54 @@ int i386_pe_dllimport_p PARAMS ((tree));
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;
/* 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;
{
if (args == NULL_TREE)
/* These attributes may apply to structure and union types being created,
but otherwise should pass to the declaration involved. */
if (!DECL_P (*node))
{
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;
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 0;
return NULL_TREE;
}
/* 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;
/* 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 (args == NULL_TREE
&& (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
if (TREE_CODE (*node) != VAR_DECL)
{
if (is_attribute_p ("dllexport", attr))
return 1;
if (is_attribute_p ("dllimport", attr))
return 1;
warning ("`%s' attribute only applies to variables",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
return ix86_valid_type_attribute_p (type, attributes, attr, args);
return NULL_TREE;
}
/* Return the type that we should use to determine if DECL is
@ -132,7 +135,7 @@ i386_pe_dllexport_p (decl)
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
exp = lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl));
exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
if (exp)
return 1;
@ -163,7 +166,7 @@ i386_pe_dllimport_p (decl)
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl));
imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
if (imp)
return 1;
@ -499,7 +502,7 @@ i386_pe_section_type_flags (decl, name, reloc)
flags = SECTION_WRITE;
if (decl && TREE_CODE (decl) == VAR_DECL
&& lookup_attribute ("shared", DECL_MACHINE_ATTRIBUTES (decl)))
&& lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
flags |= SECTION_PE_SHARED;
}

View File

@ -138,7 +138,7 @@ static rtx ia64_expand_compare_and_swap PARAMS ((enum machine_mode, int,
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));
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 *));
@ -156,8 +156,8 @@ static rtx ia64_cycle_display PARAMS ((int, rtx));
/* Initialize the GCC target structure. */
#undef TARGET_VALID_TYPE_ATTRIBUTE
#define TARGET_VALID_TYPE_ATTRIBUTE ia64_valid_type_attribute
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE ia64_attribute_table
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS ia64_init_builtins
@ -6755,29 +6755,13 @@ ia64_epilogue_uses (regno)
}
}
/* 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;
/* Table of valid machine attributes. */
const struct attribute_spec ia64_attribute_table[] =
{
/* 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;
}
/* { 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.

View File

@ -62,8 +62,8 @@ static int m32r_sched_odd_word_p;
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));
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));
@ -76,8 +76,8 @@ static int m32r_issue_rate PARAMS ((void));
/* Initialize the GCC target structure. */
#undef TARGET_VALID_DECL_ATTRIBUTE
#define TARGET_VALID_DECL_ATTRIBUTE m32r_valid_decl_attribute
#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
@ -250,10 +250,6 @@ init_reg_tables ()
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;
@ -264,12 +260,8 @@ static tree large_ident2;
static void
init_idents PARAMS ((void))
{
if (interrupt_ident1 == 0)
if (small_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");
@ -279,34 +271,43 @@ init_idents PARAMS ((void))
}
}
/* 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;
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 ((identifier == interrupt_ident1
|| identifier == interrupt_ident2)
&& list_length (args) == 0)
return 1;
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;
}
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;
return NULL_TREE;
}
/* A C statement or statements to switch to the appropriate
@ -370,7 +371,7 @@ m32r_encode_section_info (decl)
{
case VAR_DECL :
case FUNCTION_DECL :
model = lookup_attribute ("model", DECL_MACHINE_ATTRIBUTES (decl));
model = lookup_attribute ("model", DECL_ATTRIBUTES (decl));
break;
case STRING_CST :
case CONSTRUCTOR :
@ -1747,7 +1748,7 @@ m32r_compute_function_type (decl)
return fn_type;
/* Compute function type. */
fn_type = (lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (current_function_decl)) != NULL_TREE
fn_type = (lookup_attribute ("interrupt", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE
? M32R_FUNCTION_INTERRUPT
: M32R_FUNCTION_NORMAL);

View File

@ -66,8 +66,8 @@ static rtx m68hc11_expand_compare PARAMS((enum rtx_code, rtx, rtx));
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));
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));
@ -209,8 +209,8 @@ const char *m68hc11_soft_reg_count;
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_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE m68hc11_attribute_table
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue
@ -1130,30 +1130,34 @@ m68hc11_initialize_trampoline (tramp, fnaddr, cxt)
/* 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;
const struct attribute_spec m68hc11_attribute_table[] =
{
if (TREE_CODE (type) != FUNCTION_TYPE
&& TREE_CODE (type) != FIELD_DECL && TREE_CODE (type) != TYPE_DECL)
return 0;
/* { 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 }
};
if (TREE_CODE (type) == FUNCTION_TYPE)
/* 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)
{
if (is_attribute_p ("interrupt", identifier))
return (args == NULL_TREE);
if (is_attribute_p ("trap", identifier))
return (args == NULL_TREE);
warning ("`%s' attribute only applies to functions",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
return 0;
return NULL_TREE;
}
/* Define this macro if references to a symbol must be treated

View File

@ -130,8 +130,8 @@ static void mcore_mark_dllexport PARAMS ((tree));
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));
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));
@ -141,8 +141,8 @@ static void mcore_asm_named_section PARAMS ((const char *,
#define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
#endif
#undef TARGET_VALID_DECL_ATTRIBUTE
#define TARGET_VALID_DECL_ATTRIBUTE mcore_valid_decl_attribute
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE mcore_attribute_table
struct gcc_target targetm = TARGET_INITIALIZER;
@ -3387,7 +3387,7 @@ mcore_dllexport_p (decl)
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
return lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl)) != 0;
return lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)) != 0;
}
static int
@ -3398,7 +3398,7 @@ mcore_dllimport_p (decl)
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
return lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl)) != 0;
return lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)) != 0;
}
/* Cover function to implement ENCODE_SECTION_INFO. */
@ -3449,24 +3449,27 @@ mcore_encode_section_info (decl)
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;
const struct attribute_spec mcore_attribute_table[] =
{
if (args != NULL_TREE)
return 0;
/* { 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 }
};
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)
/* 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
@ -3483,11 +3486,15 @@ mcore_valid_decl_attribute (decl, attributes, attr, args)
}
else if (saved_warn_return_type_count)
saved_warn_return_type_count = 2;
return 1;
}
else
{
warning ("`%s' attribute only applies to functions",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
return 0;
return NULL_TREE;
}
/* Cover function for UNIQUE_SECTION. */
@ -3530,7 +3537,7 @@ mcore_unique_section (decl, reloc)
int
mcore_naked_function_p ()
{
return lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (current_function_decl)) != NULL_TREE;
return lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
}
static void

View File

@ -37,6 +37,7 @@ Boston, MA 02111-1307, USA. */
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
#include "toplev.h"
#ifdef OSF_OS
int ns32k_num_files = 0;
@ -64,13 +65,14 @@ static const char *const ns32k_out_reg_names[] = OUTPUT_REGISTER_NAMES;
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 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_VALID_TYPE_ATTRIBUTE
#define TARGET_VALID_TYPE_ATTRIBUTE ns32k_valid_type_attribute_p
#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
@ -1008,32 +1010,39 @@ symbolic_reference_mentioned_p (op)
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. */
/* Table of machine-specific attributes. */
static int
ns32k_valid_type_attribute_p (type, attributes, identifier, args)
tree type;
tree attributes ATTRIBUTE_UNUSED;
tree identifier;
tree args;
const struct attribute_spec ns32k_attribute_table[] =
{
if (TREE_CODE (type) != FUNCTION_TYPE
&& TREE_CODE (type) != FIELD_DECL
&& TREE_CODE (type) != TYPE_DECL)
return 0;
/* { 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. */
if (is_attribute_p ("stdcall", identifier))
return (args == NULL_TREE);
{ "stdcall", 0, 0, false, true, true, ns32k_handle_fntype_attribute },
/* Cdecl attribute says the callee is a normal C declaration */
if (is_attribute_p ("cdecl", identifier))
return (args == NULL_TREE);
{ "cdecl", 0, 0, false, true, true, ns32k_handle_fntype_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
return 0;
/* 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;
}

View File

@ -127,7 +127,8 @@ static int constant_pool_expr_1 PARAMS ((rtx, int *, int *));
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 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,
@ -184,8 +185,8 @@ static char alt_reg_names[][8] =
#endif
/* Initialize the GCC target structure. */
#undef TARGET_VALID_TYPE_ATTRIBUTE
#define TARGET_VALID_TYPE_ATTRIBUTE rs6000_valid_type_attribute_p
#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
@ -8123,28 +8124,34 @@ rs6000_initialize_trampoline (addr, fnaddr, cxt)
}
/* 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;
/* Table of valid machine attributes. */
const struct attribute_spec rs6000_attribute_table[] =
{
if (TREE_CODE (type) != FUNCTION_TYPE
&& TREE_CODE (type) != FIELD_DECL
&& TREE_CODE (type) != TYPE_DECL)
return 0;
/* { 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 }
};
/* 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);
/* 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 0;
return NULL_TREE;
}
/* Return a reference suitable for calling a function with the

View File

@ -154,15 +154,18 @@ static int calc_live_regs PARAMS ((int *, int *));
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));
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_VALID_DECL_ATTRIBUTE
#define TARGET_VALID_DECL_ATTRIBUTE sh_valid_decl_attribute
#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
@ -269,7 +272,7 @@ print_operand (stream, x, code)
if ((lookup_attribute
("interrupt_handler",
DECL_MACHINE_ATTRIBUTES (current_function_decl)))
DECL_ATTRIBUTES (current_function_decl)))
!= NULL_TREE)
interrupt_handler = 1;
else
@ -3964,7 +3967,7 @@ calc_live_regs (count_ptr, live_regs_mask2)
if ((lookup_attribute
("interrupt_handler",
DECL_MACHINE_ATTRIBUTES (current_function_decl)))
DECL_ATTRIBUTES (current_function_decl)))
!= NULL_TREE)
interrupt_handler = 1;
else
@ -4058,7 +4061,7 @@ sh_expand_prologue ()
current_function_interrupt
= lookup_attribute ("interrupt_handler",
DECL_MACHINE_ATTRIBUTES (current_function_decl))
DECL_ATTRIBUTES (current_function_decl))
!= NULL_TREE;
/* We have pretend args if we had an object sent partially in registers
@ -4656,11 +4659,7 @@ sh_insert_attributes (node, attributes)
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:
/* Supported attributes:
interrupt_handler -- specifies this function is an interrupt handler.
@ -4670,59 +4669,110 @@ sh_insert_attributes (node, attributes)
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;
const struct attribute_spec sh_attribute_table[] =
{
if (TREE_CODE (decl) != FUNCTION_DECL)
return 0;
/* { 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 }
};
if (is_attribute_p ("interrupt_handler", attr))
/* 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)
{
return 1;
warning ("`%s' attribute only applies to functions",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
if (is_attribute_p ("sp_switch", attr))
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. */
if (!pragma_interrupt)
return 0;
/* sp_switch must have an argument. */
if (!args || TREE_CODE (args) != TREE_LIST)
return 0;
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. */
if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
return 0;
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 1;
}
if (is_attribute_p ("trap_exit", attr))
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. */
if (!pragma_interrupt)
return 0;
/* trap_exit must have an argument. */
if (!args || TREE_CODE (args) != TREE_LIST)
return 0;
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. */
if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
return 0;
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 1;
}
return 0;
return NULL_TREE;
}

View File

@ -1909,30 +1909,34 @@ stormy16_interrupt_function_p ()
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;
#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[] =
{
if (TREE_CODE (type) != FUNCTION_TYPE)
return 0;
if (is_attribute_p ("interrupt", identifier))
return 1;
/* { 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 }
};
return 0;
/* 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;

View File

@ -1975,7 +1975,7 @@ enum reg_class
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.
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

View File

@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA. */
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));
static void mark_current_function_as_interrupt PARAMS ((void));
/* Push a data area onto the stack. */
@ -85,7 +85,7 @@ pop_data_area (data_area)
/* Set the machine specific 'interrupt' attribute on the current function. */
static int
static void
mark_current_function_as_interrupt ()
{
tree name;
@ -104,8 +104,8 @@ mark_current_function_as_interrupt ()
return 0;
}
return valid_machine_attribute
(name, NULL_TREE, current_function_decl, NULL_TREE);
decl_attributes (&current_function_decl,
tree_cons (name, NULL_TREE, NULL_TREE), 0);
}

View File

@ -53,7 +53,9 @@ static int const_costs_int PARAMS ((HOST_WIDE_INT, int));
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));
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. */
@ -84,8 +86,8 @@ static int v850_interrupt_cache_p = FALSE;
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_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE v850_attribute_table
#undef TARGET_INSERT_ATTRIBUTES
#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes
@ -1978,13 +1980,13 @@ v850_data_area
v850_get_data_area (decl)
tree decl;
{
if (lookup_attribute ("sda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
if (lookup_attribute ("sda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_SDA;
if (lookup_attribute ("tda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
if (lookup_attribute ("tda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_TDA;
if (lookup_attribute ("zda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
if (lookup_attribute ("zda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_ZDA;
return DATA_AREA_NORMAL;
@ -2008,62 +2010,92 @@ v850_set_data_area (decl, data_area)
return;
}
DECL_MACHINE_ATTRIBUTES (decl) = tree_cons
(name, NULL, DECL_MACHINE_ATTRIBUTES (decl));
DECL_ATTRIBUTES (decl) = tree_cons
(name, NULL, DECL_ATTRIBUTES (decl));
}
/* Return nonzero if ATTR is a valid attribute for DECL.
ARGS are the arguments supplied with ATTR. */
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 }
};
static int
v850_valid_decl_attribute (decl, unused, attr, args)
tree decl;
tree unused ATTRIBUTE_UNUSED;
tree attr;
tree args;
/* 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;
if (args != NULL_TREE)
return 0;
if (is_attribute_p ("interrupt_handler", attr)
|| is_attribute_p ("interrupt", attr))
return TREE_CODE (decl) == FUNCTION_DECL;
tree decl = *node;
/* Implement data area attribute. */
if (is_attribute_p ("sda", attr))
if (is_attribute_p ("sda", name))
data_area = DATA_AREA_SDA;
else if (is_attribute_p ("tda", attr))
else if (is_attribute_p ("tda", name))
data_area = DATA_AREA_TDA;
else if (is_attribute_p ("zda", attr))
else if (is_attribute_p ("zda", name))
data_area = DATA_AREA_ZDA;
else
return 0;
abort ();
switch (TREE_CODE (decl))
{
case VAR_DECL:
if (current_function_decl != NULL_TREE)
error_with_decl (decl, "\
{
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, "\
{
error_with_decl (decl, "\
data area of '%s' conflicts with previous declaration");
return 1;
*no_add_attrs = true;
}
break;
default:
break;
}
return 0;
return NULL_TREE;
}
@ -2083,13 +2115,13 @@ v850_interrupt_function_p (func)
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
a = lookup_attribute ("interrupt_handler", DECL_MACHINE_ATTRIBUTES (func));
a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
if (a != NULL_TREE)
ret = 1;
else
{
a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));
a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
ret = a != NULL_TREE;
}

View File

@ -1,3 +1,43 @@
2001-09-21 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.
2001-09-15 Gabriel Dos Reis <gdr@merlin.codesourcery.com>
* Make-lang.in (cp/error.o): Depend on real.h

View File

@ -5293,7 +5293,7 @@ finish_struct (t, attributes)
as necessary. */
unreverse_member_declarations (t);
cplus_decl_attributes (&t, attributes, NULL_TREE, 0);
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. */

View File

@ -3734,7 +3734,7 @@ extern tree grokbitfield PARAMS ((tree, tree, tree));
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 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));
@ -4208,7 +4208,7 @@ extern tree walk_tree_without_duplicates PARAMS ((tree *,
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 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 *));

View File

@ -45,7 +45,7 @@ Boston, MA 02111-1307, USA. */
#include "tm_p.h"
#include "target.h"
extern int (*valid_lang_attribute) PARAMS ((tree, tree, tree, tree));
extern const struct attribute_spec *lang_attribute_table;
#ifndef BOOL_TYPE_SIZE
/* `bool' has size and alignment `1', on all platforms. */
@ -3438,7 +3438,7 @@ duplicate_decls (newdecl, olddecl)
/* 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)
DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
@ -3746,7 +3746,7 @@ duplicate_decls (newdecl, olddecl)
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
return 1;
}
@ -6493,7 +6493,7 @@ init_decl_processing ()
/* Show we use EH for cleanups. */
using_eh_for_cleanups ();
valid_lang_attribute = cp_valid_lang_attribute;
lang_attribute_table = cp_attribute_table;
/* Maintain consistency. Perhaps we should just complain if they
say -fwritable-strings? */
@ -6986,7 +6986,7 @@ shadow_tag (declspecs)
if (TYPE_FIELDS (t))
{
tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
NULL_TREE);
NULL);
finish_anon_union (decl);
}
}
@ -7002,7 +7002,7 @@ groktypename (typename)
return typename;
return grokdeclarator (TREE_VALUE (typename),
TREE_PURPOSE (typename),
TYPENAME, 0, NULL_TREE);
TYPENAME, 0, NULL);
}
/* Decode a declarator in an ordinary declaration or data definition.
@ -7031,7 +7031,6 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
tree context;
extern int have_extern_spec;
extern int used_extern_spec;
tree attrlist;
#if 0
/* See code below that used this. */
@ -7046,13 +7045,10 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
used_extern_spec = 1;
}
if (attributes || prefix_attributes)
attrlist = build_tree_list (attributes, prefix_attributes);
else
attrlist = NULL_TREE;
attributes = chainon (attributes, prefix_attributes);
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
attrlist);
&attributes);
if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
return NULL_TREE;
@ -7119,7 +7115,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
}
/* Set attributes here so if duplicate decl, will have proper attributes. */
cplus_decl_attributes (&decl, attributes, prefix_attributes, 0);
cplus_decl_attributes (&decl, attributes, 0);
if (context && COMPLETE_TYPE_P (complete_type (context)))
{
@ -8482,7 +8478,7 @@ start_handler_parms (declspecs, declarator)
if (declspecs)
{
decl = grokdeclarator (declarator, declspecs, CATCHPARM,
1, NULL_TREE);
1, NULL);
if (decl == NULL_TREE)
error ("invalid catch parameter");
}
@ -9425,8 +9421,9 @@ check_special_function_return_type (sfk, type, optype)
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.
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
@ -9464,7 +9461,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree declarator;
enum decl_context decl_context;
int initialized;
tree attrlist;
tree *attrlist;
{
RID_BIT_TYPE specbits;
int nclasses = 0;
@ -9487,7 +9484,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
int bitfield = 0;
#if 0
/* See the code below that used this. */
tree decl_machine_attr = NULL_TREE;
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. */
@ -9506,8 +9503,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree raises = NULL_TREE;
int template_count = 0;
tree in_namespace = NULL_TREE;
tree inner_attrs;
int ignore_attrs;
tree returned_attrs = NULL_TREE;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
@ -9598,24 +9594,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
cp_finish_decl so we can get the variable
initialized... */
tree attributes, prefix_attributes;
tree attributes;
*next = TREE_OPERAND (decl, 0);
init = CALL_DECLARATOR_PARMS (decl);
if (attrlist)
{
attributes = TREE_PURPOSE (attrlist);
prefix_attributes = TREE_VALUE (attrlist);
attributes = *attrlist;
}
else
{
attributes = NULL_TREE;
prefix_attributes = NULL_TREE;
}
decl = start_decl (declarator, declspecs, 1,
attributes, prefix_attributes);
attributes, NULL_TREE);
decl_type_access_control (decl);
if (decl)
{
@ -9953,7 +9947,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = TREE_TYPE (t);
#if 0
/* See the code below that used this. */
decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
decl_attr = DECL_ATTRIBUTES (id);
#endif
typedef_decl = t;
}
@ -10312,9 +10306,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
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)
{
@ -10363,28 +10354,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
/* 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;
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;
@ -10883,15 +10876,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
/* See the comment for the TREE_LIST case, above. */
if (inner_attrs)
if (returned_attrs)
{
if (! ignore_attrs)
decl_attributes (&type, inner_attrs, 0);
else if (attrlist)
TREE_VALUE (attrlist) = chainon (inner_attrs, TREE_VALUE (attrlist));
if (attrlist)
*attrlist = chainon (returned_attrs, *attrlist);
else
attrlist = build_tree_list (NULL_TREE, inner_attrs);
attrlist = &returned_attrs;
}
/* Now TYPE has the actual type. */
@ -11302,8 +11292,8 @@ friend declaration requires class-key, i.e. `friend %#T'",
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);
/* The decl and setting of decl_attr is also turned off. */
decl = build_decl_attribute_variant (decl, decl_attr);
#endif
/* [class.conv.ctor]
@ -11401,7 +11391,7 @@ friend declaration requires class-key, i.e. `friend %#T'",
}
t = do_friend (ctype, declarator, decl,
last_function_parms, attrlist, flags, quals,
last_function_parms, *attrlist, flags, quals,
funcdef_flag);
}
if (t && funcdef_flag)
@ -11838,7 +11828,7 @@ grokparms (first_parm)
break;
decl = grokdeclarator (TREE_VALUE (decl), TREE_PURPOSE (decl),
PARM, init != NULL_TREE, NULL_TREE);
PARM, init != NULL_TREE, NULL);
if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
@ -13269,7 +13259,7 @@ start_function (declspecs, declarator, attrs, flags)
}
else
{
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL_TREE);
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;
@ -13554,7 +13544,7 @@ start_function (declspecs, declarator, attrs, flags)
pushlevel (0);
current_binding_level->parm_flag = 1;
cplus_decl_attributes (&decl1, NULL_TREE, attrs, 0);
cplus_decl_attributes (&decl1, attrs, 0);
/* Promote the value to int before returning it. */
if (c_promoting_integer_type_p (restype))
@ -14056,7 +14046,7 @@ start_method (declspecs, declarator, attrlist)
tree declarator, declspecs, attrlist;
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
attrlist);
&attrlist);
/* Something too ugly to handle. */
if (fndecl == NULL_TREE)

View File

@ -31,7 +31,7 @@ enum decl_context
};
/* We need this in here to get the decl_context definition. */
extern tree grokdeclarator PARAMS ((tree, tree, enum decl_context, int, tree));
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. */

View File

@ -1531,7 +1531,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
&& TREE_CHAIN (init) == NULL_TREE)
init = NULL_TREE;
value = grokdeclarator (declarator, declspecs, FIELD, init != 0, attrlist);
value = grokdeclarator (declarator, declspecs, FIELD, init != 0, &attrlist);
if (! value || value == error_mark_node)
/* friend or constructor went bad. */
return value;
@ -1628,8 +1628,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
value = push_template_decl (value);
if (attrlist)
cplus_decl_attributes (&value, TREE_PURPOSE (attrlist),
TREE_VALUE (attrlist), 0);
cplus_decl_attributes (&value, attrlist, 0);
if (TREE_CODE (value) == VAR_DECL)
{
@ -1679,7 +1678,7 @@ grokbitfield (declarator, declspecs, width)
tree declarator, declspecs, width;
{
register tree value = grokdeclarator (declarator, declspecs, BITFIELD,
0, NULL_TREE);
0, NULL);
if (! value) return NULL_TREE; /* friends went bad. */
@ -1735,7 +1734,7 @@ tree
grokoptypename (declspecs, declarator)
tree declspecs, declarator;
{
tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE);
tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL);
return mangle_conv_op_name_for_type (t);
}
@ -1824,8 +1823,8 @@ grok_function_init (decl, init)
}
void
cplus_decl_attributes (decl, attributes, prefix_attributes, flags)
tree *decl, attributes, prefix_attributes;
cplus_decl_attributes (decl, attributes, flags)
tree *decl, attributes;
int flags;
{
if (*decl == NULL_TREE || *decl == void_type_node)
@ -1834,7 +1833,7 @@ cplus_decl_attributes (decl, attributes, prefix_attributes, flags)
if (TREE_CODE (*decl) == TEMPLATE_DECL)
decl = &DECL_TEMPLATE_RESULT (*decl);
decl_attributes (decl, chainon (attributes, prefix_attributes), flags);
decl_attributes (decl, attributes, flags);
if (TREE_CODE (*decl) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
@ -2371,17 +2370,9 @@ import_export_class (ctype)
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)))
if (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)))
else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
import_export = 1;
/* If we got -fno-implicit-templates, we import template classes that

View File

@ -309,7 +309,6 @@ do_friend (ctype, declarator, decl, parmdecls, attrlist,
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;
@ -435,19 +434,8 @@ do_friend (ctype, declarator, decl, parmdecls, attrlist,
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);
cplus_decl_attributes (&decl, attrlist, 0);
return decl;
}

View File

@ -164,7 +164,7 @@ parse_field (declarator, attributes, asmspec, init)
tree declarator, attributes, asmspec, init;
{
tree d = grokfield (declarator, current_declspecs, init, asmspec,
build_tree_list (attributes, prefix_attributes));
chainon (attributes, prefix_attributes));
decl_type_access_control (d);
return d;
}
@ -182,7 +182,7 @@ parse_bitfield (declarator, attributes, width)
tree declarator, attributes, width;
{
tree d = grokbitfield (declarator, current_declspecs, width);
cplus_decl_attributes (&d, attributes, prefix_attributes, 0);
cplus_decl_attributes (&d, chainon (attributes, prefix_attributes), 0);
decl_type_access_control (d);
return d;
}
@ -2639,11 +2639,9 @@ component_decl_1:
$$ = NULL_TREE;
}
| notype_declarator maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, NULL_TREE, $4, $2,
build_tree_list ($3, NULL_TREE)); }
{ $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
| constructor_declarator maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, NULL_TREE, $4, $2,
build_tree_list ($3, NULL_TREE)); }
{ $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
| ':' expr_no_commas
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
| error
@ -2661,10 +2659,9 @@ component_decl_1:
{ tree specs, attrs;
split_specs_attrs ($1.t, &specs, &attrs);
$$ = grokfield ($2, specs, $5, $3,
build_tree_list ($4, attrs)); }
chainon ($4, attrs)); }
| component_constructor_declarator maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, NULL_TREE, $4, $2,
build_tree_list ($3, NULL_TREE)); }
{ $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
| using_decl
{ $$ = do_class_using_decl ($1); }

View File

@ -1929,7 +1929,7 @@ process_template_parm (list, next)
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);
PARM, 0, NULL);
/* [temp.param]
@ -9356,7 +9356,7 @@ void
do_decl_instantiation (declspecs, declarator, storage)
tree declspecs, declarator, storage;
{
tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL_TREE);
tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL);
tree result = NULL_TREE;
int extern_p = 0;

View File

@ -50,6 +50,10 @@ static tree verify_stmt_tree_r PARAMS ((tree *, int *, void *));
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. */
@ -2182,108 +2186,145 @@ pod_type_p (t)
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;
/* Table of valid C++ attributes. */
const struct attribute_spec cp_attribute_table[] =
{
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;
}
/* { 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 }
};
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))
/* 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))
{
tree initp_expr = (attr_args ? TREE_VALUE (attr_args): NULL_TREE);
int pri;
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;
if (initp_expr)
STRIP_NOPS (initp_expr);
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");
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;
}
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;
}
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 `%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

View File

@ -1658,14 +1658,11 @@ to the same declaration or type, or @code{NULL_TREE} if there are no
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.
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_MACHINE_ATTRIBUTES (tree @var{decl})
@deftypefn {Tree Macro} tree DECL_ATTRIBUTES (tree @var{decl})
This macro returns the attributes on the declaration @var{decl}.
@end deftypefn

View File

@ -2449,6 +2449,14 @@ language. Some details may vary for C++ and Objective-C@. Because of
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},
@ -2520,9 +2528,8 @@ defined is not complete until after the attribute specifiers.
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
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
@ -2597,11 +2604,11 @@ ignored.
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
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 intended future
semantics which make this syntax more useful only. It will make the
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.
@ -2642,8 +2649,26 @@ char *__attribute__((aligned(8))) *f;
@noindent
specifies the type ``pointer to 8-byte-aligned pointer to @code{char}''.
Note again that this describes intended future semantics, not current
implementation.
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

View File

@ -48,6 +48,7 @@ through the macros defined in the @file{.h} file.
* 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
@ -70,8 +71,8 @@ macros for which the default definition is inappropriate. For example:
/* @r{Initialize the GCC target structure.} */
#undef TARGET_VALID_TYPE_ATTRIBUTE
#define TARGET_VALID_TYPE_ATTRIBUTE @var{machine}_valid_type_attribute_p
#undef TARGET_COMP_TYPE_ATTRIBUTES
#define TARGET_COMP_TYPE_ATTRIBUTES @var{machine}_comp_type_attributes
struct gcc_target targetm = TARGET_INITIALIZER;
@end smallexample
@ -2528,7 +2529,7 @@ This describes the stack layout and calling conventions.
* Caller Saves::
* Function Entry::
* Profiling::
* Inlining and Tail Calls::
* Tail Calls::
@end menu
@node Frame Layout
@ -3222,7 +3223,7 @@ after the function returns.
@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.
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
@ -4204,18 +4205,11 @@ profiling when the frame pointer is omitted.
@end table
@node Inlining and Tail Calls
@subsection Permitting inlining and tail calls
@cindex inlining
@node Tail Calls
@subsection Permitting tail calls
@cindex tail calls
@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
@ -8031,6 +8025,85 @@ Generate one or more insns to set @var{entity} to @var{mode}.
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
@ -8404,7 +8477,7 @@ other compilers for the same target. In general, we discourage
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.
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
@ -8484,74 +8557,7 @@ pack value of zero resets the behaviour to the default. Successive
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

View File

@ -453,7 +453,7 @@ ggc_mark_trees ()
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));
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));

View File

@ -42,6 +42,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "loop.h"
#include "params.h"
#include "ggc.h"
#include "target.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
@ -63,12 +64,6 @@ extern struct obstack *function_maybepermanent_obstack;
? (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. */
@ -82,6 +77,8 @@ typedef struct initial_value_struct {
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));
@ -130,6 +127,38 @@ get_label_from_map (map, i)
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
@ -250,9 +279,8 @@ function_cannot_inline_p (fndecl)
/* 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))
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;

View File

@ -1,5 +1,5 @@
/* Prints out tree in human readable form - GNU C-compiler
Copyright (C) 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
Copyright (C) 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This file is part of GCC.
@ -433,8 +433,8 @@ print_node (file, prefix, node, indent)
}
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, "attributes",
DECL_ATTRIBUTES (node), indent + 4);
print_node_brief (file, "abstract_origin",
DECL_ABSTRACT_ORIGIN (node), indent + 4);

View File

@ -107,11 +107,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/* 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_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
@ -129,11 +129,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_SCHED, \
TARGET_MERGE_DECL_ATTRIBUTES, \
TARGET_MERGE_TYPE_ATTRIBUTES, \
TARGET_VALID_DECL_ATTRIBUTE, \
TARGET_VALID_TYPE_ATTRIBUTE, \
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, \

View File

@ -121,17 +121,8 @@ struct gcc_target
/* 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));
/* 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
@ -144,6 +135,10 @@ struct gcc_target
/* 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));

View File

@ -1,3 +1,8 @@
2001-09-21 Joseph S. Myers <jsm28@cam.ac.uk>
Table-driven attributes.
* g++.dg/ext/attrib1.C: New test.
2001-09-20 DJ Delorie <dj@redhat.com>
* gcc.dg/20000926-1.c: Update expected warning messages.

View File

@ -0,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 *, ...);

View File

@ -2605,14 +2605,14 @@ build_expr_wfl (node, file, line, col)
return wfl;
}
/* Return a declaration like DDECL except that its DECL_MACHINE_ATTRIBUTE
/* Return a declaration like DDECL except that its DECL_ATTRIBUTES
is ATTRIBUTE. */
tree
build_decl_attribute_variant (ddecl, attribute)
tree ddecl, attribute;
{
DECL_MACHINE_ATTRIBUTES (ddecl) = attribute;
DECL_ATTRIBUTES (ddecl) = attribute;
return ddecl;
}
@ -2670,19 +2670,6 @@ build_type_attribute_variant (ttype, attribute)
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
@ -2710,116 +2697,20 @@ default_insert_attributes (decl, attr_ptr)
{
}
/* 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;
/* Default value of targetm.attribute_table that is empty. */
const struct attribute_spec default_target_attribute_table[] =
{
tree type_attrs;
{ NULL, 0, 0, false, false, false, NULL }
};
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;
/* 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,
@ -2873,7 +2764,9 @@ is_attribute_p (attr, ident)
/* 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 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)
@ -2915,19 +2808,29 @@ merge_attributes (a1, a2)
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;
}
{
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;
@ -2951,8 +2854,8 @@ tree
merge_decl_attributes (olddecl, newdecl)
tree olddecl, newdecl;
{
return merge_attributes (DECL_MACHINE_ATTRIBUTES (olddecl),
DECL_MACHINE_ATTRIBUTES (newdecl));
return merge_attributes (DECL_ATTRIBUTES (olddecl),
DECL_ATTRIBUTES (newdecl));
}
#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
@ -2974,8 +2877,8 @@ merge_dllimport_decl_attributes (old, new)
tree a;
int delete_dllimport_p;
old = DECL_MACHINE_ATTRIBUTES (old);
new = DECL_MACHINE_ATTRIBUTES (new);
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
@ -3345,8 +3248,15 @@ attribute_list_contained (l1, l2)
for (; t2 != 0; t2 = TREE_CHAIN (t2))
{
tree attr
= lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
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;

View File

@ -1,5 +1,5 @@
/* Front-end tree definitions for GNU compiler.
Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This file is part of GCC.
@ -1337,9 +1337,8 @@ struct tree_type
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 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)
@ -1754,7 +1753,7 @@ struct tree_decl
tree abstract_origin;
tree assembler_name;
tree section_name;
tree machine_attributes;
tree attributes;
rtx rtl; /* RTL representation for object. */
rtx live_range_rtl;
@ -2069,14 +2068,82 @@ extern tree make_tree PARAMS ((tree, rtx));
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_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 *));
extern bool default_function_attribute_inlinable_p PARAMS ((tree));
/* Split a list of declspecs and attributes into two. */