cp-tree.h (NAMESPACE_ABI_TAG): New.

* cp-tree.h (NAMESPACE_ABI_TAG): New.
	* name-lookup.c (handle_namespace_attrs): Set it.
	* class.c (check_tag): Split out from find_abi_tags_r.
	(find_abi_tags_r): Also check namespace tags.
	(mark_type_abi_tags): Also mark namespace tags.

From-SVN: r218684
This commit is contained in:
Jason Merrill 2014-12-12 12:52:21 -05:00 committed by Jason Merrill
parent 9c89d52a8d
commit e3501bab81
5 changed files with 108 additions and 47 deletions

View File

@ -1,3 +1,11 @@
2014-12-12 Jason Merrill <jason@redhat.com>
* cp-tree.h (NAMESPACE_ABI_TAG): New.
* name-lookup.c (handle_namespace_attrs): Set it.
* class.c (check_tag): Split out from find_abi_tags_r.
(find_abi_tags_r): Also check namespace tags.
(mark_type_abi_tags): Also mark namespace tags.
2014-12-12 Kai Tietz <ktietz@redhat.com>
PR c++/63996

View File

@ -1352,18 +1352,73 @@ handle_using_decl (tree using_decl, tree t)
alter_access (t, decl, access);
}
/* walk_tree callback for check_abi_tags: if the type at *TP involves any
types with abi tags, add the corresponding identifiers to the VEC in
*DATA and set IDENTIFIER_MARKED. */
/* Data structure for find_abi_tags_r, below. */
struct abi_tag_data
{
tree t;
tree subob;
// error_mark_node to get diagnostics; otherwise collect missing tags here
tree tags;
tree t; // The type that we're checking for missing tags.
tree subob; // The subobject of T that we're getting tags from.
tree tags; // error_mark_node for diagnostics, or a list of missing tags.
};
/* Subroutine of find_abi_tags_r. Handle a single TAG found on the class TP
in the context of P. TAG can be either an identifier (the DECL_NAME of
a tag NAMESPACE_DECL) or a STRING_CST (a tag attribute). */
static void
check_tag (tree tag, tree *tp, abi_tag_data *p)
{
tree id;
if (TREE_CODE (tag) == STRING_CST)
id = get_identifier (TREE_STRING_POINTER (tag));
else
{
id = tag;
tag = NULL_TREE;
}
if (!IDENTIFIER_MARKED (id))
{
if (!tag)
tag = build_string (IDENTIFIER_LENGTH (id) + 1,
IDENTIFIER_POINTER (id));
if (p->tags != error_mark_node)
{
/* We're collecting tags from template arguments. */
p->tags = tree_cons (NULL_TREE, tag, p->tags);
ABI_TAG_IMPLICIT (p->tags) = true;
/* Don't inherit this tag multiple times. */
IDENTIFIER_MARKED (id) = true;
}
/* Otherwise we're diagnosing missing tags. */
else if (TYPE_P (p->subob))
{
if (warning (OPT_Wabi_tag, "%qT does not have the %E abi tag "
"that base %qT has", p->t, tag, p->subob))
inform (location_of (p->subob), "%qT declared here",
p->subob);
}
else
{
if (warning (OPT_Wabi_tag, "%qT does not have the %E abi tag "
"that %qT (used in the type of %qD) has",
p->t, tag, *tp, p->subob))
{
inform (location_of (p->subob), "%qD declared here",
p->subob);
inform (location_of (*tp), "%qT declared here", *tp);
}
}
}
}
/* walk_tree callback for check_abi_tags: if the type at *TP involves any
types with abi tags, add the corresponding identifiers to the VEC in
*DATA and set IDENTIFIER_MARKED. */
static tree
find_abi_tags_r (tree *tp, int *walk_subtrees, void *data)
{
@ -1374,48 +1429,21 @@ find_abi_tags_r (tree *tp, int *walk_subtrees, void *data)
anyway, but let's make sure of it. */
*walk_subtrees = false;
abi_tag_data *p = static_cast<struct abi_tag_data*>(data);
for (tree ns = decl_namespace_context (*tp);
ns != global_namespace;
ns = CP_DECL_CONTEXT (ns))
if (NAMESPACE_ABI_TAG (ns))
check_tag (DECL_NAME (ns), tp, p);
if (tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (*tp)))
{
struct abi_tag_data *p = static_cast<struct abi_tag_data*>(data);
for (tree list = TREE_VALUE (attributes); list;
list = TREE_CHAIN (list))
{
tree tag = TREE_VALUE (list);
tree id = get_identifier (TREE_STRING_POINTER (tag));
if (!IDENTIFIER_MARKED (id))
{
if (p->tags != error_mark_node)
{
/* We're collecting tags from template arguments. */
tree str = build_string (IDENTIFIER_LENGTH (id),
IDENTIFIER_POINTER (id));
p->tags = tree_cons (NULL_TREE, str, p->tags);
ABI_TAG_IMPLICIT (p->tags) = true;
/* Don't inherit this tag multiple times. */
IDENTIFIER_MARKED (id) = true;
}
/* Otherwise we're diagnosing missing tags. */
else if (TYPE_P (p->subob))
{
if (warning (OPT_Wabi_tag, "%qT does not have the %E abi tag "
"that base %qT has", p->t, tag, p->subob))
inform (location_of (p->subob), "%qT declared here",
p->subob);
}
else
{
if (warning (OPT_Wabi_tag, "%qT does not have the %E abi tag "
"that %qT (used in the type of %qD) has",
p->t, tag, *tp, p->subob))
{
inform (location_of (p->subob), "%qD declared here",
p->subob);
inform (location_of (*tp), "%qT declared here", *tp);
}
}
}
check_tag (tag, tp, p);
}
}
return NULL_TREE;
@ -1427,6 +1455,12 @@ find_abi_tags_r (tree *tp, int *walk_subtrees, void *data)
static void
mark_type_abi_tags (tree t, bool val)
{
for (tree ns = decl_namespace_context (t);
ns != global_namespace;
ns = CP_DECL_CONTEXT (ns))
if (NAMESPACE_ABI_TAG (ns))
IDENTIFIER_MARKED (DECL_NAME (ns)) = val;
tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (t));
if (attributes)
{

View File

@ -151,6 +151,7 @@ c-common.h, not after.
DECL_MUTABLE_P (in FIELD_DECL)
DECL_DEPENDENT_P (in USING_DECL)
LABEL_DECL_BREAK (in LABEL_DECL)
NAMESPACE_ABI_TAG (in NAMESPACE_DECL)
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL)
@ -2642,6 +2643,11 @@ struct GTY(()) lang_decl {
#define LOCAL_CLASS_P(NODE) \
(decl_function_context (TYPE_MAIN_DECL (NODE)) != NULL_TREE)
/* 1 iff this NAMESPACE_DECL should also be treated as an ABI tag for
-Wabi-tag. */
#define NAMESPACE_ABI_TAG(NODE) \
DECL_LANG_FLAG_0 (NAMESPACE_DECL_CHECK (NODE))
/* For a NAMESPACE_DECL: the list of using namespace directives
The PURPOSE is the used namespace, the value is the namespace
that is the common ancestor. */

View File

@ -3610,10 +3610,8 @@ current_decl_namespace (void)
return result;
}
/* Process any ATTRIBUTES on a namespace definition. Currently only
attribute visibility is meaningful, which is a property of the syntactic
block rather than the namespace as a whole, so we don't touch the
NAMESPACE_DECL at all. Returns true if attribute visibility is seen. */
/* Process any ATTRIBUTES on a namespace definition. Returns true if
attribute visibility is seen. */
bool
handle_namespace_attrs (tree ns, tree attributes)
@ -3628,6 +3626,9 @@ handle_namespace_attrs (tree ns, tree attributes)
if (is_attribute_p ("visibility", name))
{
/* attribute visibility is a property of the syntactic block
rather than the namespace as a whole, so we don't touch the
NAMESPACE_DECL at all. */
tree x = args ? TREE_VALUE (args) : NULL_TREE;
if (x == NULL_TREE || TREE_CODE (x) != STRING_CST || TREE_CHAIN (args))
{
@ -3645,6 +3646,10 @@ handle_namespace_attrs (tree ns, tree attributes)
push_visibility (TREE_STRING_POINTER (x), 1);
saw_vis = true;
}
else if (is_attribute_p ("abi_tag", name))
{
NAMESPACE_ABI_TAG (ns) = true;
}
else
{
warning (OPT_Wattributes, "%qD attribute directive ignored",

View File

@ -0,0 +1,8 @@
// { dg-options "-Wabi-tag" }
inline namespace A __attribute ((abi_tag)) {
struct Foo { }; // { dg-message "declared here" }
struct Baz: Foo { };
}
struct Bar: Foo { }; // { dg-warning "tag" }