+2004-03-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/13170
+ * decl.c (xref_tag): Remove attribute handling.
+ * cp-tree.h: Adjust prototype.
+ * decl.c, parser.c, rtti.c: Adjust callers.
+ * parser.c (cp_parser_class_head): Pass back attributes in the
+ class head.
+ (cp_parser_class_specifier): Adjust.
+
2004-03-08 Matt Austern <austern@apple.com>
PR debug/14079
extern void grok_special_member_properties (tree);
extern int grok_ctor_properties (tree, tree);
extern bool grok_op_properties (tree, int, bool);
-extern tree xref_tag (enum tag_types, tree, tree, bool, bool);
+extern tree xref_tag (enum tag_types, tree, bool, bool);
extern tree xref_tag_from_type (tree, tree, int);
extern void xref_basetypes (tree, tree);
extern tree start_enum (tree);
Define the tag as a forward-reference if it is not defined.
If a declaration is given, process it here, and report an error if
- multiple declarations are not identical. ATTRIBUTE is the attribute
- appeared in this declaration.
+ multiple declarations are not identical.
GLOBALIZE is false when this is also a definition. Only look in
the current frame for the name (since C++ allows new names in any
a set of template parameters. */
tree
-xref_tag (enum tag_types tag_code, tree name, tree attributes,
+xref_tag (enum tag_types tag_code, tree name,
bool globalize, bool template_header_p)
{
enum tree_code code;
redeclare_class_template (t, current_template_parms);
}
- /* Add attributes only when defining a class. */
- if (attributes)
- {
- /* The only place that xref_tag is called with non-null
- attributes is in cp_parser_class_head(), when defining a
- class. */
- my_friendly_assert (TYPE_ATTRIBUTES (t) == NULL_TREE, 20040113);
- TYPE_ATTRIBUTES (t) = attributes;
- }
-
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old);
- return xref_tag (tag_kind, id, /*attributes=*/NULL_TREE, globalize, false);
+ return xref_tag (tag_kind, id, globalize, false);
}
/* REF is a type (named NAME), for which we have just seen some
static tree cp_parser_class_specifier
(cp_parser *);
static tree cp_parser_class_head
- (cp_parser *, bool *);
+ (cp_parser *, bool *, tree *);
static enum tag_types cp_parser_class_key
(cp_parser *);
static void cp_parser_member_specification_opt
warning ("type attributes are honored only at type definition");
type = xref_tag (tag_type, identifier,
- /*attributes=*/NULL_TREE,
(is_friend
|| !is_declaration
|| cp_lexer_next_token_is_not (parser->lexer,
{
cp_token *token;
tree type;
- tree attributes = NULL_TREE;
+ tree attributes;
int has_trailing_semicolon;
bool nested_name_specifier_p;
unsigned saved_num_template_parameter_lists;
/* Parse the class-head. */
type = cp_parser_class_head (parser,
- &nested_name_specifier_p);
+ &nested_name_specifier_p,
+ &attributes);
/* If the class-head was a semantic disaster, skip the entire body
of the class. */
if (!type)
missing trailing `;'. */
token = cp_lexer_peek_token (parser->lexer);
has_trailing_semicolon = (token->type == CPP_SEMICOLON);
- /* Look for attributes to apply to this class. */
+ /* Look for trailing attributes to apply to this class. */
if (cp_parser_allow_gnu_extensions_p (parser))
- attributes = cp_parser_attributes_opt (parser);
- /* If we got any attributes in class_head, xref_tag will stick them in
- TREE_TYPE of the type. Grab them now. */
- if (type != error_mark_node)
{
- attributes = chainon (TYPE_ATTRIBUTES (type), attributes);
- TYPE_ATTRIBUTES (type) = NULL_TREE;
- type = finish_struct (type, attributes);
+ tree sub_attr = cp_parser_attributes_opt (parser);
+ attributes = chainon (attributes, sub_attr);
}
+ if (type != error_mark_node)
+ type = finish_struct (type, attributes);
if (pop_p)
pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)));
/* If this class is not itself within the scope of another class,
static tree
cp_parser_class_head (cp_parser* parser,
- bool* nested_name_specifier_p)
+ bool* nested_name_specifier_p,
+ tree *attributes_p)
{
cp_token *token;
tree nested_name_specifier;
/* If the class was unnamed, create a dummy name. */
if (!id)
id = make_anon_name ();
- type = xref_tag (class_key, id, attributes, /*globalize=*/false,
+ type = xref_tag (class_key, id, /*globalize=*/false,
parser->num_template_parameter_lists);
}
else
end_specialization ();
--parser->num_template_parameter_lists;
}
+ *attributes_p = attributes;
return type;
}
push_namespace (std_identifier);
type_info_type_node
= xref_tag (class_type, get_identifier ("type_info"),
- /*attributes=*/NULL_TREE, true, false);
+ true, false);
pop_namespace ();
const_type_info_type = build_qualified_type (type_info_type_node,
TYPE_QUAL_CONST);
push_nested_namespace (ns);
tinfo_ptr = xref_tag (class_type,
get_identifier ("__class_type_info"),
- /*attributes=*/NULL_TREE,
true, false);
tinfo_ptr = build_pointer_type
push_nested_namespace (abi_node);
real_type = xref_tag (class_type, TINFO_REAL_NAME (desc),
- /*attributes=*/NULL_TREE, true, false);
+ true, false);
pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (real_type))
push_nested_namespace (abi_node);
bltn_type = xref_tag (class_type,
get_identifier ("__fundamental_type_info"),
- /*attributes=*/NULL_TREE,
true, false);
pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (bltn_type))
--- /dev/null
+// PR c++/13170
+// The bogus attribute is ignored, but was in TYPE_ATTRIBUTES during parsing of the class,
+// causing some variants to have it and some not.
+
+struct __attribute__((bogus)) A
+{
+ virtual ~A();
+ void foo(const A&);
+ void bar(const A&);
+}; // { dg-warning "ignored" "" }
+
+void A::foo(const A&) {}
+void A::bar(const A& a) { foo(a); }