mirror of git://gcc.gnu.org/git/gcc.git
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>
|
2014-12-12 Kai Tietz <ktietz@redhat.com>
|
||||||
|
|
||||||
PR c++/63996
|
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);
|
alter_access (t, decl, access);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* walk_tree callback for check_abi_tags: if the type at *TP involves any
|
/* Data structure for find_abi_tags_r, below. */
|
||||||
types with abi tags, add the corresponding identifiers to the VEC in
|
|
||||||
*DATA and set IDENTIFIER_MARKED. */
|
|
||||||
|
|
||||||
struct abi_tag_data
|
struct abi_tag_data
|
||||||
{
|
{
|
||||||
tree t;
|
tree t; // The type that we're checking for missing tags.
|
||||||
tree subob;
|
tree subob; // The subobject of T that we're getting tags from.
|
||||||
// error_mark_node to get diagnostics; otherwise collect missing tags here
|
tree tags; // error_mark_node for diagnostics, or a list of missing tags.
|
||||||
tree 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
|
static tree
|
||||||
find_abi_tags_r (tree *tp, int *walk_subtrees, void *data)
|
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. */
|
anyway, but let's make sure of it. */
|
||||||
*walk_subtrees = false;
|
*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)))
|
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;
|
for (tree list = TREE_VALUE (attributes); list;
|
||||||
list = TREE_CHAIN (list))
|
list = TREE_CHAIN (list))
|
||||||
{
|
{
|
||||||
tree tag = TREE_VALUE (list);
|
tree tag = TREE_VALUE (list);
|
||||||
tree id = get_identifier (TREE_STRING_POINTER (tag));
|
check_tag (tag, tp, p);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
|
|
@ -1427,6 +1455,12 @@ find_abi_tags_r (tree *tp, int *walk_subtrees, void *data)
|
||||||
static void
|
static void
|
||||||
mark_type_abi_tags (tree t, bool val)
|
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));
|
tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (t));
|
||||||
if (attributes)
|
if (attributes)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,7 @@ c-common.h, not after.
|
||||||
DECL_MUTABLE_P (in FIELD_DECL)
|
DECL_MUTABLE_P (in FIELD_DECL)
|
||||||
DECL_DEPENDENT_P (in USING_DECL)
|
DECL_DEPENDENT_P (in USING_DECL)
|
||||||
LABEL_DECL_BREAK (in LABEL_DECL)
|
LABEL_DECL_BREAK (in LABEL_DECL)
|
||||||
|
NAMESPACE_ABI_TAG (in NAMESPACE_DECL)
|
||||||
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
|
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
|
||||||
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
|
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
|
||||||
DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL)
|
DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL)
|
||||||
|
|
@ -2642,6 +2643,11 @@ struct GTY(()) lang_decl {
|
||||||
#define LOCAL_CLASS_P(NODE) \
|
#define LOCAL_CLASS_P(NODE) \
|
||||||
(decl_function_context (TYPE_MAIN_DECL (NODE)) != NULL_TREE)
|
(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
|
/* For a NAMESPACE_DECL: the list of using namespace directives
|
||||||
The PURPOSE is the used namespace, the value is the namespace
|
The PURPOSE is the used namespace, the value is the namespace
|
||||||
that is the common ancestor. */
|
that is the common ancestor. */
|
||||||
|
|
|
||||||
|
|
@ -3610,10 +3610,8 @@ current_decl_namespace (void)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process any ATTRIBUTES on a namespace definition. Currently only
|
/* Process any ATTRIBUTES on a namespace definition. Returns true if
|
||||||
attribute visibility is meaningful, which is a property of the syntactic
|
attribute visibility is seen. */
|
||||||
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. */
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
handle_namespace_attrs (tree ns, tree attributes)
|
handle_namespace_attrs (tree ns, tree attributes)
|
||||||
|
|
@ -3628,6 +3626,9 @@ handle_namespace_attrs (tree ns, tree attributes)
|
||||||
|
|
||||||
if (is_attribute_p ("visibility", name))
|
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;
|
tree x = args ? TREE_VALUE (args) : NULL_TREE;
|
||||||
if (x == NULL_TREE || TREE_CODE (x) != STRING_CST || TREE_CHAIN (args))
|
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);
|
push_visibility (TREE_STRING_POINTER (x), 1);
|
||||||
saw_vis = true;
|
saw_vis = true;
|
||||||
}
|
}
|
||||||
|
else if (is_attribute_p ("abi_tag", name))
|
||||||
|
{
|
||||||
|
NAMESPACE_ABI_TAG (ns) = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
warning (OPT_Wattributes, "%qD attribute directive ignored",
|
warning (OPT_Wattributes, "%qD attribute directive ignored",
|
||||||
|
|
|
||||||
|
|
@ -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…
Reference in New Issue