mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 15:41:09 +08:00
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:
parent
9c89d52a8d
commit
e3501bab81
@ -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
|
||||
|
120
gcc/cp/class.c
120
gcc/cp/class.c
@ -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)
|
||||
{
|
||||
|
@ -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. */
|
||||
|
@ -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",
|
||||
|
8
gcc/testsuite/g++.dg/abi/abi-tag12.C
Normal file
8
gcc/testsuite/g++.dg/abi/abi-tag12.C
Normal 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" }
|
Loading…
x
Reference in New Issue
Block a user