From patchwork Fri Dec 12 17:51:13 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 420617 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id CE74114009B for ; Sat, 13 Dec 2014 04:51:27 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=QHW/2TEWh1T9Rh+p18EwbqGshfXEGLCYFSjpyBJ+0eYiY4 ajmK6DagesHHo3UpQXr7S/ONDUWEIZnVGLBB2463sdBe2bZuiorW/BPQ87ZG7Nbz WU/jBAUSMBZxQ3OAudfBZl1YCo8vBc6GxqzjfZhdn33F0E45EqOwS2+7xfb4c= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=/V13QRV2liel84Ra6Vljya8x/xc=; b=B9QoC/9srwDeIvZvc+71 LAbIazYIxPM7gicdSthuMbEZD5848Fs83sw9SjSSXi1DmH9Ib5dQ2BQnQ4sTawMl UQkUuGiglnoXwQKxJ/NMuGbSx6+4t59Ob3MtIrC6HSSS8Eai27UzfwgO/nfPBFJj H9u3X+6CK5VraMGV9JGnGCA= Received: (qmail 17780 invoked by alias); 12 Dec 2014 17:51:21 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 17770 invoked by uid 89); 12 Dec 2014 17:51:19 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.7 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 12 Dec 2014 17:51:17 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id sBCHpF6Y022762 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Fri, 12 Dec 2014 12:51:16 -0500 Received: from [10.10.116.25] ([10.10.116.25]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id sBCHpFeB023085 for ; Fri, 12 Dec 2014 12:51:15 -0500 Message-ID: <548B2B11.7060207@redhat.com> Date: Fri, 12 Dec 2014 12:51:13 -0500 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.3.0 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for abi_tag attribute on namespaces By treating a namespace name as an ABI tag we can avoid most of the need for tagging class types. Tested x86_64-pc-linux-gnu, applying to trunk. commit 65b7f772bb3240688aae6af41d0a1200972885ae Author: Jason Merrill Date: Tue Dec 2 17:11:37 2014 -0500 * 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. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index c83c8ad..07bbc69 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); } +/* Data structure for find_abi_tags_r, below. */ + +struct abi_tag_data +{ + 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. */ -struct abi_tag_data -{ - tree t; - tree subob; - // error_mark_node to get diagnostics; otherwise collect missing tags here - tree tags; -}; - 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 ad1cc71..e851660 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 71b359e..b982451 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 0000000..74dffa0 --- /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" }