From e3501bab810710c32b76884331b1d0d5b58bcc2b Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 12 Dec 2014 12:52:21 -0500 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 8 ++ gcc/cp/class.c | 120 +++++++++++++++++---------- gcc/cp/cp-tree.h | 6 ++ gcc/cp/name-lookup.c | 13 ++- gcc/testsuite/g++.dg/abi/abi-tag12.C | 8 ++ 5 files changed, 108 insertions(+), 47 deletions(-) create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag12.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3de8861f792..828848164ed 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2014-12-12 Jason Merrill + + * 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 PR c++/63996 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index c83c8adfab2..07bbc69806c 100644 --- a/gcc/cp/class.c +++ b/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(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(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) { diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ad1cc71162f..e8516606184 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 71b359eeca8..b982451caf6 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -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", diff --git a/gcc/testsuite/g++.dg/abi/abi-tag12.C b/gcc/testsuite/g++.dg/abi/abi-tag12.C new file mode 100644 index 00000000000..74dffa0efaa --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/abi-tag12.C @@ -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" } -- 2.30.2