cp-tree.h (NAMESPACE_ABI_TAG): New.
authorJason Merrill <jason@redhat.com>
Fri, 12 Dec 2014 17:52:21 +0000 (12:52 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 12 Dec 2014 17:52:21 +0000 (12:52 -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.

From-SVN: r218684

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/name-lookup.c
gcc/testsuite/g++.dg/abi/abi-tag12.C [new file with mode: 0644]

index 3de8861f792de50e34938adc908c386f54ed4e48..828848164ed4b5d60695db293ba9327e88772116 100644 (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
index c83c8adfab278dfc81543745f54b79c8dad7bcc7..07bbc69806cd4b13850055c6dd8e4f6cd1694018 100644 (file)
@@ -1352,18 +1352,73 @@ handle_using_decl (tree using_decl, tree t)
     alter_access (t, decl, access);
 }
 \f
-/* 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)
     {
index ad1cc71162ff02a9ca6a783325f7398f6f782da2..e8516606184fb43a7bdb5db22d697a3d38cd3f97 100644 (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.  */
index 71b359eeca887ba83d360f5a937e74d0f6f4f03c..b982451caf67fa0529ee1935a5bc68dff260a9fa 100644 (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",
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag12.C b/gcc/testsuite/g++.dg/abi/abi-tag12.C
new file mode 100644 (file)
index 0000000..74dffa0
--- /dev/null
@@ -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" }