aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJoseph Myers <jsm28@cam.ac.uk>2001-09-21 02:27:06 +0100
committerJoseph Myers <jsm28@gcc.gnu.org>2001-09-21 02:27:06 +0100
commit91d231cb917f53b4cd34dec24227863e95fceb6f (patch)
treef30b39e86c1e124ae235fd7661bc83c06577bc32 /gcc/cp
parent3007d592bf05a6f1728f023c46207083cd24ca32 (diff)
downloadgcc-91d231cb917f53b4cd34dec24227863e95fceb6f.zip
gcc-91d231cb917f53b4cd34dec24227863e95fceb6f.tar.gz
gcc-91d231cb917f53b4cd34dec24227863e95fceb6f.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog40
-rw-r--r--gcc/cp/class.c2
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl.c108
-rw-r--r--gcc/cp/decl.h2
-rw-r--r--gcc/cp/decl2.c27
-rw-r--r--gcc/cp/friend.c14
-rw-r--r--gcc/cp/parse.y15
-rw-r--r--gcc/cp/pt.c4
-rw-r--r--gcc/cp/tree.c219
10 files changed, 241 insertions, 194 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8d0498f..345cef4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,43 @@
+2001-09-21 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ Table-driven attributes.
+ * decl.c: Rename DECL_MACHINE_ATTRIBUTES to DECL_ATTRIBUTES.
+ * decl2.c (cplus_decl_attributes): Only take one attributes
+ parameter.
+ * cp-tree.c (cplus_decl_attributes): Update prototype.
+ * class.c (finish_struct), decl.c (start_decl, start_function),
+ decl2.c (grokfield), friend.c (do_friend), parse.y
+ (parse_bitfield): Update calls to cplus_decl_attributes.
+ * decl.c (grokdeclarator): Take a pointer to a single ordinary
+ attribute list.
+ * decl.h (grokdeclarator): Update prototype.
+ * decl2.c (grokfield): Take a single ordinary attribute list.
+ * friend.c (do_friend): Likewise.
+ * decl.c (shadow_tag, groktypename, start_decl,
+ start_handler_parms, grokdeclarator, grokparms, start_function,
+ start_method), decl2.c (grokfield, grokbitfield, grokoptypename),
+ parse.y (parse_field, parse_bitfield, component_decl_1), pt.c
+ (process_template_parm, do_decl_instantiation): Pass single
+ ordinary attribute lists around.
+ * decl.c (grokdeclarator): Correct handling of nested attributes.
+ Revert the patch
+ 1998-10-18 Jason Merrill <jason@yorick.cygnus.com>
+ * decl.c (grokdeclarator): Embedded attrs bind to the right,
+ not the left.
+ .
+ * cp-tree.h (cp_valid_lang_attribute): Remove declaration
+ (cp_attribute_table): Declare.
+ * decl.c (valid_lang_attribute): Don't define.
+ (lang_attribute_table): Define.
+ (init_decl_processing): Initialize lang_attribute_table instead of
+ valid_lang_attribute.
+ * tree.c (cp_valid_lang_attribute): Remove.
+ (handle_java_interface_attribute, handle_com_interface_attribute,
+ handle_init_priority_attribute): New functions.
+ (cp_attribute_table): New array.
+ * decl2.c (import_export_class): Don't use
+ targetm.valid_type_attribute.
+
2001-09-15 Gabriel Dos Reis <gdr@merlin.codesourcery.com>
* Make-lang.in (cp/error.o): Depend on real.h
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1526a05..0c106c3 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -5293,7 +5293,7 @@ finish_struct (t, attributes)
as necessary. */
unreverse_member_declarations (t);
- cplus_decl_attributes (&t, attributes, NULL_TREE, 0);
+ cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
/* Nadger the current location so that diagnostics point to the start of
the struct, not the end. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 04837da..2662356 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3734,7 +3734,7 @@ extern tree grokbitfield PARAMS ((tree, tree, tree));
extern tree groktypefield PARAMS ((tree, tree));
extern tree grokoptypename PARAMS ((tree, tree));
extern int copy_assignment_arg_p PARAMS ((tree, int));
-extern void cplus_decl_attributes PARAMS ((tree *, tree, tree, int));
+extern void cplus_decl_attributes PARAMS ((tree *, tree, int));
extern tree constructor_name_full PARAMS ((tree));
extern tree constructor_name PARAMS ((tree));
extern void defer_fn PARAMS ((tree));
@@ -4208,7 +4208,7 @@ extern tree walk_tree_without_duplicates PARAMS ((tree *,
walk_tree_fn,
void *));
extern tree copy_tree_r PARAMS ((tree *, int *, void *));
-extern int cp_valid_lang_attribute PARAMS ((tree, tree, tree, tree));
+extern const struct attribute_spec cp_attribute_table[];
extern tree make_ptrmem_cst PARAMS ((tree, tree));
extern tree cp_build_qualified_type_real PARAMS ((tree, int, int));
extern void remap_save_expr PARAMS ((tree *, splay_tree, tree, int *));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 9244272..60938a7 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -45,7 +45,7 @@ Boston, MA 02111-1307, USA. */
#include "tm_p.h"
#include "target.h"
-extern int (*valid_lang_attribute) PARAMS ((tree, tree, tree, tree));
+extern const struct attribute_spec *lang_attribute_table;
#ifndef BOOL_TYPE_SIZE
/* `bool' has size and alignment `1', on all platforms. */
@@ -3438,7 +3438,7 @@ duplicate_decls (newdecl, olddecl)
/* Copy all the DECL_... slots specified in the new decl
except for any that we copy here from the old type. */
- DECL_MACHINE_ATTRIBUTES (newdecl)
+ DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
@@ -3746,7 +3746,7 @@ duplicate_decls (newdecl, olddecl)
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
- DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
+ DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
return 1;
}
@@ -6493,7 +6493,7 @@ init_decl_processing ()
/* Show we use EH for cleanups. */
using_eh_for_cleanups ();
- valid_lang_attribute = cp_valid_lang_attribute;
+ lang_attribute_table = cp_attribute_table;
/* Maintain consistency. Perhaps we should just complain if they
say -fwritable-strings? */
@@ -6986,7 +6986,7 @@ shadow_tag (declspecs)
if (TYPE_FIELDS (t))
{
tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
- NULL_TREE);
+ NULL);
finish_anon_union (decl);
}
}
@@ -7002,7 +7002,7 @@ groktypename (typename)
return typename;
return grokdeclarator (TREE_VALUE (typename),
TREE_PURPOSE (typename),
- TYPENAME, 0, NULL_TREE);
+ TYPENAME, 0, NULL);
}
/* Decode a declarator in an ordinary declaration or data definition.
@@ -7031,7 +7031,6 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
tree context;
extern int have_extern_spec;
extern int used_extern_spec;
- tree attrlist;
#if 0
/* See code below that used this. */
@@ -7046,13 +7045,10 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
used_extern_spec = 1;
}
- if (attributes || prefix_attributes)
- attrlist = build_tree_list (attributes, prefix_attributes);
- else
- attrlist = NULL_TREE;
+ attributes = chainon (attributes, prefix_attributes);
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
- attrlist);
+ &attributes);
if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
return NULL_TREE;
@@ -7119,7 +7115,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
}
/* Set attributes here so if duplicate decl, will have proper attributes. */
- cplus_decl_attributes (&decl, attributes, prefix_attributes, 0);
+ cplus_decl_attributes (&decl, attributes, 0);
if (context && COMPLETE_TYPE_P (complete_type (context)))
{
@@ -8482,7 +8478,7 @@ start_handler_parms (declspecs, declarator)
if (declspecs)
{
decl = grokdeclarator (declarator, declspecs, CATCHPARM,
- 1, NULL_TREE);
+ 1, NULL);
if (decl == NULL_TREE)
error ("invalid catch parameter");
}
@@ -9425,8 +9421,9 @@ check_special_function_return_type (sfk, type, optype)
BITFIELD for a field with specified width.
INITIALIZED is 1 if the decl has an initializer.
- ATTRLIST is a TREE_LIST node with prefix attributes in TREE_VALUE and
- normal attributes in TREE_PURPOSE, or NULL_TREE.
+ ATTRLIST is a pointer to the list of attributes, which may be NULL
+ if there are none; *ATTRLIST may be modified if attributes from inside
+ the declarator should be applied to the declaration.
In the TYPENAME case, DECLARATOR is really an abstract declarator.
It may also be so in the PARM case, for a prototype where the
@@ -9464,7 +9461,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree declarator;
enum decl_context decl_context;
int initialized;
- tree attrlist;
+ tree *attrlist;
{
RID_BIT_TYPE specbits;
int nclasses = 0;
@@ -9487,7 +9484,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
int bitfield = 0;
#if 0
/* See the code below that used this. */
- tree decl_machine_attr = NULL_TREE;
+ tree decl_attr = NULL_TREE;
#endif
/* Set this to error_mark_node for FIELD_DECLs we could not handle properly.
All FIELD_DECLs we build here have `init' put into their DECL_INITIAL. */
@@ -9506,8 +9503,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree raises = NULL_TREE;
int template_count = 0;
tree in_namespace = NULL_TREE;
- tree inner_attrs;
- int ignore_attrs;
+ tree returned_attrs = NULL_TREE;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
@@ -9598,24 +9594,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
cp_finish_decl so we can get the variable
initialized... */
- tree attributes, prefix_attributes;
+ tree attributes;
*next = TREE_OPERAND (decl, 0);
init = CALL_DECLARATOR_PARMS (decl);
if (attrlist)
{
- attributes = TREE_PURPOSE (attrlist);
- prefix_attributes = TREE_VALUE (attrlist);
+ attributes = *attrlist;
}
else
{
attributes = NULL_TREE;
- prefix_attributes = NULL_TREE;
}
decl = start_decl (declarator, declspecs, 1,
- attributes, prefix_attributes);
+ attributes, NULL_TREE);
decl_type_access_control (decl);
if (decl)
{
@@ -9953,7 +9947,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = TREE_TYPE (t);
#if 0
/* See the code below that used this. */
- decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
+ decl_attr = DECL_ATTRIBUTES (id);
#endif
typedef_decl = t;
}
@@ -10312,9 +10306,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
Descend through it, creating more complex types, until we reach
the declared identifier (or NULL_TREE, in an absolute declarator). */
- inner_attrs = NULL_TREE;
- ignore_attrs = 0;
-
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
&& TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
{
@@ -10363,28 +10354,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
- /* See the comment for the TREE_LIST case, below. */
- if (ignore_attrs)
- ignore_attrs = 0;
- else if (inner_attrs)
- {
- decl_attributes (&type, inner_attrs, 0);
- inner_attrs = NULL_TREE;
- }
-
switch (TREE_CODE (declarator))
{
case TREE_LIST:
{
/* We encode a declarator with embedded attributes using
- a TREE_LIST. The attributes apply to the declarator
- directly inside them, so we have to skip an iteration
- before applying them to the type. If the declarator just
- inside is the declarator-id, we apply the attrs to the
- decl itself. */
- inner_attrs = TREE_PURPOSE (declarator);
- ignore_attrs = 1;
+ a TREE_LIST. */
+ tree attrs = TREE_PURPOSE (declarator);
+ tree inner_decl;
declarator = TREE_VALUE (declarator);
+ inner_decl = declarator;
+ while (inner_decl != NULL_TREE
+ && TREE_CODE (inner_decl) == TREE_LIST)
+ inner_decl = TREE_VALUE (inner_decl);
+ int attr_flags = 0;
+ if (inner_decl == NULL_TREE
+ || TREE_CODE (inner_decl) == IDENTIFIER_NODE)
+ attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
+ if (TREE_CODE (inner_decl) == CALL_EXPR)
+ attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
+ if (TREE_CODE (inner_decl) == ARRAY_REF)
+ attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+ returned_attrs = decl_attributes (&type,
+ chainon (returned_attrs, attrs),
+ attr_flags);
}
break;
@@ -10883,15 +10876,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
- /* See the comment for the TREE_LIST case, above. */
- if (inner_attrs)
+ if (returned_attrs)
{
- if (! ignore_attrs)
- decl_attributes (&type, inner_attrs, 0);
- else if (attrlist)
- TREE_VALUE (attrlist) = chainon (inner_attrs, TREE_VALUE (attrlist));
+ if (attrlist)
+ *attrlist = chainon (returned_attrs, *attrlist);
else
- attrlist = build_tree_list (NULL_TREE, inner_attrs);
+ attrlist = &returned_attrs;
}
/* Now TYPE has the actual type. */
@@ -11302,8 +11292,8 @@ friend declaration requires class-key, i.e. `friend %#T'",
return decl;
#if 0
/* This clobbers the attrs stored in `decl' from `attrlist'. */
- /* The decl and setting of decl_machine_attr is also turned off. */
- decl = build_decl_attribute_variant (decl, decl_machine_attr);
+ /* The decl and setting of decl_attr is also turned off. */
+ decl = build_decl_attribute_variant (decl, decl_attr);
#endif
/* [class.conv.ctor]
@@ -11401,7 +11391,7 @@ friend declaration requires class-key, i.e. `friend %#T'",
}
t = do_friend (ctype, declarator, decl,
- last_function_parms, attrlist, flags, quals,
+ last_function_parms, *attrlist, flags, quals,
funcdef_flag);
}
if (t && funcdef_flag)
@@ -11838,7 +11828,7 @@ grokparms (first_parm)
break;
decl = grokdeclarator (TREE_VALUE (decl), TREE_PURPOSE (decl),
- PARM, init != NULL_TREE, NULL_TREE);
+ PARM, init != NULL_TREE, NULL);
if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
@@ -13269,7 +13259,7 @@ start_function (declspecs, declarator, attrs, flags)
}
else
{
- decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL_TREE);
+ decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0;
@@ -13554,7 +13544,7 @@ start_function (declspecs, declarator, attrs, flags)
pushlevel (0);
current_binding_level->parm_flag = 1;
- cplus_decl_attributes (&decl1, NULL_TREE, attrs, 0);
+ cplus_decl_attributes (&decl1, attrs, 0);
/* Promote the value to int before returning it. */
if (c_promoting_integer_type_p (restype))
@@ -14056,7 +14046,7 @@ start_method (declspecs, declarator, attrlist)
tree declarator, declspecs, attrlist;
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
- attrlist);
+ &attrlist);
/* Something too ugly to handle. */
if (fndecl == NULL_TREE)
diff --git a/gcc/cp/decl.h b/gcc/cp/decl.h
index c5417d1..6f1418a 100644
--- a/gcc/cp/decl.h
+++ b/gcc/cp/decl.h
@@ -31,7 +31,7 @@ enum decl_context
};
/* We need this in here to get the decl_context definition. */
-extern tree grokdeclarator PARAMS ((tree, tree, enum decl_context, int, tree));
+extern tree grokdeclarator PARAMS ((tree, tree, enum decl_context, int, tree *));
/* Parsing a function declarator leaves a list of parameter names
or a chain or parameter decls here. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 5c62aca..28236ef 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1531,7 +1531,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
&& TREE_CHAIN (init) == NULL_TREE)
init = NULL_TREE;
- value = grokdeclarator (declarator, declspecs, FIELD, init != 0, attrlist);
+ value = grokdeclarator (declarator, declspecs, FIELD, init != 0, &attrlist);
if (! value || value == error_mark_node)
/* friend or constructor went bad. */
return value;
@@ -1628,8 +1628,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
value = push_template_decl (value);
if (attrlist)
- cplus_decl_attributes (&value, TREE_PURPOSE (attrlist),
- TREE_VALUE (attrlist), 0);
+ cplus_decl_attributes (&value, attrlist, 0);
if (TREE_CODE (value) == VAR_DECL)
{
@@ -1679,7 +1678,7 @@ grokbitfield (declarator, declspecs, width)
tree declarator, declspecs, width;
{
register tree value = grokdeclarator (declarator, declspecs, BITFIELD,
- 0, NULL_TREE);
+ 0, NULL);
if (! value) return NULL_TREE; /* friends went bad. */
@@ -1735,7 +1734,7 @@ tree
grokoptypename (declspecs, declarator)
tree declspecs, declarator;
{
- tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE);
+ tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL);
return mangle_conv_op_name_for_type (t);
}
@@ -1824,8 +1823,8 @@ grok_function_init (decl, init)
}
void
-cplus_decl_attributes (decl, attributes, prefix_attributes, flags)
- tree *decl, attributes, prefix_attributes;
+cplus_decl_attributes (decl, attributes, flags)
+ tree *decl, attributes;
int flags;
{
if (*decl == NULL_TREE || *decl == void_type_node)
@@ -1834,7 +1833,7 @@ cplus_decl_attributes (decl, attributes, prefix_attributes, flags)
if (TREE_CODE (*decl) == TEMPLATE_DECL)
decl = &DECL_TEMPLATE_RESULT (*decl);
- decl_attributes (decl, chainon (attributes, prefix_attributes), flags);
+ decl_attributes (decl, attributes, flags);
if (TREE_CODE (*decl) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
@@ -2371,17 +2370,9 @@ import_export_class (ctype)
if (CLASSTYPE_INTERFACE_ONLY (ctype))
return;
- if ((*targetm.valid_type_attribute) (ctype,
- TYPE_ATTRIBUTES (ctype),
- get_identifier ("dllimport"),
- NULL_TREE)
- && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype)))
+ if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype)))
import_export = -1;
- else if ((*targetm.valid_type_attribute) (ctype,
- TYPE_ATTRIBUTES (ctype),
- get_identifier ("dllexport"),
- NULL_TREE)
- && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
+ else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
import_export = 1;
/* If we got -fno-implicit-templates, we import template classes that
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index f7ff984..d6d720c 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -309,7 +309,6 @@ do_friend (ctype, declarator, decl, parmdecls, attrlist,
int funcdef_flag;
{
int is_friend_template = 0;
- tree prefix_attributes, attributes;
/* Every decl that gets here is a friend of something. */
DECL_FRIEND_P (decl) = 1;
@@ -435,19 +434,8 @@ do_friend (ctype, declarator, decl, parmdecls, attrlist,
handle them in start_decl_1, but since this is a friend decl start_decl_1
never gets to see it. */
- if (attrlist)
- {
- attributes = TREE_PURPOSE (attrlist);
- prefix_attributes = TREE_VALUE (attrlist);
- }
- else
- {
- attributes = NULL_TREE;
- prefix_attributes = NULL_TREE;
- }
-
/* Set attributes here so if duplicate decl, will have proper attributes. */
- cplus_decl_attributes (&decl, attributes, prefix_attributes, 0);
+ cplus_decl_attributes (&decl, attrlist, 0);
return decl;
}
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index 3b89022..9801c38 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -164,7 +164,7 @@ parse_field (declarator, attributes, asmspec, init)
tree declarator, attributes, asmspec, init;
{
tree d = grokfield (declarator, current_declspecs, init, asmspec,
- build_tree_list (attributes, prefix_attributes));
+ chainon (attributes, prefix_attributes));
decl_type_access_control (d);
return d;
}
@@ -182,7 +182,7 @@ parse_bitfield (declarator, attributes, width)
tree declarator, attributes, width;
{
tree d = grokbitfield (declarator, current_declspecs, width);
- cplus_decl_attributes (&d, attributes, prefix_attributes, 0);
+ cplus_decl_attributes (&d, chainon (attributes, prefix_attributes), 0);
decl_type_access_control (d);
return d;
}
@@ -2639,11 +2639,9 @@ component_decl_1:
$$ = NULL_TREE;
}
| notype_declarator maybeasm maybe_attribute maybe_init
- { $$ = grokfield ($$, NULL_TREE, $4, $2,
- build_tree_list ($3, NULL_TREE)); }
+ { $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
| constructor_declarator maybeasm maybe_attribute maybe_init
- { $$ = grokfield ($$, NULL_TREE, $4, $2,
- build_tree_list ($3, NULL_TREE)); }
+ { $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
| ':' expr_no_commas
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
| error
@@ -2661,10 +2659,9 @@ component_decl_1:
{ tree specs, attrs;
split_specs_attrs ($1.t, &specs, &attrs);
$$ = grokfield ($2, specs, $5, $3,
- build_tree_list ($4, attrs)); }
+ chainon ($4, attrs)); }
| component_constructor_declarator maybeasm maybe_attribute maybe_init
- { $$ = grokfield ($$, NULL_TREE, $4, $2,
- build_tree_list ($3, NULL_TREE)); }
+ { $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
| using_decl
{ $$ = do_class_using_decl ($1); }
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 05ce365..292513f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1929,7 +1929,7 @@ process_template_parm (list, next)
my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
/* is a const-param */
parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
- PARM, 0, NULL_TREE);
+ PARM, 0, NULL);
/* [temp.param]
@@ -9356,7 +9356,7 @@ void
do_decl_instantiation (declspecs, declarator, storage)
tree declspecs, declarator, storage;
{
- tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL_TREE);
+ tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL);
tree result = NULL_TREE;
int extern_p = 0;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 04e8add..32783ad 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -50,6 +50,10 @@ static tree verify_stmt_tree_r PARAMS ((tree *, int *, void *));
static tree find_tree_r PARAMS ((tree *, int *, void *));
extern int cp_statement_code_p PARAMS ((enum tree_code));
+static tree handle_java_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static tree handle_com_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static tree handle_init_priority_attribute PARAMS ((tree *, tree, tree, int, bool *));
+
/* If REF is an lvalue, returns the kind of lvalue that REF is.
Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
non-zero, rvalues of class type are considered lvalues. */
@@ -2182,108 +2186,145 @@ pod_type_p (t)
return 1;
}
-/* Return a 1 if ATTR_NAME and ATTR_ARGS denote a valid C++-specific
- attribute for either declaration DECL or type TYPE and 0 otherwise.
- Plugged into valid_lang_attribute. */
-
-int
-cp_valid_lang_attribute (attr_name, attr_args, decl, type)
- tree attr_name;
- tree attr_args ATTRIBUTE_UNUSED;
- tree decl ATTRIBUTE_UNUSED;
- tree type ATTRIBUTE_UNUSED;
+/* Table of valid C++ attributes. */
+const struct attribute_spec cp_attribute_table[] =
{
- if (is_attribute_p ("java_interface", attr_name))
+ /* { 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
- || decl != NULL_TREE
- || ! CLASS_TYPE_P (type)
- || ! TYPE_FOR_JAVA (type))
- {
- error ("`java_interface' attribute can only be applied to Java class definitions");
- return 0;
- }
- TYPE_JAVA_INTERFACE (type) = 1;
- return 1;
+ error ("`%s' attribute can only be applied to Java class definitions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ return NULL_TREE;
}
- if (is_attribute_p ("com_interface", attr_name))
- {
- static int warned;
- if (attr_args != NULL_TREE
- || decl != NULL_TREE
- || ! CLASS_TYPE_P (type)
- || type != TYPE_MAIN_VARIANT (type))
- {
- warning ("`com_interface' attribute can only be applied to class definitions");
- return 0;
- }
+ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ *node = build_type_copy (*node);
+ TYPE_JAVA_INTERFACE (*node) = 1;
- 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))
+ 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))
{
- tree initp_expr = (attr_args ? TREE_VALUE (attr_args): NULL_TREE);
- int pri;
+ warning ("`%s' attribute can only be applied to class definitions",
+ IDENTIFIER_POINTER (name));
+ return NULL_TREE;
+ }
- if (initp_expr)
- STRIP_NOPS (initp_expr);
+ if (!warned++)
+ warning ("`%s' is obsolete; g++ vtables are now COM-compatible by default",
+ IDENTIFIER_POINTER (name));
+
+ return NULL_TREE;
+}
+
+/* Handle an "init_priority" attribute; arguments as in
+ struct attribute_spec.handler. */
+static tree
+handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree initp_expr = TREE_VALUE (args);
+ tree decl = *node;
+ tree type = TREE_TYPE (decl);
+ int pri;
+
+ STRIP_NOPS (initp_expr);
- if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
- {
- error ("requested init_priority is not an integer constant");
- return 0;
- }
+ 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);
+ 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;
- }
+ 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;
+ }
- /* 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 (pri > MAX_INIT_PRIORITY || pri <= 0)
+ {
+ error ("requested init_priority is out of range");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
- if (SUPPORTS_INIT_PRIORITY)
- {
- DECL_INIT_PRIORITY (decl) = pri;
- return 1;
- }
- else
- {
- error ("init_priority attribute is not supported on this platform");
- 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");
}
- return 0;
+ 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