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
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>
|
Fri Sep 21 01:49:41 2001 J"orn Rennecke <amylaar@redhat.com>
|
||||||
|
|
||||||
* sh-protos.h (sh_pr_n_sets): Declare.
|
* 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 \
|
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) \
|
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) \
|
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) \
|
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 \
|
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)
|
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 tree fname_decl PARAMS ((unsigned, tree));
|
||||||
extern const char *fname_string PARAMS ((unsigned));
|
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 tree decl_attributes PARAMS ((tree *, tree, int));
|
||||||
extern void init_function_format_info PARAMS ((void));
|
extern void init_function_format_info PARAMS ((void));
|
||||||
extern void check_function_format PARAMS ((int *, tree, tree, tree));
|
extern void check_function_format PARAMS ((int *, tree, tree, tree));
|
||||||
extern void set_Wformat PARAMS ((int));
|
extern void set_Wformat PARAMS ((int));
|
||||||
extern void decl_handle_format_attribute PARAMS ((tree, tree));
|
extern tree handle_format_attribute PARAMS ((tree *, tree, tree,
|
||||||
extern void decl_handle_format_arg_attribute PARAMS ((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 void c_apply_type_quals_to_decl PARAMS ((int, tree));
|
||||||
extern tree c_sizeof PARAMS ((tree));
|
extern tree c_sizeof PARAMS ((tree));
|
||||||
extern tree c_alignof 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;
|
int errmsg = 0;
|
||||||
|
|
||||||
if (DECL_P (olddecl))
|
if (DECL_P (olddecl))
|
||||||
DECL_MACHINE_ATTRIBUTES (newdecl)
|
DECL_ATTRIBUTES (newdecl)
|
||||||
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
|
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
|
||||||
|
|
||||||
if (TREE_CODE (newtype) == ERROR_MARK
|
if (TREE_CODE (newtype) == ERROR_MARK
|
||||||
|
@ -2030,7 +2030,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
|
||||||
|
|
||||||
/* NEWDECL contains the merged attribute lists.
|
/* NEWDECL contains the merged attribute lists.
|
||||||
Update OLDDECL to be the same. */
|
Update OLDDECL to be the same. */
|
||||||
DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
|
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -3872,9 +3872,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||||
enum tree_code innermost_code = ERROR_MARK;
|
enum tree_code innermost_code = ERROR_MARK;
|
||||||
int bitfield = 0;
|
int bitfield = 0;
|
||||||
int size_varies = 0;
|
int size_varies = 0;
|
||||||
tree decl_machine_attr = NULL_TREE;
|
tree decl_attr = NULL_TREE;
|
||||||
tree array_ptr_quals = NULL_TREE;
|
tree array_ptr_quals = NULL_TREE;
|
||||||
int array_parm_static = 0;
|
int array_parm_static = 0;
|
||||||
|
tree returned_attrs = NULL_TREE;
|
||||||
|
|
||||||
if (decl_context == BITFIELD)
|
if (decl_context == BITFIELD)
|
||||||
bitfield = 1, decl_context = FIELD;
|
bitfield = 1, decl_context = FIELD;
|
||||||
|
@ -3898,6 +3899,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||||
decl = TREE_OPERAND (decl, 0);
|
decl = TREE_OPERAND (decl, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TREE_LIST:
|
||||||
|
decl = TREE_VALUE (decl);
|
||||||
|
break;
|
||||||
|
|
||||||
case IDENTIFIER_NODE:
|
case IDENTIFIER_NODE:
|
||||||
name = IDENTIFIER_POINTER (decl);
|
name = IDENTIFIER_POINTER (decl);
|
||||||
decl = 0;
|
decl = 0;
|
||||||
|
@ -3979,7 +3984,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||||
else if (TREE_CODE (id) == TYPE_DECL)
|
else if (TREE_CODE (id) == TYPE_DECL)
|
||||||
{
|
{
|
||||||
type = TREE_TYPE (id);
|
type = TREE_TYPE (id);
|
||||||
decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
|
decl_attr = DECL_ATTRIBUTES (id);
|
||||||
typedef_decl = id;
|
typedef_decl = id;
|
||||||
}
|
}
|
||||||
/* Built-in types come as identifiers. */
|
/* 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 ...[..]),
|
/* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
|
||||||
an INDIRECT_REF (for *...),
|
an INDIRECT_REF (for *...),
|
||||||
a CALL_EXPR (for ...(...)),
|
a CALL_EXPR (for ...(...)),
|
||||||
|
a TREE_LIST (for nested attributes),
|
||||||
an identifier (for the name being declared)
|
an identifier (for the name being declared)
|
||||||
or a null pointer (for the place in an absolute declarator
|
or a null pointer (for the place in an absolute declarator
|
||||||
where the name was omitted).
|
where the name was omitted).
|
||||||
|
@ -4313,7 +4319,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||||
array_parm_static = 0;
|
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 itype = NULL_TREE;
|
||||||
register tree size = TREE_OPERAND (declarator, 1);
|
register tree size = TREE_OPERAND (declarator, 1);
|
||||||
|
@ -4657,6 +4686,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||||
if ((specbits & (1 << (int) RID_SIGNED))
|
if ((specbits & (1 << (int) RID_SIGNED))
|
||||||
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
|
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
|
||||||
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
|
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
|
||||||
|
decl_attributes (&decl, returned_attrs, 0);
|
||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4687,6 +4717,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||||
pedwarn ("ISO C forbids const or volatile function types");
|
pedwarn ("ISO C forbids const or volatile function types");
|
||||||
if (type_quals)
|
if (type_quals)
|
||||||
type = c_build_qualified_type (type, type_quals);
|
type = c_build_qualified_type (type, type_quals);
|
||||||
|
decl_attributes (&type, returned_attrs, 0);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4711,7 +4742,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||||
or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */
|
or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */
|
||||||
|
|
||||||
{
|
{
|
||||||
register tree decl;
|
tree decl;
|
||||||
|
|
||||||
if (decl_context == PARM)
|
if (decl_context == PARM)
|
||||||
{
|
{
|
||||||
|
@ -4860,7 +4891,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||||
pedwarn ("invalid storage class for function `%s'", name);
|
pedwarn ("invalid storage class for function `%s'", name);
|
||||||
|
|
||||||
decl = build_decl (FUNCTION_DECL, declarator, type);
|
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))
|
if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
|
||||||
pedwarn ("ISO C forbids qualified function types");
|
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)))
|
if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
|
||||||
mark_addressable (decl);
|
mark_addressable (decl);
|
||||||
|
|
||||||
|
decl_attributes (&decl, returned_attrs, 0);
|
||||||
|
|
||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5341,7 +5374,7 @@ finish_struct (t, fieldlist, attributes)
|
||||||
|
|
||||||
TYPE_SIZE (t) = 0;
|
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. */
|
/* Nameless union parm types are useful as GCC extension. */
|
||||||
if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic)
|
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 ())
|
if (in_parm_level_p ())
|
||||||
warning ("enum defined inside parms");
|
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. */
|
/* 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));
|
int, int));
|
||||||
static void record_international_format PARAMS ((tree, tree, int));
|
static void record_international_format PARAMS ((tree, tree, int));
|
||||||
|
|
||||||
/* Handle the format attribute (with arguments ARGS) attached to the decl
|
/* Handle a "format" attribute; arguments as in
|
||||||
DECL. It is already verified that DECL is a decl and ARGS contains
|
struct attribute_spec.handler. */
|
||||||
exactly three arguments. */
|
tree
|
||||||
|
handle_format_attribute (node, name, args, flags, no_add_attrs)
|
||||||
void
|
tree *node;
|
||||||
decl_handle_format_attribute (decl, args)
|
tree name ATTRIBUTE_UNUSED;
|
||||||
tree decl, args;
|
tree args;
|
||||||
|
int flags ATTRIBUTE_UNUSED;
|
||||||
|
bool *no_add_attrs;
|
||||||
{
|
{
|
||||||
|
tree decl = *node;
|
||||||
tree type = TREE_TYPE (decl);
|
tree type = TREE_TYPE (decl);
|
||||||
tree format_type_id = TREE_VALUE (args);
|
tree format_type_id = TREE_VALUE (args);
|
||||||
tree format_num_expr = TREE_VALUE (TREE_CHAIN (args));
|
tree format_num_expr = TREE_VALUE (TREE_CHAIN (args));
|
||||||
|
@ -104,13 +107,15 @@ decl_handle_format_attribute (decl, args)
|
||||||
{
|
{
|
||||||
error_with_decl (decl,
|
error_with_decl (decl,
|
||||||
"argument format specified for non-function `%s'");
|
"argument format specified for non-function `%s'");
|
||||||
return;
|
*no_add_attrs = true;
|
||||||
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TREE_CODE (format_type_id) != IDENTIFIER_NODE)
|
if (TREE_CODE (format_type_id) != IDENTIFIER_NODE)
|
||||||
{
|
{
|
||||||
error ("unrecognized format specifier");
|
error ("unrecognized format specifier");
|
||||||
return;
|
*no_add_attrs = true;
|
||||||
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -121,7 +126,8 @@ decl_handle_format_attribute (decl, args)
|
||||||
if (format_type == format_type_error)
|
if (format_type == format_type_error)
|
||||||
{
|
{
|
||||||
warning ("`%s' is an unrecognized format function type", p);
|
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)
|
|| TREE_INT_CST_HIGH (first_arg_num_expr) != 0)
|
||||||
{
|
{
|
||||||
error ("format string has invalid operand number");
|
error ("format string has invalid operand number");
|
||||||
return;
|
*no_add_attrs = true;
|
||||||
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
format_num = TREE_INT_CST_LOW (format_num_expr);
|
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)
|
if (first_arg_num != 0 && first_arg_num <= format_num)
|
||||||
{
|
{
|
||||||
error ("format string arg follows the args to be formatted");
|
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
|
/* If a parameter list is specified, verify that the format_num
|
||||||
|
@ -170,7 +178,8 @@ decl_handle_format_attribute (decl, args)
|
||||||
!= char_type_node))
|
!= char_type_node))
|
||||||
{
|
{
|
||||||
error ("format string arg not a string type");
|
error ("format string arg not a string type");
|
||||||
return;
|
*no_add_attrs = true;
|
||||||
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (first_arg_num != 0)
|
else if (first_arg_num != 0)
|
||||||
|
@ -183,7 +192,8 @@ decl_handle_format_attribute (decl, args)
|
||||||
if (arg_num != first_arg_num)
|
if (arg_num != first_arg_num)
|
||||||
{
|
{
|
||||||
error ("args to be formatted is not '...'");
|
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)
|
if (format_type == strftime_format_type && first_arg_num != 0)
|
||||||
{
|
{
|
||||||
error ("strftime formats cannot format arguments");
|
error ("strftime formats cannot format arguments");
|
||||||
return;
|
*no_add_attrs = true;
|
||||||
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
record_function_format (DECL_NAME (decl), DECL_ASSEMBLER_NAME (decl),
|
record_function_format (DECL_NAME (decl), DECL_ASSEMBLER_NAME (decl),
|
||||||
format_type, format_num, first_arg_num);
|
format_type, format_num, first_arg_num);
|
||||||
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Handle the format_arg attribute (with arguments ARGS) attached to
|
/* Handle a "format" attribute; arguments as in
|
||||||
the decl DECL. It is already verified that DECL is a decl and
|
struct attribute_spec.handler. */
|
||||||
ARGS contains exactly one argument. */
|
tree
|
||||||
|
handle_format_arg_attribute (node, name, args, flags, no_add_attrs)
|
||||||
void
|
tree *node;
|
||||||
decl_handle_format_arg_attribute (decl, args)
|
tree name ATTRIBUTE_UNUSED;
|
||||||
tree decl, args;
|
tree args;
|
||||||
|
int flags ATTRIBUTE_UNUSED;
|
||||||
|
bool *no_add_attrs;
|
||||||
{
|
{
|
||||||
|
tree decl = *node;
|
||||||
tree type = TREE_TYPE (decl);
|
tree type = TREE_TYPE (decl);
|
||||||
tree format_num_expr = TREE_VALUE (args);
|
tree format_num_expr = TREE_VALUE (args);
|
||||||
unsigned HOST_WIDE_INT format_num;
|
unsigned HOST_WIDE_INT format_num;
|
||||||
|
@ -217,7 +232,8 @@ decl_handle_format_arg_attribute (decl, args)
|
||||||
{
|
{
|
||||||
error_with_decl (decl,
|
error_with_decl (decl,
|
||||||
"argument format specified for non-function `%s'");
|
"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
|
/* 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)
|
|| TREE_INT_CST_HIGH (format_num_expr) != 0)
|
||||||
{
|
{
|
||||||
error ("format string has invalid operand number");
|
error ("format string has invalid operand number");
|
||||||
return;
|
*no_add_attrs = true;
|
||||||
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
format_num = TREE_INT_CST_LOW (format_num_expr);
|
format_num = TREE_INT_CST_LOW (format_num_expr);
|
||||||
|
@ -252,7 +269,8 @@ decl_handle_format_arg_attribute (decl, args)
|
||||||
!= char_type_node))
|
!= char_type_node))
|
||||||
{
|
{
|
||||||
error ("format string arg not a string type");
|
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))
|
!= char_type_node))
|
||||||
{
|
{
|
||||||
error ("function does not return string type");
|
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),
|
record_international_format (DECL_NAME (decl), DECL_ASSEMBLER_NAME (decl),
|
||||||
format_num);
|
format_num);
|
||||||
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct function_format_info
|
typedef struct function_format_info
|
||||||
|
|
|
@ -173,7 +173,7 @@ end ifc
|
||||||
%type <ttype> declspecs_ts declspecs_nots
|
%type <ttype> declspecs_ts declspecs_nots
|
||||||
%type <ttype> declspecs_ts_nosa declspecs_nots_nosa
|
%type <ttype> declspecs_ts_nosa declspecs_nots_nosa
|
||||||
%type <ttype> declspecs_nosc_ts declspecs_nosc_nots declspecs_nosc declspecs
|
%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_reserved_nonattr typespec_reserved_attr
|
||||||
%type <ttype> typespec_nonreserved_nonattr
|
%type <ttype> typespec_nonreserved_nonattr
|
||||||
|
|
||||||
|
@ -182,7 +182,6 @@ end ifc
|
||||||
%type <ttype> init maybeasm
|
%type <ttype> init maybeasm
|
||||||
%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
|
%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
|
||||||
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
|
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
|
||||||
%type <ttype> maybe_setattrs
|
|
||||||
%type <ttype> any_word extension
|
%type <ttype> any_word extension
|
||||||
|
|
||||||
%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
|
%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
|
||||||
|
@ -847,29 +846,11 @@ setspecs: /* empty */
|
||||||
all_prefix_attributes = prefix_attributes; }
|
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
|
/* Possibly attributes after a comma, which should reset all_prefix_attributes
|
||||||
to prefix_attributes with these ones chained on the front. */
|
to prefix_attributes with these ones chained on the front. */
|
||||||
maybe_resetattrs:
|
maybe_resetattrs:
|
||||||
{ all_prefix_attributes = prefix_attributes; }
|
maybe_attribute
|
||||||
maybe_setattrs
|
{ all_prefix_attributes = chainon ($1, prefix_attributes); }
|
||||||
;
|
;
|
||||||
|
|
||||||
decl:
|
decl:
|
||||||
|
@ -1347,18 +1328,12 @@ declspecs:
|
||||||
| declspecs_sc_ts_sa_ea
|
| declspecs_sc_ts_sa_ea
|
||||||
;
|
;
|
||||||
|
|
||||||
/* A (possibly empty) sequence of type qualifiers and attributes, to be
|
/* A (possibly empty) sequence of type qualifiers and attributes. */
|
||||||
followed by the effect of setattrs if any attributes were present. */
|
maybe_type_quals_attrs:
|
||||||
maybe_type_quals_setattrs:
|
|
||||||
/* empty */
|
/* empty */
|
||||||
{ $$ = NULL_TREE; }
|
{ $$ = NULL_TREE; }
|
||||||
| declspecs_nosc_nots
|
| declspecs_nosc_nots
|
||||||
{ tree specs, attrs;
|
{ $$ = $1; }
|
||||||
split_specs_attrs ($1, &specs, &attrs);
|
|
||||||
/* ??? Yuck. See maybe_setattrs. */
|
|
||||||
if (attrs != NULL_TREE)
|
|
||||||
all_prefix_attributes = chainon (attrs, all_prefix_attributes);
|
|
||||||
$$ = specs; }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
/* A type specifier (but not a type qualifier).
|
/* A type specifier (but not a type qualifier).
|
||||||
|
@ -1669,8 +1644,8 @@ declarator:
|
||||||
/* A declarator that is allowed only after an explicit typespec. */
|
/* A declarator that is allowed only after an explicit typespec. */
|
||||||
|
|
||||||
after_type_declarator:
|
after_type_declarator:
|
||||||
'(' maybe_setattrs after_type_declarator ')'
|
'(' maybe_attribute after_type_declarator ')'
|
||||||
{ $$ = $3; }
|
{ $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
|
||||||
| after_type_declarator '(' parmlist_or_identifiers %prec '.'
|
| after_type_declarator '(' parmlist_or_identifiers %prec '.'
|
||||||
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
|
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
|
||||||
/* | after_type_declarator '(' error ')' %prec '.'
|
/* | after_type_declarator '(' error ')' %prec '.'
|
||||||
|
@ -1678,7 +1653,7 @@ after_type_declarator:
|
||||||
poplevel (0, 0, 0); } */
|
poplevel (0, 0, 0); } */
|
||||||
| after_type_declarator array_declarator %prec '.'
|
| after_type_declarator array_declarator %prec '.'
|
||||||
{ $$ = set_array_declarator_type ($2, $1, 0); }
|
{ $$ = 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); }
|
{ $$ = make_pointer_declarator ($2, $3); }
|
||||||
| TYPENAME
|
| TYPENAME
|
||||||
ifobjc
|
ifobjc
|
||||||
|
@ -1717,12 +1692,12 @@ parm_declarator_nostarttypename:
|
||||||
poplevel (0, 0, 0); } */
|
poplevel (0, 0, 0); } */
|
||||||
| parm_declarator_nostarttypename array_declarator %prec '.'
|
| parm_declarator_nostarttypename array_declarator %prec '.'
|
||||||
{ $$ = set_array_declarator_type ($2, $1, 0); }
|
{ $$ = 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); }
|
{ $$ = 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); }
|
{ $$ = make_pointer_declarator ($2, $3); }
|
||||||
| '(' maybe_setattrs parm_declarator_nostarttypename ')'
|
| '(' maybe_attribute parm_declarator_nostarttypename ')'
|
||||||
{ $$ = $3; }
|
{ $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
|
||||||
;
|
;
|
||||||
|
|
||||||
/* A declarator allowed whether or not there has been
|
/* A declarator allowed whether or not there has been
|
||||||
|
@ -1734,9 +1709,9 @@ notype_declarator:
|
||||||
/* | notype_declarator '(' error ')' %prec '.'
|
/* | notype_declarator '(' error ')' %prec '.'
|
||||||
{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
|
{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
|
||||||
poplevel (0, 0, 0); } */
|
poplevel (0, 0, 0); } */
|
||||||
| '(' maybe_setattrs notype_declarator ')'
|
| '(' maybe_attribute notype_declarator ')'
|
||||||
{ $$ = $3; }
|
{ $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
|
||||||
| '*' maybe_type_quals_setattrs notype_declarator %prec UNARY
|
| '*' maybe_type_quals_attrs notype_declarator %prec UNARY
|
||||||
{ $$ = make_pointer_declarator ($2, $3); }
|
{ $$ = make_pointer_declarator ($2, $3); }
|
||||||
| notype_declarator array_declarator %prec '.'
|
| notype_declarator array_declarator %prec '.'
|
||||||
{ $$ = set_array_declarator_type ($2, $1, 0); }
|
{ $$ = set_array_declarator_type ($2, $1, 0); }
|
||||||
|
@ -1991,20 +1966,20 @@ absdcl1: /* a nonempty absolute declarator */
|
||||||
|
|
||||||
absdcl1_noea:
|
absdcl1_noea:
|
||||||
direct_absdcl1
|
direct_absdcl1
|
||||||
| '*' maybe_type_quals_setattrs absdcl1_noea
|
| '*' maybe_type_quals_attrs absdcl1_noea
|
||||||
{ $$ = make_pointer_declarator ($2, $3); }
|
{ $$ = make_pointer_declarator ($2, $3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
absdcl1_ea:
|
absdcl1_ea:
|
||||||
'*' maybe_type_quals_setattrs
|
'*' maybe_type_quals_attrs
|
||||||
{ $$ = make_pointer_declarator ($2, NULL_TREE); }
|
{ $$ = make_pointer_declarator ($2, NULL_TREE); }
|
||||||
| '*' maybe_type_quals_setattrs absdcl1_ea
|
| '*' maybe_type_quals_attrs absdcl1_ea
|
||||||
{ $$ = make_pointer_declarator ($2, $3); }
|
{ $$ = make_pointer_declarator ($2, $3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
direct_absdcl1:
|
direct_absdcl1:
|
||||||
'(' maybe_setattrs absdcl1 ')'
|
'(' maybe_attribute absdcl1 ')'
|
||||||
{ $$ = $3; }
|
{ $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
|
||||||
| direct_absdcl1 '(' parmlist
|
| direct_absdcl1 '(' parmlist
|
||||||
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
|
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
|
||||||
| direct_absdcl1 array_declarator
|
| direct_absdcl1 array_declarator
|
||||||
|
@ -3904,15 +3879,21 @@ yyprint (file, yychar, yyl)
|
||||||
|
|
||||||
/* Return something to represent absolute declarators containing a *.
|
/* Return something to represent absolute declarators containing a *.
|
||||||
TARGET is the absolute declarator that the * contains.
|
TARGET is the absolute declarator that the * contains.
|
||||||
TYPE_QUALS is a list of modifiers such as const or volatile
|
TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
|
||||||
to apply to the pointer type, represented as identifiers.
|
to apply to the pointer type, represented as identifiers, possible mixed
|
||||||
|
with attributes.
|
||||||
|
|
||||||
We return an INDIRECT_REF whose "contents" are TARGET
|
We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
|
||||||
and whose type is the modifier list. */
|
if attributes are present) and whose type is the modifier list. */
|
||||||
|
|
||||||
tree
|
tree
|
||||||
make_pointer_declarator (type_quals, target)
|
make_pointer_declarator (type_quals_attrs, target)
|
||||||
tree type_quals, 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. */
|
/* Initialize the GCC target structure. */
|
||||||
#if TARGET_ABI_OPEN_VMS
|
#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 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_named_section PARAMS ((const char *, unsigned int));
|
||||||
static void vms_asm_out_constructor PARAMS ((rtx, int));
|
static void vms_asm_out_constructor PARAMS ((rtx, int));
|
||||||
static void vms_asm_out_destructor PARAMS ((rtx, int));
|
static void vms_asm_out_destructor PARAMS ((rtx, int));
|
||||||
# undef TARGET_VALID_DECL_ATTRIBUTE
|
# undef TARGET_ATTRIBUTE_TABLE
|
||||||
# define TARGET_VALID_DECL_ATTRIBUTE vms_valid_decl_attribute_p
|
# define TARGET_ATTRIBUTE_TABLE vms_attribute_table
|
||||||
# undef TARGET_SECTION_TYPE_FLAGS
|
# undef TARGET_SECTION_TYPE_FLAGS
|
||||||
# define TARGET_SECTION_TYPE_FLAGS vms_section_type_flags
|
# define TARGET_SECTION_TYPE_FLAGS vms_section_type_flags
|
||||||
#endif
|
#endif
|
||||||
|
@ -5732,17 +5732,12 @@ alpha_using_fp ()
|
||||||
|
|
||||||
#if TARGET_ABI_OPEN_VMS
|
#if TARGET_ABI_OPEN_VMS
|
||||||
|
|
||||||
static int
|
const struct attribute_spec vms_attribute_table[] =
|
||||||
vms_valid_decl_attribute_p (decl, attributes, identifier, args)
|
|
||||||
tree decl ATTRIBUTE_UNUSED;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree identifier;
|
|
||||||
tree args;
|
|
||||||
{
|
{
|
||||||
if (is_attribute_p ("overlaid", identifier))
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
return (args == NULL_TREE);
|
{ "overlaid", 0, 0, true, false, false, NULL },
|
||||||
return 0;
|
{ NULL, 0, 0, false, false, false, NULL }
|
||||||
}
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7895,8 +7890,8 @@ vms_section_type_flags (decl, name, reloc)
|
||||||
{
|
{
|
||||||
unsigned int flags = default_section_type_flags (decl, name, reloc);
|
unsigned int flags = default_section_type_flags (decl, name, reloc);
|
||||||
|
|
||||||
if (decl && DECL_MACHINE_ATTRIBUTES (decl)
|
if (decl && DECL_ATTRIBUTES (decl)
|
||||||
&& lookup_attribute ("overlaid", DECL_MACHINE_ATTRIBUTES (decl)))
|
&& lookup_attribute ("overlaid", DECL_ATTRIBUTES (decl)))
|
||||||
flags |= SECTION_VMS_OVERLAY;
|
flags |= SECTION_VMS_OVERLAY;
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
|
|
|
@ -87,7 +87,8 @@ static int current_insn_set_cc_p;
|
||||||
static void record_cc_ref PARAMS ((rtx));
|
static void record_cc_ref PARAMS ((rtx));
|
||||||
static void arc_init_reg_tables PARAMS ((void));
|
static void arc_init_reg_tables PARAMS ((void));
|
||||||
static int get_arc_condition_code PARAMS ((rtx));
|
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_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||||
static void arc_output_function_epilogue 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
|
#define TARGET_ASM_FUNCTION_PROLOGUE arc_output_function_prologue
|
||||||
#undef TARGET_ASM_FUNCTION_EPILOGUE
|
#undef TARGET_ASM_FUNCTION_EPILOGUE
|
||||||
#define TARGET_ASM_FUNCTION_EPILOGUE arc_output_function_epilogue
|
#define TARGET_ASM_FUNCTION_EPILOGUE arc_output_function_epilogue
|
||||||
#undef TARGET_VALID_DECL_ATTRIBUTE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_VALID_DECL_ATTRIBUTE arc_valid_decl_attribute
|
#define TARGET_ATTRIBUTE_TABLE arc_attribute_table
|
||||||
|
|
||||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||||
|
|
||||||
|
@ -326,26 +327,40 @@ arc_init_reg_tables ()
|
||||||
interrupt - for interrupt functions
|
interrupt - for interrupt functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Return nonzero if IDENTIFIER is a valid decl attribute. */
|
const struct attribute_spec arc_attribute_table[] =
|
||||||
|
|
||||||
static int
|
|
||||||
arc_valid_decl_attribute (type, attributes, identifier, args)
|
|
||||||
tree type ATTRIBUTE_UNUSED;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree identifier;
|
|
||||||
tree args;
|
|
||||||
{
|
{
|
||||||
if (identifier == get_identifier ("__interrupt__")
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
&& list_length (args) == 1
|
{ "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute },
|
||||||
&& TREE_CODE (TREE_VALUE (args)) == STRING_CST)
|
{ NULL, 0, 0, false, false, false, NULL }
|
||||||
{
|
};
|
||||||
tree value = TREE_VALUE (args);
|
|
||||||
|
|
||||||
if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
|
/* Handle an "interrupt" attribute; arguments as in
|
||||||
|| !strcmp (TREE_STRING_POINTER (value), "ilink2"))
|
struct attribute_spec.handler. */
|
||||||
return 1;
|
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;
|
fn_type = ARC_FUNCTION_NORMAL;
|
||||||
|
|
||||||
/* Now see if this is an interrupt handler. */
|
/* 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;
|
||||||
a = TREE_CHAIN (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_compute_save_reg_mask PARAMS ((void));
|
||||||
static Ulong arm_isr_value PARAMS ((tree));
|
static Ulong arm_isr_value PARAMS ((tree));
|
||||||
static Ulong arm_compute_func_type PARAMS ((void));
|
static Ulong arm_compute_func_type PARAMS ((void));
|
||||||
static int arm_valid_type_attribute_p PARAMS ((tree, tree,
|
static tree arm_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
|
||||||
tree, tree));
|
static tree arm_handle_isr_attribute PARAMS ((tree *, tree, tree, int, bool *));
|
||||||
static int arm_valid_decl_attribute_p PARAMS ((tree, tree,
|
const struct attribute_spec arm_attribute_table[];
|
||||||
tree, tree));
|
|
||||||
static void arm_output_function_epilogue PARAMS ((FILE *,
|
static void arm_output_function_epilogue PARAMS ((FILE *,
|
||||||
HOST_WIDE_INT));
|
HOST_WIDE_INT));
|
||||||
static void arm_output_function_prologue PARAMS ((FILE *,
|
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
|
#define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef TARGET_VALID_TYPE_ATTRIBUTE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_VALID_TYPE_ATTRIBUTE arm_valid_type_attribute_p
|
#define TARGET_ATTRIBUTE_TABLE arm_attribute_table
|
||||||
|
|
||||||
#undef TARGET_VALID_DECL_ATTRIBUTE
|
|
||||||
#ifdef ARM_PE
|
|
||||||
static int arm_pe_valid_decl_attribute_p PARAMS ((tree, tree, tree, tree));
|
|
||||||
# define TARGET_VALID_DECL_ATTRIBUTE arm_pe_valid_decl_attribute_p
|
|
||||||
#else
|
|
||||||
# define TARGET_VALID_DECL_ATTRIBUTE arm_valid_decl_attribute_p
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
||||||
#define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue
|
#define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue
|
||||||
|
@ -845,7 +836,7 @@ arm_compute_func_type ()
|
||||||
if (current_function_needs_context)
|
if (current_function_needs_context)
|
||||||
type |= ARM_FT_NESTED;
|
type |= ARM_FT_NESTED;
|
||||||
|
|
||||||
attr = DECL_MACHINE_ATTRIBUTES (current_function_decl);
|
attr = DECL_ATTRIBUTES (current_function_decl);
|
||||||
|
|
||||||
a = lookup_attribute ("naked", attr);
|
a = lookup_attribute ("naked", attr);
|
||||||
if (a != NULL_TREE)
|
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
|
/* Table of machine attributes. */
|
||||||
specific attribute for TYPE. The attributes in ATTRIBUTES have
|
const struct attribute_spec arm_attribute_table[] =
|
||||||
previously been assigned to TYPE. */
|
|
||||||
static int
|
|
||||||
arm_valid_type_attribute_p (type, attributes, identifier, args)
|
|
||||||
tree type;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree identifier;
|
|
||||||
tree args;
|
|
||||||
{
|
{
|
||||||
if ( TREE_CODE (type) != FUNCTION_TYPE
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
&& TREE_CODE (type) != METHOD_TYPE
|
|
||||||
&& TREE_CODE (type) != FIELD_DECL
|
|
||||||
&& TREE_CODE (type) != TYPE_DECL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Function calls made to this symbol must be done indirectly, because
|
/* 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
|
it may lie outside of the 26 bit addressing range of a normal function
|
||||||
call. */
|
call. */
|
||||||
if (is_attribute_p ("long_call", identifier))
|
{ "long_call", 0, 0, false, true, true, NULL },
|
||||||
return (args == NULL_TREE);
|
|
||||||
|
|
||||||
/* Whereas these functions are always known to reside within the 26 bit
|
/* Whereas these functions are always known to reside within the 26 bit
|
||||||
addressing range. */
|
addressing range. */
|
||||||
if (is_attribute_p ("short_call", identifier))
|
{ "short_call", 0, 0, false, true, true, NULL },
|
||||||
return (args == NULL_TREE);
|
|
||||||
|
|
||||||
/* Interrupt Service Routines have special prologue and epilogue requirements. */
|
/* Interrupt Service Routines have special prologue and epilogue requirements. */
|
||||||
if (is_attribute_p ("isr", identifier)
|
{ "isr", 0, 1, false, false, false, arm_handle_isr_attribute },
|
||||||
|| is_attribute_p ("interrupt", identifier))
|
{ "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute },
|
||||||
return arm_isr_value (args);
|
{ "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
|
/* Return 0 if the attributes for two types are incompatible, 1 if they
|
||||||
|
@ -4132,85 +4204,6 @@ multi_register_push (op, mode)
|
||||||
return 1;
|
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. */
|
/* Routines for use in generating RTL. */
|
||||||
rtx
|
rtx
|
||||||
arm_gen_load_multiple (base_regno, count, from, up, write_back, unchanging_p,
|
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;
|
return TRUE;
|
||||||
|
|
||||||
#ifdef ARM_PE
|
#ifdef ARM_PE
|
||||||
return lookup_attribute ("interfacearm", DECL_MACHINE_ATTRIBUTES (func)) != NULL_TREE;
|
return lookup_attribute ("interfacearm", DECL_ATTRIBUTES (func)) != NULL_TREE;
|
||||||
#else
|
#else
|
||||||
return FALSE;
|
return FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Routines for GCC for ARM/pe.
|
/* 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).
|
Contributed by Doug Evans (dje@cygnus.com).
|
||||||
|
|
||||||
This file is part of GNU CC.
|
This file is part of GNU CC.
|
||||||
|
@ -45,7 +45,7 @@ arm_dllexport_p (decl)
|
||||||
if (TREE_CODE (decl) != VAR_DECL
|
if (TREE_CODE (decl) != VAR_DECL
|
||||||
&& TREE_CODE (decl) != FUNCTION_DECL)
|
&& TREE_CODE (decl) != FUNCTION_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
exp = lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl));
|
exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
|
||||||
if (exp)
|
if (exp)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ arm_dllimport_p (decl)
|
||||||
if (TREE_CODE (decl) != VAR_DECL
|
if (TREE_CODE (decl) != VAR_DECL
|
||||||
&& TREE_CODE (decl) != FUNCTION_DECL)
|
&& TREE_CODE (decl) != FUNCTION_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl));
|
imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
|
||||||
if (imp)
|
if (imp)
|
||||||
return 1;
|
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 reg_was_0 PARAMS ((rtx insn, rtx op));
|
||||||
static int io_address_p PARAMS ((rtx x, int size));
|
static int io_address_p PARAMS ((rtx x, int size));
|
||||||
void debug_hard_reg_set PARAMS ((HARD_REG_SET set));
|
void debug_hard_reg_set PARAMS ((HARD_REG_SET set));
|
||||||
static int avr_valid_type_attribute PARAMS ((tree, tree, tree, tree));
|
static tree avr_handle_progmem_attribute PARAMS ((tree *, tree, tree, int, bool *));
|
||||||
static int avr_valid_decl_attribute PARAMS ((tree, tree, tree, tree));
|
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_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||||
static void avr_output_function_epilogue 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
|
#define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
|
||||||
#undef TARGET_ASM_FUNCTION_EPILOGUE
|
#undef TARGET_ASM_FUNCTION_EPILOGUE
|
||||||
#define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
|
#define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
|
||||||
#undef TARGET_VALID_DECL_ATTRIBUTE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_VALID_DECL_ATTRIBUTE avr_valid_decl_attribute
|
#define TARGET_ATTRIBUTE_TABLE avr_attribute_table
|
||||||
|
|
||||||
#undef TARGET_VALID_TYPE_ATTRIBUTE
|
|
||||||
#define TARGET_VALID_TYPE_ATTRIBUTE avr_valid_type_attribute
|
|
||||||
|
|
||||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||||
|
|
||||||
|
@ -310,7 +308,7 @@ avr_naked_function_p (func)
|
||||||
if (TREE_CODE (func) != FUNCTION_DECL)
|
if (TREE_CODE (func) != FUNCTION_DECL)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
|
a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
|
||||||
return a != NULL_TREE;
|
return a != NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +324,7 @@ interrupt_function_p (func)
|
||||||
if (TREE_CODE (func) != FUNCTION_DECL)
|
if (TREE_CODE (func) != FUNCTION_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));
|
a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
|
||||||
return a != NULL_TREE;
|
return a != NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +340,7 @@ signal_function_p (func)
|
||||||
if (TREE_CODE (func) != FUNCTION_DECL)
|
if (TREE_CODE (func) != FUNCTION_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
a = lookup_attribute ("signal", DECL_MACHINE_ATTRIBUTES (func));
|
a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
|
||||||
return a != NULL_TREE;
|
return a != NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4665,54 +4663,76 @@ class_likely_spilled_p (c)
|
||||||
return (c != ALL_REGS && c != ADDW_REGS);
|
return (c != ALL_REGS && c != ADDW_REGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only `progmem' attribute valid for type. */
|
/* Valid attributes:
|
||||||
|
|
||||||
static int
|
|
||||||
avr_valid_type_attribute (type, attributes, identifier, args)
|
|
||||||
tree type ATTRIBUTE_UNUSED;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree identifier;
|
|
||||||
tree args ATTRIBUTE_UNUSED;
|
|
||||||
{
|
|
||||||
return is_attribute_p ("progmem", identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If IDENTIFIER with arguments ARGS is a valid machine specific
|
|
||||||
attribute for DECL return 1.
|
|
||||||
Valid attributes:
|
|
||||||
progmem - put data to program memory;
|
progmem - put data to program memory;
|
||||||
signal - make a function to be hardware interrupt. After function
|
signal - make a function to be hardware interrupt. After function
|
||||||
prologue interrupts are disabled;
|
prologue interrupts are disabled;
|
||||||
interrupt - make a function to be hardware interrupt. After function
|
interrupt - make a function to be hardware interrupt. After function
|
||||||
prologue interrupts are enabled;
|
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
|
Only `progmem' attribute valid for type. */
|
||||||
avr_valid_decl_attribute (decl, attributes, attr, args)
|
|
||||||
tree decl;
|
const struct attribute_spec avr_attribute_table[] =
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree attr;
|
|
||||||
tree args ATTRIBUTE_UNUSED;
|
|
||||||
{
|
{
|
||||||
if (is_attribute_p ("interrupt", attr)
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
|| is_attribute_p ("signal", attr)
|
{ "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
|
||||||
|| is_attribute_p ("naked", attr))
|
{ "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
|
||||||
return TREE_CODE (decl) == FUNCTION_DECL;
|
{ "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)
|
/* Handle a "progmem" attribute; arguments as in
|
||||||
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
|
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 "
|
if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
|
||||||
"program memory area.");
|
{
|
||||||
return 0;
|
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
|
/* Look for attribute `progmem' in DECL
|
||||||
if found return 1, otherwise 0. */
|
if found return 1, otherwise 0. */
|
||||||
|
@ -4727,7 +4747,7 @@ avr_progmem_p (decl)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (NULL_TREE
|
if (NULL_TREE
|
||||||
!= lookup_attribute ("progmem", DECL_MACHINE_ATTRIBUTES (decl)))
|
!= lookup_attribute ("progmem", DECL_ATTRIBUTES (decl)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
a=decl;
|
a=decl;
|
||||||
|
|
|
@ -1110,7 +1110,7 @@ enum reg_class {
|
||||||
FUNDECL is a C variable whose value is a tree node that describes
|
FUNDECL is a C variable whose value is a tree node that describes
|
||||||
the function in question. Normally it is a node of type
|
the function in question. Normally it is a node of type
|
||||||
`FUNCTION_DECL' that describes the declaration of the function.
|
`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.
|
function.
|
||||||
|
|
||||||
FUNTYPE is a C variable whose value is a tree node that describes
|
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_r11_set_p PARAMS ((rtx));
|
||||||
static int c4x_rptb_valid_p PARAMS ((rtx, rtx));
|
static int c4x_rptb_valid_p PARAMS ((rtx, rtx));
|
||||||
static int c4x_label_ref_used_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_insert_attributes PARAMS ((tree, tree *));
|
||||||
static void c4x_asm_named_section PARAMS ((const char *, unsigned int));
|
static void c4x_asm_named_section PARAMS ((const char *, unsigned int));
|
||||||
static int c4x_adjust_cost PARAMS ((rtx, rtx, rtx, int));
|
static int c4x_adjust_cost PARAMS ((rtx, rtx, rtx, int));
|
||||||
|
|
||||||
/* Initialize the GCC target structure. */
|
/* Initialize the GCC target structure. */
|
||||||
#undef TARGET_VALID_TYPE_ATTRIBUTE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_VALID_TYPE_ATTRIBUTE c4x_valid_type_attribute_p
|
#define TARGET_ATTRIBUTE_TABLE c4x_attribute_table
|
||||||
|
|
||||||
#undef TARGET_INSERT_ATTRIBUTES
|
#undef TARGET_INSERT_ATTRIBUTES
|
||||||
#define TARGET_INSERT_ATTRIBUTES c4x_insert_attributes
|
#define TARGET_INSERT_ATTRIBUTES c4x_insert_attributes
|
||||||
|
@ -4761,31 +4762,36 @@ c4x_insert_attributes (decl, attributes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Table of valid machine attributes. */
|
||||||
/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine
|
const struct attribute_spec c4x_attribute_table[] =
|
||||||
specific attribute for TYPE. The attributes in ATTRIBUTES have
|
|
||||||
previously been assigned to TYPE. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
c4x_valid_type_attribute_p (type, attributes, identifier, args)
|
|
||||||
tree type;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree identifier;
|
|
||||||
tree args ATTRIBUTE_UNUSED;
|
|
||||||
{
|
{
|
||||||
if (TREE_CODE (type) != FUNCTION_TYPE)
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
return 0;
|
{ "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 }
|
||||||
|
};
|
||||||
|
|
||||||
if (is_attribute_p ("interrupt", identifier))
|
/* Handle an attribute requiring a FUNCTION_TYPE;
|
||||||
return 1;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_attribute_p ("assembler", identifier))
|
return NULL_TREE;
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (is_attribute_p ("leaf_pretend", identifier))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2272,7 +2272,7 @@ typedef struct d30v_stack {
|
||||||
FUNDECL is a C variable whose value is a tree node that describes the
|
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
|
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
|
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
|
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
|
function in question. Normally it is a node of type `FUNCTION_TYPE' that
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*{{{ Comment. */
|
/*{{{ Comment. */
|
||||||
|
|
||||||
/* Definitions of FR30 target.
|
/* 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.
|
Contributed by Cygnus Solutions.
|
||||||
|
|
||||||
This file is part of GNU CC.
|
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
|
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
|
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
|
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
|
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
|
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 push PARAMS ((FILE *, int));
|
||||||
static void pop PARAMS ((FILE *, int));
|
static void pop PARAMS ((FILE *, int));
|
||||||
static const char *cond_string PARAMS ((enum rtx_code));
|
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_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||||
static void h8300_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
static void h8300_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||||
static void h8300_asm_named_section PARAMS ((const char *, unsigned int));
|
static 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;
|
const char *h8_push_op, *h8_pop_op, *h8_mov_op;
|
||||||
|
|
||||||
/* Initialize the GCC target structure. */
|
/* Initialize the GCC target structure. */
|
||||||
#undef TARGET_VALID_DECL_ATTRIBUTE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_VALID_DECL_ATTRIBUTE h8300_valid_decl_attribute
|
#define TARGET_ATTRIBUTE_TABLE h8300_attribute_table
|
||||||
|
|
||||||
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
||||||
#define TARGET_ASM_FUNCTION_PROLOGUE h8300_output_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)
|
if (TREE_CODE (func) != FUNCTION_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
a = lookup_attribute ("interrupt_handler", DECL_MACHINE_ATTRIBUTES (func));
|
a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
|
||||||
return a != NULL_TREE;
|
return a != NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3118,7 +3121,7 @@ h8300_os_task_function_p (func)
|
||||||
if (TREE_CODE (func) != FUNCTION_DECL)
|
if (TREE_CODE (func) != FUNCTION_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
a = lookup_attribute ("OS_Task", DECL_MACHINE_ATTRIBUTES (func));
|
a = lookup_attribute ("OS_Task", DECL_ATTRIBUTES (func));
|
||||||
return a != NULL_TREE;
|
return a != NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3134,7 +3137,7 @@ h8300_monitor_function_p (func)
|
||||||
if (TREE_CODE (func) != FUNCTION_DECL)
|
if (TREE_CODE (func) != FUNCTION_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
a = lookup_attribute ("monitor", DECL_MACHINE_ATTRIBUTES (func));
|
a = lookup_attribute ("monitor", DECL_ATTRIBUTES (func));
|
||||||
return a != NULL_TREE;
|
return a != NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3150,7 +3153,7 @@ h8300_funcvec_function_p (func)
|
||||||
if (TREE_CODE (func) != FUNCTION_DECL)
|
if (TREE_CODE (func) != FUNCTION_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
a = lookup_attribute ("function_vector", DECL_MACHINE_ATTRIBUTES (func));
|
a = lookup_attribute ("function_vector", DECL_ATTRIBUTES (func));
|
||||||
return a != NULL_TREE;
|
return a != NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3166,7 +3169,7 @@ h8300_eightbit_data_p (decl)
|
||||||
if (TREE_CODE (decl) != VAR_DECL)
|
if (TREE_CODE (decl) != VAR_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
a = lookup_attribute ("eightbit_data", DECL_MACHINE_ATTRIBUTES (decl));
|
a = lookup_attribute ("eightbit_data", DECL_ATTRIBUTES (decl));
|
||||||
return a != NULL_TREE;
|
return a != NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3182,15 +3185,11 @@ h8300_tiny_data_p (decl)
|
||||||
if (TREE_CODE (decl) != VAR_DECL)
|
if (TREE_CODE (decl) != VAR_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
a = lookup_attribute ("tiny_data", DECL_MACHINE_ATTRIBUTES (decl));
|
a = lookup_attribute ("tiny_data", DECL_ATTRIBUTES (decl));
|
||||||
return a != NULL_TREE;
|
return a != NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return nonzero if ATTR is a valid attribute for DECL.
|
/* Supported attributes:
|
||||||
ATTRIBUTES are any existing attributes and ARGS are the arguments
|
|
||||||
supplied with ATTR.
|
|
||||||
|
|
||||||
Supported attributes:
|
|
||||||
|
|
||||||
interrupt_handler: output a prologue and epilogue suitable for an
|
interrupt_handler: output a prologue and epilogue suitable for an
|
||||||
interrupt handler.
|
interrupt handler.
|
||||||
|
@ -3204,47 +3203,99 @@ h8300_tiny_data_p (decl)
|
||||||
tiny_data: This variable lives in the tiny data area and can be
|
tiny_data: This variable lives in the tiny data area and can be
|
||||||
referenced with 16-bit absolute memory references. */
|
referenced with 16-bit absolute memory references. */
|
||||||
|
|
||||||
static int
|
const struct attribute_spec h8300_attribute_table[] =
|
||||||
h8300_valid_decl_attribute (decl, attributes, attr, args)
|
|
||||||
tree decl;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree attr;
|
|
||||||
tree args;
|
|
||||||
{
|
{
|
||||||
if (args != NULL_TREE)
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
return 0;
|
{ "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)
|
/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
|
||||||
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
|
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)
|
if (DECL_INITIAL (decl) == NULL_TREE)
|
||||||
{
|
{
|
||||||
warning ("Only initialized variables can be placed into the 8-bit area.");
|
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");
|
else
|
||||||
return 1;
|
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)
|
return NULL_TREE;
|
||||||
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
|
}
|
||||||
|
|
||||||
|
/* 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)
|
if (DECL_INITIAL (decl) == NULL_TREE)
|
||||||
{
|
{
|
||||||
warning ("Only initialized variables can be placed into the 8-bit area.");
|
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");
|
else
|
||||||
return 1;
|
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
|
void
|
||||||
|
|
|
@ -191,7 +191,7 @@ union tree_node;
|
||||||
It's also used to handle dllimport override semantics. */
|
It's also used to handle dllimport override semantics. */
|
||||||
#if 0
|
#if 0
|
||||||
#define REDO_SECTION_INFO_P(DECL) \
|
#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)))
|
|| (TREE_CODE (DECL) == VAR_DECL && DECL_VIRTUAL_P (DECL)))
|
||||||
#else
|
#else
|
||||||
#define REDO_SECTION_INFO_P(DECL) 1
|
#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_data_alignment PARAMS ((tree, int));
|
||||||
extern int ix86_local_alignment PARAMS ((tree, int));
|
extern int ix86_local_alignment PARAMS ((tree, int));
|
||||||
extern int ix86_constant_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 tree ix86_handle_dll_attribute PARAMS ((tree *, tree, tree, int, bool *));
|
||||||
extern int i386_pe_valid_decl_attribute_p PARAMS ((tree, tree, tree, tree));
|
extern tree ix86_handle_shared_attribute PARAMS ((tree *, tree, tree, int, bool *));
|
||||||
extern int i386_pe_valid_type_attribute_p PARAMS ((tree, tree, tree, tree));
|
|
||||||
extern unsigned int i386_pe_section_type_flags PARAMS ((tree, const char *,
|
extern unsigned int i386_pe_section_type_flags PARAMS ((tree, const char *,
|
||||||
int));
|
int));
|
||||||
extern void i386_pe_asm_named_section PARAMS ((const char *, unsigned 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 int ix86_save_reg PARAMS ((int, int));
|
||||||
static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
|
static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
|
||||||
static int ix86_comp_type_attributes PARAMS ((tree, tree));
|
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
|
#ifdef DO_GLOBAL_CTORS_BODY
|
||||||
static void ix86_svr3_asm_out_constructor PARAMS ((rtx, int));
|
static void ix86_svr3_asm_out_constructor PARAMS ((rtx, int));
|
||||||
|
@ -667,15 +670,11 @@ static void sco_asm_out_constructor PARAMS ((rtx, int));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Initialize the GCC target structure. */
|
/* 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
|
#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
|
# undef TARGET_MERGE_DECL_ATTRIBUTES
|
||||||
# define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
|
# define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
|
||||||
#else
|
|
||||||
# define TARGET_VALID_TYPE_ATTRIBUTE ix86_valid_type_attribute_p
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef TARGET_COMP_TYPE_ATTRIBUTES
|
#undef TARGET_COMP_TYPE_ATTRIBUTES
|
||||||
|
@ -977,56 +976,94 @@ optimization_options (level, size)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
|
/* Table of valid machine attributes. */
|
||||||
attribute for TYPE. The attributes in ATTRIBUTES have previously been
|
const struct attribute_spec ix86_attribute_table[] =
|
||||||
assigned to TYPE. */
|
|
||||||
|
|
||||||
int
|
|
||||||
ix86_valid_type_attribute_p (type, attributes, identifier, args)
|
|
||||||
tree type;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree identifier;
|
|
||||||
tree args;
|
|
||||||
{
|
{
|
||||||
if (TREE_CODE (type) != FUNCTION_TYPE
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
&& TREE_CODE (type) != METHOD_TYPE
|
|
||||||
&& TREE_CODE (type) != FIELD_DECL
|
|
||||||
&& TREE_CODE (type) != TYPE_DECL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Stdcall attribute says callee is responsible for popping arguments
|
/* Stdcall attribute says callee is responsible for popping arguments
|
||||||
if they are not variable. */
|
if they are not variable. */
|
||||||
if (is_attribute_p ("stdcall", identifier)
|
{ "stdcall", 0, 0, false, true, true, ix86_handle_cdecl_attribute },
|
||||||
&& !TARGET_64BIT)
|
/* Cdecl attribute says the callee is a normal C declaration */
|
||||||
return (args == NULL_TREE);
|
{ "cdecl", 0, 0, false, true, true, ix86_handle_cdecl_attribute },
|
||||||
|
|
||||||
/* Cdecl attribute says the callee is a normal C declaration. */
|
|
||||||
if (is_attribute_p ("cdecl", identifier)
|
|
||||||
&& !TARGET_64BIT)
|
|
||||||
return (args == NULL_TREE);
|
|
||||||
|
|
||||||
/* Regparm attribute specifies how many integer arguments are to be
|
/* Regparm attribute specifies how many integer arguments are to be
|
||||||
passed in registers. */
|
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;
|
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);
|
cst = TREE_VALUE (args);
|
||||||
if (TREE_CODE (cst) != INTEGER_CST)
|
if (TREE_CODE (cst) != INTEGER_CST)
|
||||||
return 0;
|
{
|
||||||
|
warning ("`%s' attribute requires an integer constant argument",
|
||||||
if (compare_tree_int (cst, REGPARM_MAX) > 0)
|
IDENTIFIER_POINTER (name));
|
||||||
return 0;
|
*no_add_attrs = true;
|
||||||
|
}
|
||||||
return 1;
|
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)
|
#if defined (OSF_OS) || defined (TARGET_OSF1ELF)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* Subroutines for insn-output.c for Windows NT.
|
/* Subroutines for insn-output.c for Windows NT.
|
||||||
Contributed by Douglas Rupp (drupp@cs.washington.edu)
|
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.
|
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_dllexport PARAMS ((tree));
|
||||||
void i386_pe_mark_dllimport PARAMS ((tree));
|
void i386_pe_mark_dllimport PARAMS ((tree));
|
||||||
|
|
||||||
/* Return nonzero if ATTR is a valid attribute for DECL.
|
/* Handle a "dllimport" or "dllexport" attribute;
|
||||||
ATTRIBUTES are any existing attributes and ARGS are the arguments
|
arguments as in struct attribute_spec.handler. */
|
||||||
supplied with ATTR. */
|
tree
|
||||||
|
ix86_handle_dll_attribute (node, name, args, flags, no_add_attrs)
|
||||||
int
|
tree *node;
|
||||||
i386_pe_valid_decl_attribute_p (decl, attributes, attr, args)
|
tree name;
|
||||||
tree decl;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree attr;
|
|
||||||
tree args;
|
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))
|
if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
|
||||||
return 1;
|
| (int) ATTR_FLAG_ARRAY_NEXT))
|
||||||
if (is_attribute_p ("dllimport", attr))
|
{
|
||||||
return 1;
|
*no_add_attrs = true;
|
||||||
if (is_attribute_p ("shared", attr))
|
return tree_cons (name, args, NULL_TREE);
|
||||||
return TREE_CODE (decl) == VAR_DECL;
|
}
|
||||||
|
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.
|
/* Handle a "shared" attribute;
|
||||||
ATTRIBUTES are any existing attributes and ARGS are the arguments
|
arguments as in struct attribute_spec.handler. */
|
||||||
supplied with ATTR. */
|
tree
|
||||||
|
ix86_handle_shared_attribute (node, name, args, flags, no_add_attrs)
|
||||||
int
|
tree *node;
|
||||||
i386_pe_valid_type_attribute_p (type, attributes, attr, args)
|
tree name;
|
||||||
tree type;
|
tree args ATTRIBUTE_UNUSED;
|
||||||
tree attributes;
|
int flags ATTRIBUTE_UNUSED;
|
||||||
tree attr;
|
bool *no_add_attrs;
|
||||||
tree args;
|
|
||||||
{
|
{
|
||||||
if (args == NULL_TREE
|
if (TREE_CODE (*node) != VAR_DECL)
|
||||||
&& (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
|
|
||||||
{
|
{
|
||||||
if (is_attribute_p ("dllexport", attr))
|
warning ("`%s' attribute only applies to variables",
|
||||||
return 1;
|
IDENTIFIER_POINTER (name));
|
||||||
if (is_attribute_p ("dllimport", attr))
|
*no_add_attrs = true;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
/* 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
|
if (TREE_CODE (decl) != VAR_DECL
|
||||||
&& TREE_CODE (decl) != FUNCTION_DECL)
|
&& TREE_CODE (decl) != FUNCTION_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
exp = lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl));
|
exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
|
||||||
if (exp)
|
if (exp)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -163,7 +166,7 @@ i386_pe_dllimport_p (decl)
|
||||||
if (TREE_CODE (decl) != VAR_DECL
|
if (TREE_CODE (decl) != VAR_DECL
|
||||||
&& TREE_CODE (decl) != FUNCTION_DECL)
|
&& TREE_CODE (decl) != FUNCTION_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl));
|
imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
|
||||||
if (imp)
|
if (imp)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -499,7 +502,7 @@ i386_pe_section_type_flags (decl, name, reloc)
|
||||||
flags = SECTION_WRITE;
|
flags = SECTION_WRITE;
|
||||||
|
|
||||||
if (decl && TREE_CODE (decl) == VAR_DECL
|
if (decl && TREE_CODE (decl) == VAR_DECL
|
||||||
&& lookup_attribute ("shared", DECL_MACHINE_ATTRIBUTES (decl)))
|
&& lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
|
||||||
flags |= SECTION_PE_SHARED;
|
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,
|
static rtx ia64_expand_lock_test_and_set PARAMS ((enum machine_mode,
|
||||||
tree, rtx));
|
tree, rtx));
|
||||||
static rtx ia64_expand_lock_release 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_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||||
static void ia64_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
static void ia64_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||||
static void ia64_output_function_end_prologue PARAMS ((FILE *));
|
static 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. */
|
/* Initialize the GCC target structure. */
|
||||||
#undef TARGET_VALID_TYPE_ATTRIBUTE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_VALID_TYPE_ATTRIBUTE ia64_valid_type_attribute
|
#define TARGET_ATTRIBUTE_TABLE ia64_attribute_table
|
||||||
|
|
||||||
#undef TARGET_INIT_BUILTINS
|
#undef TARGET_INIT_BUILTINS
|
||||||
#define TARGET_INIT_BUILTINS ia64_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. */
|
/* Table of valid machine attributes. */
|
||||||
|
const struct attribute_spec ia64_attribute_table[] =
|
||||||
static int
|
|
||||||
ia64_valid_type_attribute (type, attributes, identifier, args)
|
|
||||||
tree type;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree identifier;
|
|
||||||
tree args;
|
|
||||||
{
|
{
|
||||||
/* We only support an attribute for function calls. */
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
|
{ "syscall_linkage", 0, 0, false, true, true, NULL },
|
||||||
if (TREE_CODE (type) != FUNCTION_TYPE
|
{ NULL, 0, 0, false, false, false, NULL }
|
||||||
&& TREE_CODE (type) != METHOD_TYPE)
|
};
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* The "syscall_linkage" attribute says the callee is a system call entry
|
|
||||||
point. This affects ia64_epilogue_uses. */
|
|
||||||
|
|
||||||
if (is_attribute_p ("syscall_linkage", identifier))
|
|
||||||
return args == NULL_TREE;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For ia64, SYMBOL_REF_FLAG set means that it is a function.
|
/* 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 init_reg_tables PARAMS ((void));
|
||||||
static void block_move_call PARAMS ((rtx, rtx, rtx));
|
static void block_move_call PARAMS ((rtx, rtx, rtx));
|
||||||
static int m32r_is_insn PARAMS ((rtx));
|
static int m32r_is_insn PARAMS ((rtx));
|
||||||
static int m32r_valid_decl_attribute PARAMS ((tree, tree,
|
const struct attribute_spec m32r_attribute_table[];
|
||||||
tree, tree));
|
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_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||||
static void m32r_output_function_epilogue 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. */
|
/* Initialize the GCC target structure. */
|
||||||
#undef TARGET_VALID_DECL_ATTRIBUTE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_VALID_DECL_ATTRIBUTE m32r_valid_decl_attribute
|
#define TARGET_ATTRIBUTE_TABLE m32r_attribute_table
|
||||||
|
|
||||||
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
||||||
#define TARGET_ASM_FUNCTION_PROLOGUE m32r_output_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.
|
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_ident1;
|
||||||
static tree small_ident2;
|
static tree small_ident2;
|
||||||
static tree medium_ident1;
|
static tree medium_ident1;
|
||||||
|
@ -264,12 +260,8 @@ static tree large_ident2;
|
||||||
static void
|
static void
|
||||||
init_idents PARAMS ((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_ident1 = get_identifier ("small");
|
||||||
small_ident2 = get_identifier ("__small__");
|
small_ident2 = get_identifier ("__small__");
|
||||||
medium_ident1 = get_identifier ("medium");
|
medium_ident1 = get_identifier ("medium");
|
||||||
|
@ -279,34 +271,43 @@ init_idents PARAMS ((void))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return nonzero if IDENTIFIER is a valid decl attribute. */
|
const struct attribute_spec m32r_attribute_table[] =
|
||||||
|
|
||||||
static int
|
|
||||||
m32r_valid_decl_attribute (type, attributes, identifier, args)
|
|
||||||
tree type ATTRIBUTE_UNUSED;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree identifier;
|
|
||||||
tree args;
|
|
||||||
{
|
{
|
||||||
|
/* { 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 ();
|
init_idents ();
|
||||||
|
arg = TREE_VALUE (args);
|
||||||
|
|
||||||
if ((identifier == interrupt_ident1
|
if (arg != small_ident1
|
||||||
|| identifier == interrupt_ident2)
|
&& arg != small_ident2
|
||||||
&& list_length (args) == 0)
|
&& arg != medium_ident1
|
||||||
return 1;
|
&& 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
|
return NULL_TREE;
|
||||||
|| identifier == model_ident2)
|
|
||||||
&& list_length (args) == 1
|
|
||||||
&& (TREE_VALUE (args) == small_ident1
|
|
||||||
|| TREE_VALUE (args) == small_ident2
|
|
||||||
|| TREE_VALUE (args) == medium_ident1
|
|
||||||
|| TREE_VALUE (args) == medium_ident2
|
|
||||||
|| TREE_VALUE (args) == large_ident1
|
|
||||||
|| TREE_VALUE (args) == large_ident2))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A C statement or statements to switch to the appropriate
|
/* A C statement or statements to switch to the appropriate
|
||||||
|
@ -370,7 +371,7 @@ m32r_encode_section_info (decl)
|
||||||
{
|
{
|
||||||
case VAR_DECL :
|
case VAR_DECL :
|
||||||
case FUNCTION_DECL :
|
case FUNCTION_DECL :
|
||||||
model = lookup_attribute ("model", DECL_MACHINE_ATTRIBUTES (decl));
|
model = lookup_attribute ("model", DECL_ATTRIBUTES (decl));
|
||||||
break;
|
break;
|
||||||
case STRING_CST :
|
case STRING_CST :
|
||||||
case CONSTRUCTOR :
|
case CONSTRUCTOR :
|
||||||
|
@ -1747,7 +1748,7 @@ m32r_compute_function_type (decl)
|
||||||
return fn_type;
|
return fn_type;
|
||||||
|
|
||||||
/* Compute function 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_INTERRUPT
|
||||||
: M32R_FUNCTION_NORMAL);
|
: 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 must_parenthesize PARAMS ((rtx));
|
||||||
static int m68hc11_shift_cost PARAMS ((enum machine_mode, rtx, int));
|
static int m68hc11_shift_cost PARAMS ((enum machine_mode, rtx, int));
|
||||||
static int m68hc11_auto_inc_p PARAMS ((rtx));
|
static int m68hc11_auto_inc_p PARAMS ((rtx));
|
||||||
static int m68hc11_valid_type_attribute_p PARAMS((tree, tree,
|
static tree m68hc11_handle_fntype_attribute PARAMS ((tree *, tree, tree, int, bool *));
|
||||||
tree, tree));
|
const struct attribute_spec m68hc11_attribute_table[];
|
||||||
|
|
||||||
void create_regs_rtx PARAMS ((void));
|
void create_regs_rtx PARAMS ((void));
|
||||||
static void m68hc11_add_gc_roots 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;
|
static int nb_soft_regs;
|
||||||
|
|
||||||
/* Initialize the GCC target structure. */
|
/* Initialize the GCC target structure. */
|
||||||
#undef TARGET_VALID_TYPE_ATTRIBUTE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_VALID_TYPE_ATTRIBUTE m68hc11_valid_type_attribute_p
|
#define TARGET_ATTRIBUTE_TABLE m68hc11_attribute_table
|
||||||
|
|
||||||
#undef TARGET_ASM_FUNCTION_EPILOGUE
|
#undef TARGET_ASM_FUNCTION_EPILOGUE
|
||||||
#define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue
|
#define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue
|
||||||
|
@ -1130,30 +1130,34 @@ m68hc11_initialize_trampoline (tramp, fnaddr, cxt)
|
||||||
|
|
||||||
/* Declaration of types. */
|
/* Declaration of types. */
|
||||||
|
|
||||||
/* If defined, a C expression whose value is nonzero if IDENTIFIER
|
const struct attribute_spec m68hc11_attribute_table[] =
|
||||||
with arguments ARGS is a valid machine specific attribute for TYPE.
|
|
||||||
The attributes in ATTRIBUTES have previously been assigned to TYPE. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
m68hc11_valid_type_attribute_p (type, attributes, identifier, args)
|
|
||||||
tree type;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree identifier;
|
|
||||||
tree args;
|
|
||||||
{
|
{
|
||||||
if (TREE_CODE (type) != FUNCTION_TYPE
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
&& TREE_CODE (type) != FIELD_DECL && TREE_CODE (type) != TYPE_DECL)
|
{ "interrupt", 0, 0, false, true, true, m68hc11_handle_fntype_attribute },
|
||||||
return 0;
|
{ "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))
|
warning ("`%s' attribute only applies to functions",
|
||||||
return (args == NULL_TREE);
|
IDENTIFIER_POINTER (name));
|
||||||
if (is_attribute_p ("trap", identifier))
|
*no_add_attrs = true;
|
||||||
return (args == NULL_TREE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Define this macro if references to a symbol must be treated
|
/* 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 void mcore_mark_dllimport PARAMS ((tree));
|
||||||
static int mcore_dllexport_p PARAMS ((tree));
|
static int mcore_dllexport_p PARAMS ((tree));
|
||||||
static int mcore_dllimport_p PARAMS ((tree));
|
static int mcore_dllimport_p PARAMS ((tree));
|
||||||
static int mcore_valid_decl_attribute PARAMS ((tree, tree,
|
const struct attribute_spec mcore_attribute_table[];
|
||||||
tree, tree));
|
static tree mcore_handle_naked_attribute PARAMS ((tree *, tree, tree, int, bool *));
|
||||||
static void mcore_asm_named_section PARAMS ((const char *,
|
static void mcore_asm_named_section PARAMS ((const char *,
|
||||||
unsigned int));
|
unsigned int));
|
||||||
|
|
||||||
|
@ -141,8 +141,8 @@ static void mcore_asm_named_section PARAMS ((const char *,
|
||||||
#define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
|
#define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef TARGET_VALID_DECL_ATTRIBUTE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_VALID_DECL_ATTRIBUTE mcore_valid_decl_attribute
|
#define TARGET_ATTRIBUTE_TABLE mcore_attribute_table
|
||||||
|
|
||||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||||
|
|
||||||
|
@ -3387,7 +3387,7 @@ mcore_dllexport_p (decl)
|
||||||
&& TREE_CODE (decl) != FUNCTION_DECL)
|
&& TREE_CODE (decl) != FUNCTION_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl)) != 0;
|
return lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -3398,7 +3398,7 @@ mcore_dllimport_p (decl)
|
||||||
&& TREE_CODE (decl) != FUNCTION_DECL)
|
&& TREE_CODE (decl) != FUNCTION_DECL)
|
||||||
return 0;
|
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. */
|
/* 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
|
dllexport - for exporting a function/variable that will live in a dll
|
||||||
dllimport - for importing a function/variable from a dll
|
dllimport - for importing a function/variable from a dll
|
||||||
naked - do not create a function prologue/epilogue. */
|
naked - do not create a function prologue/epilogue. */
|
||||||
static int
|
|
||||||
mcore_valid_decl_attribute (decl, attributes, attr, args)
|
const struct attribute_spec mcore_attribute_table[] =
|
||||||
tree decl;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree attr;
|
|
||||||
tree args;
|
|
||||||
{
|
{
|
||||||
if (args != NULL_TREE)
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
return 0;
|
{ "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))
|
/* Handle a "naked" attribute; arguments as in
|
||||||
return 1;
|
struct attribute_spec.handler. */
|
||||||
|
static tree
|
||||||
if (is_attribute_p ("dllimport", attr))
|
mcore_handle_naked_attribute (node, name, args, flags, no_add_attrs)
|
||||||
return 1;
|
tree *node;
|
||||||
|
tree name;
|
||||||
if (is_attribute_p ("naked", attr) &&
|
tree args ATTRIBUTE_UNUSED;
|
||||||
TREE_CODE (decl) == FUNCTION_DECL)
|
int flags ATTRIBUTE_UNUSED;
|
||||||
|
bool *no_add_attrs;
|
||||||
|
{
|
||||||
|
if (TREE_CODE (*node) == FUNCTION_DECL)
|
||||||
{
|
{
|
||||||
/* PR14310 - don't complain about lack of return statement
|
/* PR14310 - don't complain about lack of return statement
|
||||||
in naked functions. The solution here is a gross hack
|
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)
|
else if (saved_warn_return_type_count)
|
||||||
saved_warn_return_type_count = 2;
|
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. */
|
/* Cover function for UNIQUE_SECTION. */
|
||||||
|
@ -3530,7 +3537,7 @@ mcore_unique_section (decl, reloc)
|
||||||
int
|
int
|
||||||
mcore_naked_function_p ()
|
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
|
static void
|
||||||
|
|
|
@ -37,6 +37,7 @@ Boston, MA 02111-1307, USA. */
|
||||||
#include "tm_p.h"
|
#include "tm_p.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "target-def.h"
|
#include "target-def.h"
|
||||||
|
#include "toplev.h"
|
||||||
|
|
||||||
#ifdef OSF_OS
|
#ifdef OSF_OS
|
||||||
int ns32k_num_files = 0;
|
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 rtx gen_indexed_expr PARAMS ((rtx, rtx, rtx));
|
||||||
static const char *singlemove_string PARAMS ((rtx *));
|
static const char *singlemove_string PARAMS ((rtx *));
|
||||||
static void move_tail PARAMS ((rtx[], int, int));
|
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_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||||
static void ns32k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
static void ns32k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||||
|
|
||||||
/* Initialize the GCC target structure. */
|
/* Initialize the GCC target structure. */
|
||||||
#undef TARGET_VALID_TYPE_ATTRIBUTE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_VALID_TYPE_ATTRIBUTE ns32k_valid_type_attribute_p
|
#define TARGET_ATTRIBUTE_TABLE ns32k_attribute_table
|
||||||
|
|
||||||
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
||||||
#define TARGET_ASM_FUNCTION_PROLOGUE ns32k_output_function_prologue
|
#define TARGET_ASM_FUNCTION_PROLOGUE ns32k_output_function_prologue
|
||||||
|
@ -1008,32 +1010,39 @@ symbolic_reference_mentioned_p (op)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
|
/* Table of machine-specific attributes. */
|
||||||
attribute for TYPE. The attributes in ATTRIBUTES have previously been
|
|
||||||
assigned to TYPE. */
|
|
||||||
|
|
||||||
static int
|
const struct attribute_spec ns32k_attribute_table[] =
|
||||||
ns32k_valid_type_attribute_p (type, attributes, identifier, args)
|
|
||||||
tree type;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree identifier;
|
|
||||||
tree args;
|
|
||||||
{
|
{
|
||||||
if (TREE_CODE (type) != FUNCTION_TYPE
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
&& TREE_CODE (type) != FIELD_DECL
|
|
||||||
&& TREE_CODE (type) != TYPE_DECL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Stdcall attribute says callee is responsible for popping arguments
|
/* Stdcall attribute says callee is responsible for popping arguments
|
||||||
if they are not variable. */
|
if they are not variable. */
|
||||||
if (is_attribute_p ("stdcall", identifier))
|
{ "stdcall", 0, 0, false, true, true, ns32k_handle_fntype_attribute },
|
||||||
return (args == NULL_TREE);
|
|
||||||
|
|
||||||
/* Cdecl attribute says the callee is a normal C declaration */
|
/* Cdecl attribute says the callee is a normal C declaration */
|
||||||
if (is_attribute_p ("cdecl", identifier))
|
{ "cdecl", 0, 0, false, true, true, ns32k_handle_fntype_attribute },
|
||||||
return (args == NULL_TREE);
|
{ 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_free_machine_status PARAMS ((struct function *));
|
||||||
static void rs6000_init_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_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_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||||
static void rs6000_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
static void rs6000_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||||
static rtx rs6000_emit_set_long_const PARAMS ((rtx,
|
static rtx rs6000_emit_set_long_const PARAMS ((rtx,
|
||||||
|
@ -184,8 +185,8 @@ static char alt_reg_names[][8] =
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Initialize the GCC target structure. */
|
/* Initialize the GCC target structure. */
|
||||||
#undef TARGET_VALID_TYPE_ATTRIBUTE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_VALID_TYPE_ATTRIBUTE rs6000_valid_type_attribute_p
|
#define TARGET_ATTRIBUTE_TABLE rs6000_attribute_table
|
||||||
|
|
||||||
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
||||||
#define TARGET_ASM_FUNCTION_PROLOGUE rs6000_output_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
|
/* Table of valid machine attributes. */
|
||||||
with arguments ARGS is a valid machine specific attribute for TYPE.
|
const struct attribute_spec rs6000_attribute_table[] =
|
||||||
The attributes in ATTRIBUTES have previously been assigned to TYPE. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
rs6000_valid_type_attribute_p (type, attributes, identifier, args)
|
|
||||||
tree type;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree identifier;
|
|
||||||
tree args;
|
|
||||||
{
|
{
|
||||||
if (TREE_CODE (type) != FUNCTION_TYPE
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
&& TREE_CODE (type) != FIELD_DECL
|
{ "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
|
||||||
&& TREE_CODE (type) != TYPE_DECL)
|
{ NULL, 0, 0, false, false, false, NULL }
|
||||||
return 0;
|
};
|
||||||
|
|
||||||
/* Longcall attribute says that the function is not within 2**26 bytes
|
/* Handle a "longcall" attribute;
|
||||||
of the current function, and to do an indirect call. */
|
arguments as in struct attribute_spec.handler. */
|
||||||
if (is_attribute_p ("longcall", identifier))
|
static tree
|
||||||
return (args == NULL_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
|
/* 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 void mark_use PARAMS ((rtx, rtx *));
|
||||||
static HOST_WIDE_INT rounded_frame_size PARAMS ((int));
|
static HOST_WIDE_INT rounded_frame_size PARAMS ((int));
|
||||||
static rtx mark_constant_pool_use PARAMS ((rtx));
|
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_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||||
static void sh_insert_attributes PARAMS ((tree, tree *));
|
static void sh_insert_attributes PARAMS ((tree, tree *));
|
||||||
static void sh_asm_named_section PARAMS ((const char *, unsigned int));
|
static void sh_asm_named_section PARAMS ((const char *, unsigned int));
|
||||||
static int sh_adjust_cost PARAMS ((rtx, rtx, rtx, int));
|
static int sh_adjust_cost PARAMS ((rtx, rtx, rtx, int));
|
||||||
|
|
||||||
/* Initialize the GCC target structure. */
|
/* Initialize the GCC target structure. */
|
||||||
#undef TARGET_VALID_DECL_ATTRIBUTE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_VALID_DECL_ATTRIBUTE sh_valid_decl_attribute
|
#define TARGET_ATTRIBUTE_TABLE sh_attribute_table
|
||||||
|
|
||||||
#undef TARGET_ASM_FUNCTION_EPILOGUE
|
#undef TARGET_ASM_FUNCTION_EPILOGUE
|
||||||
#define TARGET_ASM_FUNCTION_EPILOGUE sh_output_function_epilogue
|
#define TARGET_ASM_FUNCTION_EPILOGUE sh_output_function_epilogue
|
||||||
|
@ -269,7 +272,7 @@ print_operand (stream, x, code)
|
||||||
|
|
||||||
if ((lookup_attribute
|
if ((lookup_attribute
|
||||||
("interrupt_handler",
|
("interrupt_handler",
|
||||||
DECL_MACHINE_ATTRIBUTES (current_function_decl)))
|
DECL_ATTRIBUTES (current_function_decl)))
|
||||||
!= NULL_TREE)
|
!= NULL_TREE)
|
||||||
interrupt_handler = 1;
|
interrupt_handler = 1;
|
||||||
else
|
else
|
||||||
|
@ -3964,7 +3967,7 @@ calc_live_regs (count_ptr, live_regs_mask2)
|
||||||
|
|
||||||
if ((lookup_attribute
|
if ((lookup_attribute
|
||||||
("interrupt_handler",
|
("interrupt_handler",
|
||||||
DECL_MACHINE_ATTRIBUTES (current_function_decl)))
|
DECL_ATTRIBUTES (current_function_decl)))
|
||||||
!= NULL_TREE)
|
!= NULL_TREE)
|
||||||
interrupt_handler = 1;
|
interrupt_handler = 1;
|
||||||
else
|
else
|
||||||
|
@ -4058,7 +4061,7 @@ sh_expand_prologue ()
|
||||||
|
|
||||||
current_function_interrupt
|
current_function_interrupt
|
||||||
= lookup_attribute ("interrupt_handler",
|
= lookup_attribute ("interrupt_handler",
|
||||||
DECL_MACHINE_ATTRIBUTES (current_function_decl))
|
DECL_ATTRIBUTES (current_function_decl))
|
||||||
!= NULL_TREE;
|
!= NULL_TREE;
|
||||||
|
|
||||||
/* We have pretend args if we had an object sent partially in registers
|
/* We have pretend args if we had an object sent partially in registers
|
||||||
|
@ -4656,11 +4659,7 @@ sh_insert_attributes (node, attributes)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return nonzero if ATTR is a valid attribute for DECL.
|
/* Supported attributes:
|
||||||
ATTRIBUTES are any existing attributes and ARGS are the arguments
|
|
||||||
supplied with ATTR.
|
|
||||||
|
|
||||||
Supported attributes:
|
|
||||||
|
|
||||||
interrupt_handler -- specifies this function is an interrupt handler.
|
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
|
trap_exit -- use a trapa to exit an interrupt function instead of
|
||||||
an rte instruction. */
|
an rte instruction. */
|
||||||
|
|
||||||
static int
|
const struct attribute_spec sh_attribute_table[] =
|
||||||
sh_valid_decl_attribute (decl, attributes, attr, args)
|
|
||||||
tree decl;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree attr;
|
|
||||||
tree args;
|
|
||||||
{
|
{
|
||||||
if (TREE_CODE (decl) != FUNCTION_DECL)
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
return 0;
|
{ "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. */
|
/* The sp_switch attribute only has meaning for interrupt functions. */
|
||||||
if (!pragma_interrupt)
|
warning ("`%s' attribute only applies to interrupt functions",
|
||||||
return 0;
|
IDENTIFIER_POINTER (name));
|
||||||
|
*no_add_attrs = true;
|
||||||
/* sp_switch must have an argument. */
|
}
|
||||||
if (!args || TREE_CODE (args) != TREE_LIST)
|
else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
|
||||||
return 0;
|
{
|
||||||
|
|
||||||
/* The argument must be a constant string. */
|
/* The argument must be a constant string. */
|
||||||
if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
|
warning ("`%s' attribute argument not a string constant",
|
||||||
return 0;
|
IDENTIFIER_POINTER (name));
|
||||||
|
*no_add_attrs = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
sp_switch = gen_rtx_SYMBOL_REF (VOIDmode,
|
sp_switch = gen_rtx_SYMBOL_REF (VOIDmode,
|
||||||
TREE_STRING_POINTER (TREE_VALUE (args)));
|
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. */
|
/* The trap_exit attribute only has meaning for interrupt functions. */
|
||||||
if (!pragma_interrupt)
|
warning ("`%s' attribute only applies to interrupt functions",
|
||||||
return 0;
|
IDENTIFIER_POINTER (name));
|
||||||
|
*no_add_attrs = true;
|
||||||
/* trap_exit must have an argument. */
|
}
|
||||||
if (!args || TREE_CODE (args) != TREE_LIST)
|
else if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
|
||||||
return 0;
|
{
|
||||||
|
|
||||||
/* The argument must be a constant integer. */
|
/* The argument must be a constant integer. */
|
||||||
if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
|
warning ("`%s' attribute argument not an integer constant",
|
||||||
return 0;
|
IDENTIFIER_POINTER (name));
|
||||||
|
*no_add_attrs = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
trap_exit = TREE_INT_CST_LOW (TREE_VALUE (args));
|
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;
|
return lookup_attribute ("interrupt", attributes) != NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If defined, a C function which returns nonzero if IDENTIFIER
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
with arguments ARGS is a valid machine specific attribute for TYPE.
|
#define TARGET_ATTRIBUTE_TABLE stormy16_attribute_table
|
||||||
The attributes in ATTRIBUTES have previously been assigned to TYPE. */
|
static tree stormy16_handle_interrupt_attribute PARAMS ((tree *, tree, tree, int, bool *));
|
||||||
#undef TARGET_VALID_TYPE_ATTRIBUTE
|
static const struct attribute_spec stormy16_attribute_table[] =
|
||||||
#define TARGET_VALID_TYPE_ATTRIBUTE stormy16_valid_type_attribute
|
|
||||||
static int stormy16_valid_type_attribute PARAMS ((tree TYPE,
|
|
||||||
tree ATTRIBUTES,
|
|
||||||
tree IDENTIFIER,
|
|
||||||
tree ARGS));
|
|
||||||
|
|
||||||
static int
|
|
||||||
stormy16_valid_type_attribute (type, attributes, identifier, args)
|
|
||||||
tree type;
|
|
||||||
tree attributes ATTRIBUTE_UNUSED;
|
|
||||||
tree identifier;
|
|
||||||
tree args ATTRIBUTE_UNUSED;
|
|
||||||
{
|
{
|
||||||
if (TREE_CODE (type) != FUNCTION_TYPE)
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
return 0;
|
{ "interrupt", 0, 0, false, true, true, stormy16_handle_interrupt_attribute },
|
||||||
|
{ NULL, 0, 0, false, false, false, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
if (is_attribute_p ("interrupt", identifier))
|
/* Handle an "interrupt" attribute;
|
||||||
return 1;
|
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 0;
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
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
|
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
|
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
|
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
|
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
|
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 pop_data_area PARAMS ((v850_data_area));
|
||||||
static int push_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. */
|
/* 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. */
|
/* Set the machine specific 'interrupt' attribute on the current function. */
|
||||||
|
|
||||||
static int
|
static void
|
||||||
mark_current_function_as_interrupt ()
|
mark_current_function_as_interrupt ()
|
||||||
{
|
{
|
||||||
tree name;
|
tree name;
|
||||||
|
@ -104,8 +104,8 @@ mark_current_function_as_interrupt ()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return valid_machine_attribute
|
decl_attributes (¤t_function_decl,
|
||||||
(name, NULL_TREE, current_function_decl, NULL_TREE);
|
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 void substitute_ep_register PARAMS ((rtx, rtx, int, int, rtx *, rtx *));
|
||||||
static int ep_memory_offset PARAMS ((enum machine_mode, int));
|
static int ep_memory_offset PARAMS ((enum machine_mode, int));
|
||||||
static void v850_set_data_area PARAMS ((tree, v850_data_area));
|
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 *));
|
static void v850_insert_attributes PARAMS ((tree, tree *));
|
||||||
|
|
||||||
/* True if the current function has anonymous arguments. */
|
/* 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;
|
static int v850_interrupt_p = FALSE;
|
||||||
|
|
||||||
/* Initialize the GCC target structure. */
|
/* Initialize the GCC target structure. */
|
||||||
#undef TARGET_VALID_DECL_ATTRIBUTE
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_VALID_DECL_ATTRIBUTE v850_valid_decl_attribute
|
#define TARGET_ATTRIBUTE_TABLE v850_attribute_table
|
||||||
|
|
||||||
#undef TARGET_INSERT_ATTRIBUTES
|
#undef TARGET_INSERT_ATTRIBUTES
|
||||||
#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes
|
#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes
|
||||||
|
@ -1978,13 +1980,13 @@ v850_data_area
|
||||||
v850_get_data_area (decl)
|
v850_get_data_area (decl)
|
||||||
tree 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;
|
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;
|
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_ZDA;
|
||||||
|
|
||||||
return DATA_AREA_NORMAL;
|
return DATA_AREA_NORMAL;
|
||||||
|
@ -2008,62 +2010,92 @@ v850_set_data_area (decl, data_area)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DECL_MACHINE_ATTRIBUTES (decl) = tree_cons
|
DECL_ATTRIBUTES (decl) = tree_cons
|
||||||
(name, NULL, DECL_MACHINE_ATTRIBUTES (decl));
|
(name, NULL, DECL_ATTRIBUTES (decl));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return nonzero if ATTR is a valid attribute for DECL.
|
const struct attribute_spec v850_attribute_table[] =
|
||||||
ARGS are the arguments supplied with ATTR. */
|
{
|
||||||
|
/* { 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
|
/* Handle an "interrupt" attribute; arguments as in
|
||||||
v850_valid_decl_attribute (decl, unused, attr, args)
|
struct attribute_spec.handler. */
|
||||||
tree decl;
|
static tree
|
||||||
tree unused ATTRIBUTE_UNUSED;
|
v850_handle_interrupt_attribute (node, name, args, flags, no_add_attrs)
|
||||||
tree attr;
|
tree *node;
|
||||||
tree args;
|
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 data_area;
|
||||||
v850_data_area area;
|
v850_data_area area;
|
||||||
|
tree decl = *node;
|
||||||
if (args != NULL_TREE)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (is_attribute_p ("interrupt_handler", attr)
|
|
||||||
|| is_attribute_p ("interrupt", attr))
|
|
||||||
return TREE_CODE (decl) == FUNCTION_DECL;
|
|
||||||
|
|
||||||
/* Implement data area attribute. */
|
/* Implement data area attribute. */
|
||||||
if (is_attribute_p ("sda", attr))
|
if (is_attribute_p ("sda", name))
|
||||||
data_area = DATA_AREA_SDA;
|
data_area = DATA_AREA_SDA;
|
||||||
else if (is_attribute_p ("tda", attr))
|
else if (is_attribute_p ("tda", name))
|
||||||
data_area = DATA_AREA_TDA;
|
data_area = DATA_AREA_TDA;
|
||||||
else if (is_attribute_p ("zda", attr))
|
else if (is_attribute_p ("zda", name))
|
||||||
data_area = DATA_AREA_ZDA;
|
data_area = DATA_AREA_ZDA;
|
||||||
else
|
else
|
||||||
return 0;
|
abort ();
|
||||||
|
|
||||||
switch (TREE_CODE (decl))
|
switch (TREE_CODE (decl))
|
||||||
{
|
{
|
||||||
case VAR_DECL:
|
case VAR_DECL:
|
||||||
if (current_function_decl != NULL_TREE)
|
if (current_function_decl != NULL_TREE)
|
||||||
error_with_decl (decl, "\
|
{
|
||||||
|
error_with_decl (decl, "\
|
||||||
a data area attribute cannot be specified for local variables");
|
a data area attribute cannot be specified for local variables");
|
||||||
|
*no_add_attrs = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Drop through. */
|
/* Drop through. */
|
||||||
|
|
||||||
case FUNCTION_DECL:
|
case FUNCTION_DECL:
|
||||||
area = v850_get_data_area (decl);
|
area = v850_get_data_area (decl);
|
||||||
if (area != DATA_AREA_NORMAL && data_area != area)
|
if (area != DATA_AREA_NORMAL && data_area != area)
|
||||||
error_with_decl (decl, "\
|
{
|
||||||
|
error_with_decl (decl, "\
|
||||||
data area of '%s' conflicts with previous declaration");
|
data area of '%s' conflicts with previous declaration");
|
||||||
|
*no_add_attrs = true;
|
||||||
return 1;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2083,13 +2115,13 @@ v850_interrupt_function_p (func)
|
||||||
if (TREE_CODE (func) != FUNCTION_DECL)
|
if (TREE_CODE (func) != FUNCTION_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
a = lookup_attribute ("interrupt_handler", DECL_MACHINE_ATTRIBUTES (func));
|
a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
|
||||||
if (a != NULL_TREE)
|
if (a != NULL_TREE)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));
|
a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
|
||||||
ret = a != NULL_TREE;
|
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>
|
2001-09-15 Gabriel Dos Reis <gdr@merlin.codesourcery.com>
|
||||||
|
|
||||||
* Make-lang.in (cp/error.o): Depend on real.h
|
* Make-lang.in (cp/error.o): Depend on real.h
|
||||||
|
|
|
@ -5293,7 +5293,7 @@ finish_struct (t, attributes)
|
||||||
as necessary. */
|
as necessary. */
|
||||||
unreverse_member_declarations (t);
|
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
|
/* Nadger the current location so that diagnostics point to the start of
|
||||||
the struct, not the end. */
|
the struct, not the end. */
|
||||||
|
|
|
@ -3734,7 +3734,7 @@ extern tree grokbitfield PARAMS ((tree, tree, tree));
|
||||||
extern tree groktypefield PARAMS ((tree, tree));
|
extern tree groktypefield PARAMS ((tree, tree));
|
||||||
extern tree grokoptypename PARAMS ((tree, tree));
|
extern tree grokoptypename PARAMS ((tree, tree));
|
||||||
extern int copy_assignment_arg_p PARAMS ((tree, int));
|
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_full PARAMS ((tree));
|
||||||
extern tree constructor_name PARAMS ((tree));
|
extern tree constructor_name PARAMS ((tree));
|
||||||
extern void defer_fn PARAMS ((tree));
|
extern void defer_fn PARAMS ((tree));
|
||||||
|
@ -4208,7 +4208,7 @@ extern tree walk_tree_without_duplicates PARAMS ((tree *,
|
||||||
walk_tree_fn,
|
walk_tree_fn,
|
||||||
void *));
|
void *));
|
||||||
extern tree copy_tree_r PARAMS ((tree *, int *, 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 make_ptrmem_cst PARAMS ((tree, tree));
|
||||||
extern tree cp_build_qualified_type_real PARAMS ((tree, int, int));
|
extern tree cp_build_qualified_type_real PARAMS ((tree, int, int));
|
||||||
extern void remap_save_expr PARAMS ((tree *, splay_tree, tree, 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 "tm_p.h"
|
||||||
#include "target.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
|
#ifndef BOOL_TYPE_SIZE
|
||||||
/* `bool' has size and alignment `1', on all platforms. */
|
/* `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
|
/* Copy all the DECL_... slots specified in the new decl
|
||||||
except for any that we copy here from the old type. */
|
except for any that we copy here from the old type. */
|
||||||
DECL_MACHINE_ATTRIBUTES (newdecl)
|
DECL_ATTRIBUTES (newdecl)
|
||||||
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
|
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
|
||||||
|
|
||||||
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
|
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
|
||||||
|
@ -3746,7 +3746,7 @@ duplicate_decls (newdecl, olddecl)
|
||||||
|
|
||||||
/* NEWDECL contains the merged attribute lists.
|
/* NEWDECL contains the merged attribute lists.
|
||||||
Update OLDDECL to be the same. */
|
Update OLDDECL to be the same. */
|
||||||
DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
|
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -6493,7 +6493,7 @@ init_decl_processing ()
|
||||||
/* Show we use EH for cleanups. */
|
/* Show we use EH for cleanups. */
|
||||||
using_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
|
/* Maintain consistency. Perhaps we should just complain if they
|
||||||
say -fwritable-strings? */
|
say -fwritable-strings? */
|
||||||
|
@ -6986,7 +6986,7 @@ shadow_tag (declspecs)
|
||||||
if (TYPE_FIELDS (t))
|
if (TYPE_FIELDS (t))
|
||||||
{
|
{
|
||||||
tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
|
tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
|
||||||
NULL_TREE);
|
NULL);
|
||||||
finish_anon_union (decl);
|
finish_anon_union (decl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7002,7 +7002,7 @@ groktypename (typename)
|
||||||
return typename;
|
return typename;
|
||||||
return grokdeclarator (TREE_VALUE (typename),
|
return grokdeclarator (TREE_VALUE (typename),
|
||||||
TREE_PURPOSE (typename),
|
TREE_PURPOSE (typename),
|
||||||
TYPENAME, 0, NULL_TREE);
|
TYPENAME, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decode a declarator in an ordinary declaration or data definition.
|
/* Decode a declarator in an ordinary declaration or data definition.
|
||||||
|
@ -7031,7 +7031,6 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
|
||||||
tree context;
|
tree context;
|
||||||
extern int have_extern_spec;
|
extern int have_extern_spec;
|
||||||
extern int used_extern_spec;
|
extern int used_extern_spec;
|
||||||
tree attrlist;
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* See code below that used this. */
|
/* See code below that used this. */
|
||||||
|
@ -7046,13 +7045,10 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
|
||||||
used_extern_spec = 1;
|
used_extern_spec = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributes || prefix_attributes)
|
attributes = chainon (attributes, prefix_attributes);
|
||||||
attrlist = build_tree_list (attributes, prefix_attributes);
|
|
||||||
else
|
|
||||||
attrlist = NULL_TREE;
|
|
||||||
|
|
||||||
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
|
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
|
||||||
attrlist);
|
&attributes);
|
||||||
|
|
||||||
if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
|
if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
|
||||||
return NULL_TREE;
|
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. */
|
/* 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)))
|
if (context && COMPLETE_TYPE_P (complete_type (context)))
|
||||||
{
|
{
|
||||||
|
@ -8482,7 +8478,7 @@ start_handler_parms (declspecs, declarator)
|
||||||
if (declspecs)
|
if (declspecs)
|
||||||
{
|
{
|
||||||
decl = grokdeclarator (declarator, declspecs, CATCHPARM,
|
decl = grokdeclarator (declarator, declspecs, CATCHPARM,
|
||||||
1, NULL_TREE);
|
1, NULL);
|
||||||
if (decl == NULL_TREE)
|
if (decl == NULL_TREE)
|
||||||
error ("invalid catch parameter");
|
error ("invalid catch parameter");
|
||||||
}
|
}
|
||||||
|
@ -9425,8 +9421,9 @@ check_special_function_return_type (sfk, type, optype)
|
||||||
BITFIELD for a field with specified width.
|
BITFIELD for a field with specified width.
|
||||||
INITIALIZED is 1 if the decl has an initializer.
|
INITIALIZED is 1 if the decl has an initializer.
|
||||||
|
|
||||||
ATTRLIST is a TREE_LIST node with prefix attributes in TREE_VALUE and
|
ATTRLIST is a pointer to the list of attributes, which may be NULL
|
||||||
normal attributes in TREE_PURPOSE, or NULL_TREE.
|
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.
|
In the TYPENAME case, DECLARATOR is really an abstract declarator.
|
||||||
It may also be so in the PARM case, for a prototype where the
|
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;
|
tree declarator;
|
||||||
enum decl_context decl_context;
|
enum decl_context decl_context;
|
||||||
int initialized;
|
int initialized;
|
||||||
tree attrlist;
|
tree *attrlist;
|
||||||
{
|
{
|
||||||
RID_BIT_TYPE specbits;
|
RID_BIT_TYPE specbits;
|
||||||
int nclasses = 0;
|
int nclasses = 0;
|
||||||
|
@ -9487,7 +9484,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
||||||
int bitfield = 0;
|
int bitfield = 0;
|
||||||
#if 0
|
#if 0
|
||||||
/* See the code below that used this. */
|
/* See the code below that used this. */
|
||||||
tree decl_machine_attr = NULL_TREE;
|
tree decl_attr = NULL_TREE;
|
||||||
#endif
|
#endif
|
||||||
/* Set this to error_mark_node for FIELD_DECLs we could not handle properly.
|
/* 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. */
|
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;
|
tree raises = NULL_TREE;
|
||||||
int template_count = 0;
|
int template_count = 0;
|
||||||
tree in_namespace = NULL_TREE;
|
tree in_namespace = NULL_TREE;
|
||||||
tree inner_attrs;
|
tree returned_attrs = NULL_TREE;
|
||||||
int ignore_attrs;
|
|
||||||
|
|
||||||
RIDBIT_RESET_ALL (specbits);
|
RIDBIT_RESET_ALL (specbits);
|
||||||
if (decl_context == FUNCDEF)
|
if (decl_context == FUNCDEF)
|
||||||
|
@ -9598,24 +9594,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
||||||
cp_finish_decl so we can get the variable
|
cp_finish_decl so we can get the variable
|
||||||
initialized... */
|
initialized... */
|
||||||
|
|
||||||
tree attributes, prefix_attributes;
|
tree attributes;
|
||||||
|
|
||||||
*next = TREE_OPERAND (decl, 0);
|
*next = TREE_OPERAND (decl, 0);
|
||||||
init = CALL_DECLARATOR_PARMS (decl);
|
init = CALL_DECLARATOR_PARMS (decl);
|
||||||
|
|
||||||
if (attrlist)
|
if (attrlist)
|
||||||
{
|
{
|
||||||
attributes = TREE_PURPOSE (attrlist);
|
attributes = *attrlist;
|
||||||
prefix_attributes = TREE_VALUE (attrlist);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
attributes = NULL_TREE;
|
attributes = NULL_TREE;
|
||||||
prefix_attributes = NULL_TREE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
decl = start_decl (declarator, declspecs, 1,
|
decl = start_decl (declarator, declspecs, 1,
|
||||||
attributes, prefix_attributes);
|
attributes, NULL_TREE);
|
||||||
decl_type_access_control (decl);
|
decl_type_access_control (decl);
|
||||||
if (decl)
|
if (decl)
|
||||||
{
|
{
|
||||||
|
@ -9953,7 +9947,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
||||||
type = TREE_TYPE (t);
|
type = TREE_TYPE (t);
|
||||||
#if 0
|
#if 0
|
||||||
/* See the code below that used this. */
|
/* See the code below that used this. */
|
||||||
decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
|
decl_attr = DECL_ATTRIBUTES (id);
|
||||||
#endif
|
#endif
|
||||||
typedef_decl = t;
|
typedef_decl = t;
|
||||||
}
|
}
|
||||||
|
@ -10312,9 +10306,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
||||||
Descend through it, creating more complex types, until we reach
|
Descend through it, creating more complex types, until we reach
|
||||||
the declared identifier (or NULL_TREE, in an absolute declarator). */
|
the declared identifier (or NULL_TREE, in an absolute declarator). */
|
||||||
|
|
||||||
inner_attrs = NULL_TREE;
|
|
||||||
ignore_attrs = 0;
|
|
||||||
|
|
||||||
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
|
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
|
||||||
&& TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
|
&& 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))
|
switch (TREE_CODE (declarator))
|
||||||
{
|
{
|
||||||
case TREE_LIST:
|
case TREE_LIST:
|
||||||
{
|
{
|
||||||
/* We encode a declarator with embedded attributes using
|
/* We encode a declarator with embedded attributes using
|
||||||
a TREE_LIST. The attributes apply to the declarator
|
a TREE_LIST. */
|
||||||
directly inside them, so we have to skip an iteration
|
tree attrs = TREE_PURPOSE (declarator);
|
||||||
before applying them to the type. If the declarator just
|
tree inner_decl;
|
||||||
inside is the declarator-id, we apply the attrs to the
|
|
||||||
decl itself. */
|
|
||||||
inner_attrs = TREE_PURPOSE (declarator);
|
|
||||||
ignore_attrs = 1;
|
|
||||||
declarator = TREE_VALUE (declarator);
|
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;
|
break;
|
||||||
|
|
||||||
|
@ -10883,15 +10876,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See the comment for the TREE_LIST case, above. */
|
if (returned_attrs)
|
||||||
if (inner_attrs)
|
|
||||||
{
|
{
|
||||||
if (! ignore_attrs)
|
if (attrlist)
|
||||||
decl_attributes (&type, inner_attrs, 0);
|
*attrlist = chainon (returned_attrs, *attrlist);
|
||||||
else if (attrlist)
|
|
||||||
TREE_VALUE (attrlist) = chainon (inner_attrs, TREE_VALUE (attrlist));
|
|
||||||
else
|
else
|
||||||
attrlist = build_tree_list (NULL_TREE, inner_attrs);
|
attrlist = &returned_attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now TYPE has the actual type. */
|
/* Now TYPE has the actual type. */
|
||||||
|
@ -11302,8 +11292,8 @@ friend declaration requires class-key, i.e. `friend %#T'",
|
||||||
return decl;
|
return decl;
|
||||||
#if 0
|
#if 0
|
||||||
/* This clobbers the attrs stored in `decl' from `attrlist'. */
|
/* This clobbers the attrs stored in `decl' from `attrlist'. */
|
||||||
/* The decl and setting of decl_machine_attr is also turned off. */
|
/* The decl and setting of decl_attr is also turned off. */
|
||||||
decl = build_decl_attribute_variant (decl, decl_machine_attr);
|
decl = build_decl_attribute_variant (decl, decl_attr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* [class.conv.ctor]
|
/* [class.conv.ctor]
|
||||||
|
@ -11401,7 +11391,7 @@ friend declaration requires class-key, i.e. `friend %#T'",
|
||||||
}
|
}
|
||||||
|
|
||||||
t = do_friend (ctype, declarator, decl,
|
t = do_friend (ctype, declarator, decl,
|
||||||
last_function_parms, attrlist, flags, quals,
|
last_function_parms, *attrlist, flags, quals,
|
||||||
funcdef_flag);
|
funcdef_flag);
|
||||||
}
|
}
|
||||||
if (t && funcdef_flag)
|
if (t && funcdef_flag)
|
||||||
|
@ -11838,7 +11828,7 @@ grokparms (first_parm)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
decl = grokdeclarator (TREE_VALUE (decl), TREE_PURPOSE (decl),
|
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)
|
if (! decl || TREE_TYPE (decl) == error_mark_node)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -13269,7 +13259,7 @@ start_function (declspecs, declarator, attrs, flags)
|
||||||
}
|
}
|
||||||
else
|
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,
|
/* If the declarator is not suitable for a function definition,
|
||||||
cause a syntax error. */
|
cause a syntax error. */
|
||||||
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0;
|
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0;
|
||||||
|
@ -13554,7 +13544,7 @@ start_function (declspecs, declarator, attrs, flags)
|
||||||
pushlevel (0);
|
pushlevel (0);
|
||||||
current_binding_level->parm_flag = 1;
|
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. */
|
/* Promote the value to int before returning it. */
|
||||||
if (c_promoting_integer_type_p (restype))
|
if (c_promoting_integer_type_p (restype))
|
||||||
|
@ -14056,7 +14046,7 @@ start_method (declspecs, declarator, attrlist)
|
||||||
tree declarator, declspecs, attrlist;
|
tree declarator, declspecs, attrlist;
|
||||||
{
|
{
|
||||||
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
|
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
|
||||||
attrlist);
|
&attrlist);
|
||||||
|
|
||||||
/* Something too ugly to handle. */
|
/* Something too ugly to handle. */
|
||||||
if (fndecl == NULL_TREE)
|
if (fndecl == NULL_TREE)
|
||||||
|
|
|
@ -31,7 +31,7 @@ enum decl_context
|
||||||
};
|
};
|
||||||
|
|
||||||
/* We need this in here to get the decl_context definition. */
|
/* 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
|
/* Parsing a function declarator leaves a list of parameter names
|
||||||
or a chain or parameter decls here. */
|
or a chain or parameter decls here. */
|
||||||
|
|
|
@ -1531,7 +1531,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
|
||||||
&& TREE_CHAIN (init) == NULL_TREE)
|
&& TREE_CHAIN (init) == NULL_TREE)
|
||||||
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)
|
if (! value || value == error_mark_node)
|
||||||
/* friend or constructor went bad. */
|
/* friend or constructor went bad. */
|
||||||
return value;
|
return value;
|
||||||
|
@ -1628,8 +1628,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
|
||||||
value = push_template_decl (value);
|
value = push_template_decl (value);
|
||||||
|
|
||||||
if (attrlist)
|
if (attrlist)
|
||||||
cplus_decl_attributes (&value, TREE_PURPOSE (attrlist),
|
cplus_decl_attributes (&value, attrlist, 0);
|
||||||
TREE_VALUE (attrlist), 0);
|
|
||||||
|
|
||||||
if (TREE_CODE (value) == VAR_DECL)
|
if (TREE_CODE (value) == VAR_DECL)
|
||||||
{
|
{
|
||||||
|
@ -1679,7 +1678,7 @@ grokbitfield (declarator, declspecs, width)
|
||||||
tree declarator, declspecs, width;
|
tree declarator, declspecs, width;
|
||||||
{
|
{
|
||||||
register tree value = grokdeclarator (declarator, declspecs, BITFIELD,
|
register tree value = grokdeclarator (declarator, declspecs, BITFIELD,
|
||||||
0, NULL_TREE);
|
0, NULL);
|
||||||
|
|
||||||
if (! value) return NULL_TREE; /* friends went bad. */
|
if (! value) return NULL_TREE; /* friends went bad. */
|
||||||
|
|
||||||
|
@ -1735,7 +1734,7 @@ tree
|
||||||
grokoptypename (declspecs, declarator)
|
grokoptypename (declspecs, declarator)
|
||||||
tree 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);
|
return mangle_conv_op_name_for_type (t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1824,8 +1823,8 @@ grok_function_init (decl, init)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cplus_decl_attributes (decl, attributes, prefix_attributes, flags)
|
cplus_decl_attributes (decl, attributes, flags)
|
||||||
tree *decl, attributes, prefix_attributes;
|
tree *decl, attributes;
|
||||||
int flags;
|
int flags;
|
||||||
{
|
{
|
||||||
if (*decl == NULL_TREE || *decl == void_type_node)
|
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)
|
if (TREE_CODE (*decl) == TEMPLATE_DECL)
|
||||||
decl = &DECL_TEMPLATE_RESULT (*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)
|
if (TREE_CODE (*decl) == TYPE_DECL)
|
||||||
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_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))
|
if (CLASSTYPE_INTERFACE_ONLY (ctype))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((*targetm.valid_type_attribute) (ctype,
|
if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype)))
|
||||||
TYPE_ATTRIBUTES (ctype),
|
|
||||||
get_identifier ("dllimport"),
|
|
||||||
NULL_TREE)
|
|
||||||
&& lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype)))
|
|
||||||
import_export = -1;
|
import_export = -1;
|
||||||
else if ((*targetm.valid_type_attribute) (ctype,
|
else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
|
||||||
TYPE_ATTRIBUTES (ctype),
|
|
||||||
get_identifier ("dllexport"),
|
|
||||||
NULL_TREE)
|
|
||||||
&& lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
|
|
||||||
import_export = 1;
|
import_export = 1;
|
||||||
|
|
||||||
/* If we got -fno-implicit-templates, we import template classes that
|
/* 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 funcdef_flag;
|
||||||
{
|
{
|
||||||
int is_friend_template = 0;
|
int is_friend_template = 0;
|
||||||
tree prefix_attributes, attributes;
|
|
||||||
|
|
||||||
/* Every decl that gets here is a friend of something. */
|
/* Every decl that gets here is a friend of something. */
|
||||||
DECL_FRIEND_P (decl) = 1;
|
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
|
handle them in start_decl_1, but since this is a friend decl start_decl_1
|
||||||
never gets to see it. */
|
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. */
|
/* 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;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ parse_field (declarator, attributes, asmspec, init)
|
||||||
tree declarator, attributes, asmspec, init;
|
tree declarator, attributes, asmspec, init;
|
||||||
{
|
{
|
||||||
tree d = grokfield (declarator, current_declspecs, init, asmspec,
|
tree d = grokfield (declarator, current_declspecs, init, asmspec,
|
||||||
build_tree_list (attributes, prefix_attributes));
|
chainon (attributes, prefix_attributes));
|
||||||
decl_type_access_control (d);
|
decl_type_access_control (d);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ parse_bitfield (declarator, attributes, width)
|
||||||
tree declarator, attributes, width;
|
tree declarator, attributes, width;
|
||||||
{
|
{
|
||||||
tree d = grokbitfield (declarator, current_declspecs, 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);
|
decl_type_access_control (d);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
@ -2639,11 +2639,9 @@ component_decl_1:
|
||||||
$$ = NULL_TREE;
|
$$ = NULL_TREE;
|
||||||
}
|
}
|
||||||
| notype_declarator maybeasm maybe_attribute maybe_init
|
| notype_declarator maybeasm maybe_attribute maybe_init
|
||||||
{ $$ = grokfield ($$, NULL_TREE, $4, $2,
|
{ $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
|
||||||
build_tree_list ($3, NULL_TREE)); }
|
|
||||||
| constructor_declarator maybeasm maybe_attribute maybe_init
|
| constructor_declarator maybeasm maybe_attribute maybe_init
|
||||||
{ $$ = grokfield ($$, NULL_TREE, $4, $2,
|
{ $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
|
||||||
build_tree_list ($3, NULL_TREE)); }
|
|
||||||
| ':' expr_no_commas
|
| ':' expr_no_commas
|
||||||
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
|
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
|
||||||
| error
|
| error
|
||||||
|
@ -2661,10 +2659,9 @@ component_decl_1:
|
||||||
{ tree specs, attrs;
|
{ tree specs, attrs;
|
||||||
split_specs_attrs ($1.t, &specs, &attrs);
|
split_specs_attrs ($1.t, &specs, &attrs);
|
||||||
$$ = grokfield ($2, specs, $5, $3,
|
$$ = grokfield ($2, specs, $5, $3,
|
||||||
build_tree_list ($4, attrs)); }
|
chainon ($4, attrs)); }
|
||||||
| component_constructor_declarator maybeasm maybe_attribute maybe_init
|
| component_constructor_declarator maybeasm maybe_attribute maybe_init
|
||||||
{ $$ = grokfield ($$, NULL_TREE, $4, $2,
|
{ $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
|
||||||
build_tree_list ($3, NULL_TREE)); }
|
|
||||||
| using_decl
|
| using_decl
|
||||||
{ $$ = do_class_using_decl ($1); }
|
{ $$ = 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);
|
my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
|
||||||
/* is a const-param */
|
/* is a const-param */
|
||||||
parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
|
parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
|
||||||
PARM, 0, NULL_TREE);
|
PARM, 0, NULL);
|
||||||
|
|
||||||
/* [temp.param]
|
/* [temp.param]
|
||||||
|
|
||||||
|
@ -9356,7 +9356,7 @@ void
|
||||||
do_decl_instantiation (declspecs, declarator, storage)
|
do_decl_instantiation (declspecs, declarator, storage)
|
||||||
tree 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;
|
tree result = NULL_TREE;
|
||||||
int extern_p = 0;
|
int extern_p = 0;
|
||||||
|
|
||||||
|
|
233
gcc/cp/tree.c
233
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 *));
|
static tree find_tree_r PARAMS ((tree *, int *, void *));
|
||||||
extern int cp_statement_code_p PARAMS ((enum tree_code));
|
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.
|
/* If REF is an lvalue, returns the kind of lvalue that REF is.
|
||||||
Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
|
Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
|
||||||
non-zero, rvalues of class type are considered lvalues. */
|
non-zero, rvalues of class type are considered lvalues. */
|
||||||
|
@ -2182,108 +2186,145 @@ pod_type_p (t)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a 1 if ATTR_NAME and ATTR_ARGS denote a valid C++-specific
|
/* Table of valid C++ attributes. */
|
||||||
attribute for either declaration DECL or type TYPE and 0 otherwise.
|
const struct attribute_spec cp_attribute_table[] =
|
||||||
Plugged into valid_lang_attribute. */
|
|
||||||
|
|
||||||
int
|
|
||||||
cp_valid_lang_attribute (attr_name, attr_args, decl, type)
|
|
||||||
tree attr_name;
|
|
||||||
tree attr_args ATTRIBUTE_UNUSED;
|
|
||||||
tree decl ATTRIBUTE_UNUSED;
|
|
||||||
tree type ATTRIBUTE_UNUSED;
|
|
||||||
{
|
{
|
||||||
if (is_attribute_p ("java_interface", attr_name))
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
|
{ "java_interface", 0, 0, false, false, false, handle_java_interface_attribute },
|
||||||
|
{ "com_interface", 0, 0, false, false, false, handle_com_interface_attribute },
|
||||||
|
{ "init_priority", 1, 1, true, false, false, handle_init_priority_attribute },
|
||||||
|
{ NULL, 0, 0, false, false, false, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Handle a "java_interface" attribute; arguments as in
|
||||||
|
struct attribute_spec.handler. */
|
||||||
|
static tree
|
||||||
|
handle_java_interface_attribute (node, name, args, flags, no_add_attrs)
|
||||||
|
tree *node;
|
||||||
|
tree name;
|
||||||
|
tree args ATTRIBUTE_UNUSED;
|
||||||
|
int flags;
|
||||||
|
bool *no_add_attrs;
|
||||||
|
{
|
||||||
|
if (DECL_P (*node)
|
||||||
|
|| !CLASS_TYPE_P (*node)
|
||||||
|
|| !TYPE_FOR_JAVA (*node))
|
||||||
{
|
{
|
||||||
if (attr_args != NULL_TREE
|
error ("`%s' attribute can only be applied to Java class definitions",
|
||||||
|| decl != NULL_TREE
|
IDENTIFIER_POINTER (name));
|
||||||
|| ! CLASS_TYPE_P (type)
|
*no_add_attrs = true;
|
||||||
|| ! TYPE_FOR_JAVA (type))
|
return NULL_TREE;
|
||||||
{
|
|
||||||
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))
|
if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
|
||||||
|
*node = build_type_copy (*node);
|
||||||
|
TYPE_JAVA_INTERFACE (*node) = 1;
|
||||||
|
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle a "com_interface" attribute; arguments as in
|
||||||
|
struct attribute_spec.handler. */
|
||||||
|
static tree
|
||||||
|
handle_com_interface_attribute (node, name, args, flags, no_add_attrs)
|
||||||
|
tree *node;
|
||||||
|
tree name;
|
||||||
|
tree args ATTRIBUTE_UNUSED;
|
||||||
|
int flags ATTRIBUTE_UNUSED;
|
||||||
|
bool *no_add_attrs;
|
||||||
|
{
|
||||||
|
static int warned;
|
||||||
|
|
||||||
|
*no_add_attrs = true;
|
||||||
|
|
||||||
|
if (DECL_P (*node)
|
||||||
|
|| !CLASS_TYPE_P (*node)
|
||||||
|
|| *node != TYPE_MAIN_VARIANT (*node))
|
||||||
{
|
{
|
||||||
static int warned;
|
warning ("`%s' attribute can only be applied to class definitions",
|
||||||
if (attr_args != NULL_TREE
|
IDENTIFIER_POINTER (name));
|
||||||
|| decl != NULL_TREE
|
return NULL_TREE;
|
||||||
|| ! CLASS_TYPE_P (type)
|
|
||||||
|| type != TYPE_MAIN_VARIANT (type))
|
|
||||||
{
|
|
||||||
warning ("`com_interface' attribute can only be applied to class definitions");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! warned++)
|
|
||||||
warning ("\
|
|
||||||
`com_interface' is obsolete; g++ vtables are now COM-compatible by default");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (is_attribute_p ("init_priority", attr_name))
|
|
||||||
{
|
|
||||||
tree initp_expr = (attr_args ? TREE_VALUE (attr_args): NULL_TREE);
|
|
||||||
int pri;
|
|
||||||
|
|
||||||
if (initp_expr)
|
|
||||||
STRIP_NOPS (initp_expr);
|
|
||||||
|
|
||||||
if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
|
|
||||||
{
|
|
||||||
error ("requested init_priority is not an integer constant");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pri = TREE_INT_CST_LOW (initp_expr);
|
|
||||||
|
|
||||||
type = strip_array_types (type);
|
|
||||||
|
|
||||||
if (decl == NULL_TREE
|
|
||||||
|| TREE_CODE (decl) != VAR_DECL
|
|
||||||
|| ! TREE_STATIC (decl)
|
|
||||||
|| DECL_EXTERNAL (decl)
|
|
||||||
|| (TREE_CODE (type) != RECORD_TYPE
|
|
||||||
&& TREE_CODE (type) != UNION_TYPE)
|
|
||||||
/* Static objects in functions are initialized the
|
|
||||||
first time control passes through that
|
|
||||||
function. This is not precise enough to pin down an
|
|
||||||
init_priority value, so don't allow it. */
|
|
||||||
|| current_function_decl)
|
|
||||||
{
|
|
||||||
error ("can only use init_priority attribute on file-scope definitions of objects of class type");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pri > MAX_INIT_PRIORITY || pri <= 0)
|
|
||||||
{
|
|
||||||
error ("requested init_priority is out of range");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for init_priorities that are reserved for
|
|
||||||
language and runtime support implementations.*/
|
|
||||||
if (pri <= MAX_RESERVED_INIT_PRIORITY)
|
|
||||||
{
|
|
||||||
warning
|
|
||||||
("requested init_priority is reserved for internal use");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUPPORTS_INIT_PRIORITY)
|
|
||||||
{
|
|
||||||
DECL_INIT_PRIORITY (decl) = pri;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error ("init_priority attribute is not supported on this platform");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
if (!warned++)
|
||||||
|
warning ("`%s' is obsolete; g++ vtables are now COM-compatible by default",
|
||||||
|
IDENTIFIER_POINTER (name));
|
||||||
|
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle an "init_priority" attribute; arguments as in
|
||||||
|
struct attribute_spec.handler. */
|
||||||
|
static tree
|
||||||
|
handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
|
||||||
|
tree *node;
|
||||||
|
tree name;
|
||||||
|
tree args;
|
||||||
|
int flags ATTRIBUTE_UNUSED;
|
||||||
|
bool *no_add_attrs;
|
||||||
|
{
|
||||||
|
tree initp_expr = TREE_VALUE (args);
|
||||||
|
tree decl = *node;
|
||||||
|
tree type = TREE_TYPE (decl);
|
||||||
|
int pri;
|
||||||
|
|
||||||
|
STRIP_NOPS (initp_expr);
|
||||||
|
|
||||||
|
if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
|
||||||
|
{
|
||||||
|
error ("requested init_priority is not an integer constant");
|
||||||
|
*no_add_attrs = true;
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pri = TREE_INT_CST_LOW (initp_expr);
|
||||||
|
|
||||||
|
type = strip_array_types (type);
|
||||||
|
|
||||||
|
if (decl == NULL_TREE
|
||||||
|
|| TREE_CODE (decl) != VAR_DECL
|
||||||
|
|| !TREE_STATIC (decl)
|
||||||
|
|| DECL_EXTERNAL (decl)
|
||||||
|
|| (TREE_CODE (type) != RECORD_TYPE
|
||||||
|
&& TREE_CODE (type) != UNION_TYPE)
|
||||||
|
/* Static objects in functions are initialized the
|
||||||
|
first time control passes through that
|
||||||
|
function. This is not precise enough to pin down an
|
||||||
|
init_priority value, so don't allow it. */
|
||||||
|
|| current_function_decl)
|
||||||
|
{
|
||||||
|
error ("can only use `%s' attribute on file-scope definitions of objects of class type",
|
||||||
|
IDENTIFIER_POINTER (name));
|
||||||
|
*no_add_attrs = true;
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pri > MAX_INIT_PRIORITY || pri <= 0)
|
||||||
|
{
|
||||||
|
error ("requested init_priority is out of range");
|
||||||
|
*no_add_attrs = true;
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for init_priorities that are reserved for
|
||||||
|
language and runtime support implementations.*/
|
||||||
|
if (pri <= MAX_RESERVED_INIT_PRIORITY)
|
||||||
|
{
|
||||||
|
warning
|
||||||
|
("requested init_priority is reserved for internal use");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUPPORTS_INIT_PRIORITY)
|
||||||
|
{
|
||||||
|
DECL_INIT_PRIORITY (decl) = pri;
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error ("`%s' attribute is not supported on this platform",
|
||||||
|
IDENTIFIER_POINTER (name));
|
||||||
|
*no_add_attrs = true;
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a new PTRMEM_CST of the indicated TYPE. The MEMBER is the
|
/* 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.
|
further attributes in the list.
|
||||||
|
|
||||||
Attributes may be attached to declarations and to types; these
|
Attributes may be attached to declarations and to types; these
|
||||||
attributes may be accessed with the following macros. At present only
|
attributes may be accessed with the following macros. All attributes
|
||||||
machine-dependent attributes are stored in this way (other attributes
|
are stored in this way, and many also cause other changes to the
|
||||||
cause changes to the declaration or type or to other internal compiler
|
declaration or type or to other internal compiler data structures.
|
||||||
data structures, but are not themselves stored along with the
|
|
||||||
declaration or type), but in future all attributes may be stored like
|
|
||||||
this.
|
|
||||||
|
|
||||||
@deftypefn {Tree Macro} tree DECL_MACHINE_ATTRIBUTES (tree @var{decl})
|
@deftypefn {Tree Macro} tree DECL_ATTRIBUTES (tree @var{decl})
|
||||||
This macro returns the attributes on the declaration @var{decl}.
|
This macro returns the attributes on the declaration @var{decl}.
|
||||||
@end deftypefn
|
@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
|
infelicities in the grammar for attributes, some forms described here
|
||||||
may not be successfully parsed in all cases.
|
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
|
@xref{Function Attributes}, for details of the semantics of attributes
|
||||||
applying to functions. @xref{Variable Attributes}, for details of the
|
applying to functions. @xref{Variable Attributes}, for details of the
|
||||||
semantics of attributes applying to variables. @xref{Type Attributes},
|
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,
|
Otherwise, an attribute specifier appears as part of a declaration,
|
||||||
counting declarations of unnamed parameters and type names, and relates
|
counting declarations of unnamed parameters and type names, and relates
|
||||||
to that declaration (which may be nested in another declaration, for
|
to that declaration (which may be nested in another declaration, for
|
||||||
example in the case of a parameter declaration). In future, attribute
|
example in the case of a parameter declaration), or to a particular declarator
|
||||||
specifiers in some places may however apply to a particular declarator
|
within a declaration. Where an
|
||||||
within a declaration instead; these cases are noted below. Where an
|
|
||||||
attribute specifier is applied to a parameter declared as a function or
|
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
|
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
|
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
|
An attribute specifier list may appear at the start of a nested
|
||||||
declarator. At present, there are some limitations in this usage: the
|
declarator. At present, there are some limitations in this usage: the
|
||||||
attributes apply to the identifier declared, rather than to a specific
|
attributes correctly apply to the declarator, but for most individual
|
||||||
declarator. When attribute specifiers follow the @code{*} of a pointer
|
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.
|
declarator, they may be mixed with any type qualifiers present.
|
||||||
The following describes intended future
|
The following describes the formal semantics of this syntax. It will make the
|
||||||
semantics which make this syntax more useful only. It will make the
|
|
||||||
most sense if you are familiar with the formal specification of
|
most sense if you are familiar with the formal specification of
|
||||||
declarators in the ISO C standard.
|
declarators in the ISO C standard.
|
||||||
|
|
||||||
|
@ -2642,8 +2649,26 @@ char *__attribute__((aligned(8))) *f;
|
||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
specifies the type ``pointer to 8-byte-aligned pointer to @code{char}''.
|
specifies the type ``pointer to 8-byte-aligned pointer to @code{char}''.
|
||||||
Note again that this describes intended future semantics, not current
|
Note again that this does not work with most attributes; for example,
|
||||||
implementation.
|
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
|
@node Function Prototypes
|
||||||
@section Prototypes and Old-Style Function Definitions
|
@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.
|
* Debugging Info:: Defining the format of debugging output.
|
||||||
* Cross-compilation:: Handling floating point for cross-compilers.
|
* Cross-compilation:: Handling floating point for cross-compilers.
|
||||||
* Mode Switching:: Insertion of mode-switching instructions.
|
* Mode Switching:: Insertion of mode-switching instructions.
|
||||||
|
* Target Attributes:: Defining target-specific uses of @code{__attribute__}.
|
||||||
* Misc:: Everything else.
|
* Misc:: Everything else.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
@ -70,8 +71,8 @@ macros for which the default definition is inappropriate. For example:
|
||||||
|
|
||||||
/* @r{Initialize the GCC target structure.} */
|
/* @r{Initialize the GCC target structure.} */
|
||||||
|
|
||||||
#undef TARGET_VALID_TYPE_ATTRIBUTE
|
#undef TARGET_COMP_TYPE_ATTRIBUTES
|
||||||
#define TARGET_VALID_TYPE_ATTRIBUTE @var{machine}_valid_type_attribute_p
|
#define TARGET_COMP_TYPE_ATTRIBUTES @var{machine}_comp_type_attributes
|
||||||
|
|
||||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||||
@end smallexample
|
@end smallexample
|
||||||
|
@ -2528,7 +2529,7 @@ This describes the stack layout and calling conventions.
|
||||||
* Caller Saves::
|
* Caller Saves::
|
||||||
* Function Entry::
|
* Function Entry::
|
||||||
* Profiling::
|
* Profiling::
|
||||||
* Inlining and Tail Calls::
|
* Tail Calls::
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node Frame Layout
|
@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
|
@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
|
the function in question. Normally it is a node of type
|
||||||
@code{FUNCTION_DECL} that describes the declaration of the function.
|
@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
|
@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
|
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
|
@end table
|
||||||
|
|
||||||
@node Inlining and Tail Calls
|
@node Tail Calls
|
||||||
@subsection Permitting inlining and tail calls
|
@subsection Permitting tail calls
|
||||||
@cindex inlining
|
@cindex tail calls
|
||||||
|
|
||||||
@table @code
|
@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
|
@findex FUNCTION_OK_FOR_SIBCALL
|
||||||
@item FUNCTION_OK_FOR_SIBCALL (@var{decl})
|
@item FUNCTION_OK_FOR_SIBCALL (@var{decl})
|
||||||
A C expression that evaluates to true if it is ok to perform a sibling
|
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.
|
the insn(s) are to be inserted.
|
||||||
@end table
|
@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
|
@node Misc
|
||||||
@section Miscellaneous Parameters
|
@section Miscellaneous Parameters
|
||||||
@cindex parameters, miscellaneous
|
@cindex parameters, miscellaneous
|
||||||
|
@ -8404,7 +8477,7 @@ other compilers for the same target. In general, we discourage
|
||||||
definition of target-specific pragmas for GCC@.
|
definition of target-specific pragmas for GCC@.
|
||||||
|
|
||||||
If the pragma can be implemented by attributes then you should consider
|
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
|
Preprocessor macros that appear on pragma lines are not expanded. All
|
||||||
@samp{#pragma} directives that do not match any registered pragma are
|
@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
|
invocations of this pragma cause the previous values to be stacked, so
|
||||||
that invocations of @samp{#pragma pack(pop)} will return to the previous
|
that invocations of @samp{#pragma pack(pop)} will return to the previous
|
||||||
value.
|
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
|
@findex DOLLARS_IN_IDENTIFIERS
|
||||||
@item DOLLARS_IN_IDENTIFIERS
|
@item DOLLARS_IN_IDENTIFIERS
|
||||||
Define this macro to control use of the character @samp{$} in identifier
|
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_INITIAL (t));
|
||||||
ggc_mark_tree (DECL_ABSTRACT_ORIGIN (t));
|
ggc_mark_tree (DECL_ABSTRACT_ORIGIN (t));
|
||||||
ggc_mark_tree (DECL_SECTION_NAME (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))
|
if (DECL_RTL_SET_P (t))
|
||||||
ggc_mark_rtx (DECL_RTL (t));
|
ggc_mark_rtx (DECL_RTL (t));
|
||||||
ggc_mark_rtx (DECL_LIVE_RANGE_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 "loop.h"
|
||||||
#include "params.h"
|
#include "params.h"
|
||||||
#include "ggc.h"
|
#include "ggc.h"
|
||||||
|
#include "target.h"
|
||||||
|
|
||||||
#include "obstack.h"
|
#include "obstack.h"
|
||||||
#define obstack_chunk_alloc xmalloc
|
#define obstack_chunk_alloc xmalloc
|
||||||
|
@ -63,12 +64,6 @@ extern struct obstack *function_maybepermanent_obstack;
|
||||||
? (1 + (3 * list_length (DECL_ARGUMENTS (DECL))) / 2) \
|
? (1 + (3 * list_length (DECL_ARGUMENTS (DECL))) / 2) \
|
||||||
: (8 * (8 + list_length (DECL_ARGUMENTS (DECL)))))
|
: (8 * (8 + list_length (DECL_ARGUMENTS (DECL)))))
|
||||||
#endif
|
#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. */
|
/* 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_pair *entries;
|
||||||
} initial_value_struct;
|
} 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 void setup_initial_hard_reg_value_integration PARAMS ((struct function *, struct inline_remap *));
|
||||||
|
|
||||||
static rtvec initialize_for_inline PARAMS ((tree));
|
static rtvec initialize_for_inline PARAMS ((tree));
|
||||||
|
@ -130,6 +127,38 @@ get_label_from_map (map, i)
|
||||||
return x;
|
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)
|
/* Zero if the current function (whose FUNCTION_DECL is FNDECL)
|
||||||
is safe and reasonable to integrate into other functions.
|
is safe and reasonable to integrate into other functions.
|
||||||
Nonzero means value is a warning msgid with a single %s
|
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,
|
/* If the function has a target specific attribute attached to it,
|
||||||
then we assume that we should not inline it. This can be overriden
|
then we assume that we should not inline it. This can be overriden
|
||||||
by the target if it defines FUNCTION_ATTRIBUTE_INLINABLE_P. */
|
by the target if it defines TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P. */
|
||||||
if (DECL_MACHINE_ATTRIBUTES (fndecl)
|
if (!function_attribute_inlinable_p (fndecl))
|
||||||
&& ! FUNCTION_ATTRIBUTE_INLINABLE_P (fndecl))
|
|
||||||
return N_("function with target specific attribute(s) cannot be inlined");
|
return N_("function with target specific attribute(s) cannot be inlined");
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Prints out tree in human readable form - GNU C-compiler
|
/* 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.
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GCC.
|
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, "context", DECL_CONTEXT (node), indent + 4);
|
||||||
print_node_brief (file, "machine_attributes",
|
print_node_brief (file, "attributes",
|
||||||
DECL_MACHINE_ATTRIBUTES (node), indent + 4);
|
DECL_ATTRIBUTES (node), indent + 4);
|
||||||
print_node_brief (file, "abstract_origin",
|
print_node_brief (file, "abstract_origin",
|
||||||
DECL_ABSTRACT_ORIGIN (node), indent + 4);
|
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. */
|
/* All in tree.c. */
|
||||||
#define TARGET_MERGE_DECL_ATTRIBUTES merge_decl_attributes
|
#define TARGET_MERGE_DECL_ATTRIBUTES merge_decl_attributes
|
||||||
#define TARGET_MERGE_TYPE_ATTRIBUTES merge_type_attributes
|
#define TARGET_MERGE_TYPE_ATTRIBUTES merge_type_attributes
|
||||||
#define TARGET_VALID_DECL_ATTRIBUTE default_valid_attribute_p
|
#define TARGET_ATTRIBUTE_TABLE default_target_attribute_table
|
||||||
#define TARGET_VALID_TYPE_ATTRIBUTE default_valid_attribute_p
|
|
||||||
#define TARGET_COMP_TYPE_ATTRIBUTES default_comp_type_attributes
|
#define TARGET_COMP_TYPE_ATTRIBUTES default_comp_type_attributes
|
||||||
#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES default_set_default_type_attributes
|
#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES default_set_default_type_attributes
|
||||||
#define TARGET_INSERT_ATTRIBUTES default_insert_attributes
|
#define TARGET_INSERT_ATTRIBUTES default_insert_attributes
|
||||||
|
#define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P default_function_attribute_inlinable_p
|
||||||
|
|
||||||
/* In builtins.c. */
|
/* In builtins.c. */
|
||||||
#define TARGET_INIT_BUILTINS default_init_builtins
|
#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_SCHED, \
|
||||||
TARGET_MERGE_DECL_ATTRIBUTES, \
|
TARGET_MERGE_DECL_ATTRIBUTES, \
|
||||||
TARGET_MERGE_TYPE_ATTRIBUTES, \
|
TARGET_MERGE_TYPE_ATTRIBUTES, \
|
||||||
TARGET_VALID_DECL_ATTRIBUTE, \
|
TARGET_ATTRIBUTE_TABLE, \
|
||||||
TARGET_VALID_TYPE_ATTRIBUTE, \
|
|
||||||
TARGET_COMP_TYPE_ATTRIBUTES, \
|
TARGET_COMP_TYPE_ATTRIBUTES, \
|
||||||
TARGET_SET_DEFAULT_TYPE_ATTRIBUTES, \
|
TARGET_SET_DEFAULT_TYPE_ATTRIBUTES, \
|
||||||
TARGET_INSERT_ATTRIBUTES, \
|
TARGET_INSERT_ATTRIBUTES, \
|
||||||
|
TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P, \
|
||||||
TARGET_INIT_BUILTINS, \
|
TARGET_INIT_BUILTINS, \
|
||||||
TARGET_EXPAND_BUILTIN, \
|
TARGET_EXPAND_BUILTIN, \
|
||||||
TARGET_SECTION_TYPE_FLAGS, \
|
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. */
|
/* Given two types, merge their attributes and return the result. */
|
||||||
tree (* merge_type_attributes) PARAMS ((tree, tree));
|
tree (* merge_type_attributes) PARAMS ((tree, tree));
|
||||||
|
|
||||||
/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine
|
/* Table of machine attributes and functions to handle them. */
|
||||||
specific attribute for DECL. The attributes in ATTRIBUTES have
|
const struct attribute_spec *attribute_table;
|
||||||
previously been assigned to DECL. */
|
|
||||||
int (* valid_decl_attribute) PARAMS ((tree decl, tree attributes,
|
|
||||||
tree identifier, tree args));
|
|
||||||
|
|
||||||
/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine
|
|
||||||
specific attribute for TYPE. The attributes in ATTRIBUTES have
|
|
||||||
previously been assigned to TYPE. */
|
|
||||||
int (* valid_type_attribute) PARAMS ((tree type, tree attributes,
|
|
||||||
tree identifier, tree args));
|
|
||||||
|
|
||||||
/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
|
/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
|
||||||
one if they are compatible and two if they are nearly compatible
|
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. */
|
/* Insert attributes on the newly created DECL. */
|
||||||
void (* insert_attributes) PARAMS ((tree decl, tree *attributes));
|
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. */
|
/* Set up target-specific built-in functions. */
|
||||||
void (* init_builtins) PARAMS ((void));
|
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>
|
2001-09-20 DJ Delorie <dj@redhat.com>
|
||||||
|
|
||||||
* gcc.dg/20000926-1.c: Update expected warning messages.
|
* gcc.dg/20000926-1.c: Update expected warning messages.
|
||||||
|
|
|
@ -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 wfl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a declaration like DDECL except that its DECL_MACHINE_ATTRIBUTE
|
/* Return a declaration like DDECL except that its DECL_ATTRIBUTES
|
||||||
is ATTRIBUTE. */
|
is ATTRIBUTE. */
|
||||||
|
|
||||||
tree
|
tree
|
||||||
build_decl_attribute_variant (ddecl, attribute)
|
build_decl_attribute_variant (ddecl, attribute)
|
||||||
tree ddecl, attribute;
|
tree ddecl, attribute;
|
||||||
{
|
{
|
||||||
DECL_MACHINE_ATTRIBUTES (ddecl) = attribute;
|
DECL_ATTRIBUTES (ddecl) = attribute;
|
||||||
return ddecl;
|
return ddecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2670,19 +2670,6 @@ build_type_attribute_variant (ttype, attribute)
|
||||||
return ttype;
|
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. */
|
/* Default value of targetm.comp_type_attributes that always returns 1. */
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -2710,116 +2697,20 @@ default_insert_attributes (decl, attr_ptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 if ATTR_NAME and ATTR_ARGS is valid for either declaration
|
/* Default value of targetm.attribute_table that is empty. */
|
||||||
DECL or type TYPE and 0 otherwise. Validity is determined the
|
const struct attribute_spec default_target_attribute_table[] =
|
||||||
target functions valid_decl_attribute and valid_machine_attribute. */
|
|
||||||
|
|
||||||
int
|
|
||||||
valid_machine_attribute (attr_name, attr_args, decl, type)
|
|
||||||
tree attr_name;
|
|
||||||
tree attr_args;
|
|
||||||
tree decl;
|
|
||||||
tree type;
|
|
||||||
{
|
{
|
||||||
tree type_attrs;
|
{ NULL, 0, 0, false, false, false, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
if (TREE_CODE (attr_name) != IDENTIFIER_NODE)
|
/* Default value of targetm.function_attribute_inlinable_p that always
|
||||||
abort ();
|
returns false. */
|
||||||
|
bool
|
||||||
if (decl)
|
default_function_attribute_inlinable_p (fndecl)
|
||||||
{
|
tree fndecl ATTRIBUTE_UNUSED;
|
||||||
tree decl_attrs = DECL_MACHINE_ATTRIBUTES (decl);
|
{
|
||||||
|
/* By default, functions with machine attributes cannot be inlined. */
|
||||||
if ((*targetm.valid_decl_attribute) (decl, decl_attrs, attr_name,
|
return false;
|
||||||
attr_args))
|
|
||||||
{
|
|
||||||
tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
|
|
||||||
decl_attrs);
|
|
||||||
|
|
||||||
if (attr != NULL_TREE)
|
|
||||||
{
|
|
||||||
/* Override existing arguments. Declarations are unique
|
|
||||||
so we can modify this in place. */
|
|
||||||
TREE_VALUE (attr) = attr_args;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
decl_attrs = tree_cons (attr_name, attr_args, decl_attrs);
|
|
||||||
decl = build_decl_attribute_variant (decl, decl_attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't apply the attribute to both the decl and the type. */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type_attrs = TYPE_ATTRIBUTES (type);
|
|
||||||
if ((*targetm.valid_type_attribute) (type, type_attrs, attr_name,
|
|
||||||
attr_args))
|
|
||||||
{
|
|
||||||
tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
|
|
||||||
type_attrs);
|
|
||||||
|
|
||||||
if (attr != NULL_TREE)
|
|
||||||
{
|
|
||||||
/* Override existing arguments. ??? This currently
|
|
||||||
works since attribute arguments are not included in
|
|
||||||
`attribute_hash_list'. Something more complicated
|
|
||||||
may be needed in the future. */
|
|
||||||
TREE_VALUE (attr) = attr_args;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* If this is part of a declaration, create a type variant,
|
|
||||||
otherwise, this is part of a type definition, so add it
|
|
||||||
to the base type. */
|
|
||||||
type_attrs = tree_cons (attr_name, attr_args, type_attrs);
|
|
||||||
if (decl != 0)
|
|
||||||
type = build_type_attribute_variant (type, type_attrs);
|
|
||||||
else
|
|
||||||
TYPE_ATTRIBUTES (type) = type_attrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (decl)
|
|
||||||
TREE_TYPE (decl) = type;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* Handle putting a type attribute on pointer-to-function-type
|
|
||||||
by putting the attribute on the function type. */
|
|
||||||
else if (POINTER_TYPE_P (type)
|
|
||||||
&& TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
|
|
||||||
&& (*targetm.valid_type_attribute) (TREE_TYPE (type), type_attrs,
|
|
||||||
attr_name, attr_args))
|
|
||||||
{
|
|
||||||
tree inner_type = TREE_TYPE (type);
|
|
||||||
tree inner_attrs = TYPE_ATTRIBUTES (inner_type);
|
|
||||||
tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
|
|
||||||
type_attrs);
|
|
||||||
|
|
||||||
if (attr != NULL_TREE)
|
|
||||||
TREE_VALUE (attr) = attr_args;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inner_attrs = tree_cons (attr_name, attr_args, inner_attrs);
|
|
||||||
inner_type = build_type_attribute_variant (inner_type,
|
|
||||||
inner_attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (decl)
|
|
||||||
TREE_TYPE (decl) = build_pointer_type (inner_type);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Clear TYPE_POINTER_TO for the old inner type, since
|
|
||||||
`type' won't be pointing to it anymore. */
|
|
||||||
TYPE_POINTER_TO (TREE_TYPE (type)) = NULL_TREE;
|
|
||||||
TREE_TYPE (type) = inner_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return non-zero if IDENT is a valid name for attribute ATTR,
|
/* 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
|
/* 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
|
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
|
tree
|
||||||
lookup_attribute (attr_name, list)
|
lookup_attribute (attr_name, list)
|
||||||
|
@ -2915,19 +2808,29 @@ merge_attributes (a1, a2)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Pick the longest list, and hang on the other list. */
|
/* 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))
|
if (list_length (a1) < list_length (a2))
|
||||||
attributes = a2, a2 = a1;
|
attributes = a2, a2 = a1;
|
||||||
|
|
||||||
for (; a2 != 0; a2 = TREE_CHAIN (a2))
|
for (; a2 != 0; a2 = TREE_CHAIN (a2))
|
||||||
if (lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
|
{
|
||||||
attributes) == NULL_TREE)
|
tree a;
|
||||||
{
|
for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
|
||||||
a1 = copy_node (a2);
|
attributes);
|
||||||
TREE_CHAIN (a1) = attributes;
|
a != NULL_TREE;
|
||||||
attributes = a1;
|
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;
|
return attributes;
|
||||||
|
@ -2951,8 +2854,8 @@ tree
|
||||||
merge_decl_attributes (olddecl, newdecl)
|
merge_decl_attributes (olddecl, newdecl)
|
||||||
tree olddecl, newdecl;
|
tree olddecl, newdecl;
|
||||||
{
|
{
|
||||||
return merge_attributes (DECL_MACHINE_ATTRIBUTES (olddecl),
|
return merge_attributes (DECL_ATTRIBUTES (olddecl),
|
||||||
DECL_MACHINE_ATTRIBUTES (newdecl));
|
DECL_ATTRIBUTES (newdecl));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
||||||
|
@ -2974,8 +2877,8 @@ merge_dllimport_decl_attributes (old, new)
|
||||||
tree a;
|
tree a;
|
||||||
int delete_dllimport_p;
|
int delete_dllimport_p;
|
||||||
|
|
||||||
old = DECL_MACHINE_ATTRIBUTES (old);
|
old = DECL_ATTRIBUTES (old);
|
||||||
new = DECL_MACHINE_ATTRIBUTES (new);
|
new = DECL_ATTRIBUTES (new);
|
||||||
|
|
||||||
/* What we need to do here is remove from `old' dllimport if it doesn't
|
/* 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
|
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))
|
for (; t2 != 0; t2 = TREE_CHAIN (t2))
|
||||||
{
|
{
|
||||||
tree attr
|
tree attr;
|
||||||
= lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
|
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)
|
if (attr == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
79
gcc/tree.h
79
gcc/tree.h
|
@ -1,5 +1,5 @@
|
||||||
/* Front-end tree definitions for GNU compiler.
|
/* 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.
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GCC.
|
This file is part of GCC.
|
||||||
|
@ -1337,9 +1337,8 @@ struct tree_type
|
||||||
type, or NULL_TREE if the given decl has "file scope". */
|
type, or NULL_TREE if the given decl has "file scope". */
|
||||||
#define DECL_CONTEXT(NODE) (DECL_CHECK (NODE)->decl.context)
|
#define DECL_CONTEXT(NODE) (DECL_CHECK (NODE)->decl.context)
|
||||||
#define DECL_FIELD_CONTEXT(NODE) (FIELD_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
|
/* In a DECL this is the field where attributes are stored. */
|
||||||
attributes are store */
|
#define DECL_ATTRIBUTES(NODE) (DECL_CHECK (NODE)->decl.attributes)
|
||||||
#define DECL_MACHINE_ATTRIBUTES(NODE) (DECL_CHECK (NODE)->decl.machine_attributes)
|
|
||||||
/* In a FIELD_DECL, this is the field position, counting in bytes, of the
|
/* 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. */
|
byte containing the bit closest to the beginning of the structure. */
|
||||||
#define DECL_FIELD_OFFSET(NODE) (FIELD_DECL_CHECK (NODE)->decl.arguments)
|
#define DECL_FIELD_OFFSET(NODE) (FIELD_DECL_CHECK (NODE)->decl.arguments)
|
||||||
|
@ -1754,7 +1753,7 @@ struct tree_decl
|
||||||
tree abstract_origin;
|
tree abstract_origin;
|
||||||
tree assembler_name;
|
tree assembler_name;
|
||||||
tree section_name;
|
tree section_name;
|
||||||
tree machine_attributes;
|
tree attributes;
|
||||||
rtx rtl; /* RTL representation for object. */
|
rtx rtl; /* RTL representation for object. */
|
||||||
rtx live_range_rtl;
|
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_type_attribute_variant PARAMS ((tree, tree));
|
||||||
extern tree build_decl_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. */
|
/* Default versions of target-overridable functions. */
|
||||||
|
|
||||||
extern tree merge_decl_attributes PARAMS ((tree, tree));
|
extern tree merge_decl_attributes PARAMS ((tree, tree));
|
||||||
extern tree merge_type_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 int default_comp_type_attributes PARAMS ((tree, tree));
|
||||||
extern void default_set_default_type_attributes PARAMS ((tree));
|
extern void default_set_default_type_attributes PARAMS ((tree));
|
||||||
extern void default_insert_attributes PARAMS ((tree, 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. */
|
/* Split a list of declspecs and attributes into two. */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue