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:
parent
3007d592bf
commit
91d231cb91
54 changed files with 2642 additions and 1656 deletions
182
gcc/ChangeLog
182
gcc/ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
1381
gcc/c-common.c
1381
gcc/c-common.c
File diff suppressed because it is too large
Load diff
|
@ -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));
|
||||
|
|
51
gcc/c-decl.c
51
gcc/c-decl.c
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 (¤t_function_decl,
|
||||
tree_cons (name, NULL_TREE, NULL_TREE), 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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 *));
|
||||
|
|
108
gcc/cp/decl.c
108
gcc/cp/decl.c
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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); }
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
231
gcc/cp/tree.c
231
gcc/cp/tree.c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
170
gcc/doc/tm.texi
170
gcc/doc/tm.texi
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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, \
|
||||
|
|
17
gcc/target.h
17
gcc/target.h
|
@ -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));
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
10
gcc/testsuite/g++.dg/ext/attrib1.C
Normal file
10
gcc/testsuite/g++.dg/ext/attrib1.C
Normal 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 *, ...);
|
186
gcc/tree.c
186
gcc/tree.c
|
@ -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;
|
||||
|
|
79
gcc/tree.h
79
gcc/tree.h
|
@ -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. */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue