class.c (mark_type_abi_tags): New.
authorJason Merrill <jason@redhat.com>
Mon, 3 Jun 2013 23:13:10 +0000 (19:13 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 3 Jun 2013 23:13:10 +0000 (19:13 -0400)
* class.c (mark_type_abi_tags): New.
(check_abi_tags): Use it.

From-SVN: r199629

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/testsuite/g++.dg/abi/abi-tag5.C [new file with mode: 0644]

index a30a7d634760f50d107c039a39cf33cac9141522..76c401e089bdcd8fc2980bdbb8d40f0b2c377d07 100644 (file)
@@ -1,3 +1,8 @@
+2013-05-31  Jason Merrill  <jason@redhat.com>
+
+       * class.c (mark_type_abi_tags): New.
+       (check_abi_tags): Use it.
+
 2013-06-03  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/57419
index 22cdf90f735b9254d23476736c1074570a16cb22..40e6d3eed73d19c3825c420b2437cb9ed247f79a 100644 (file)
@@ -1354,11 +1354,11 @@ find_abi_tags_r (tree *tp, int */*walk_subtrees*/, void *data)
   return NULL_TREE;
 }
 
-/* Check that class T has all the abi tags that subobject SUBOB has, or
-   warn if not.  */
+/* Set IDENTIFIER_MARKED on all the ABI tags on T and its (transitively
+   complete) template arguments.  */
 
 static void
-check_abi_tags (tree t, tree subob)
+mark_type_abi_tags (tree t, bool val)
 {
   tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (t));
   if (attributes)
@@ -1368,25 +1368,41 @@ check_abi_tags (tree t, tree subob)
        {
          tree tag = TREE_VALUE (list);
          tree id = get_identifier (TREE_STRING_POINTER (tag));
-         IDENTIFIER_MARKED (id) = true;
+         IDENTIFIER_MARKED (id) = val;
+       }
+    }
+
+  /* Also mark ABI tags from template arguments.  */
+  if (CLASSTYPE_TEMPLATE_INFO (t))
+    {
+      tree args = CLASSTYPE_TI_ARGS (t);
+      for (int i = 0; i < TMPL_ARGS_DEPTH (args); ++i)
+       {
+         tree level = TMPL_ARGS_LEVEL (args, i+1);
+         for (int j = 0; j < TREE_VEC_LENGTH (level); ++j)
+           {
+             tree arg = TREE_VEC_ELT (level, j);
+             if (CLASS_TYPE_P (arg))
+               mark_type_abi_tags (arg, val);
+           }
        }
     }
+}
+
+/* Check that class T has all the abi tags that subobject SUBOB has, or
+   warn if not.  */
+
+static void
+check_abi_tags (tree t, tree subob)
+{
+  mark_type_abi_tags (t, true);
 
   tree subtype = TYPE_P (subob) ? subob : TREE_TYPE (subob);
   struct abi_tag_data data = { t, subob };
 
   cp_walk_tree_without_duplicates (&subtype, find_abi_tags_r, &data);
 
-  if (attributes)
-    {
-      for (tree list = TREE_VALUE (attributes); list;
-          list = TREE_CHAIN (list))
-       {
-         tree tag = TREE_VALUE (list);
-         tree id = get_identifier (TREE_STRING_POINTER (tag));
-         IDENTIFIER_MARKED (id) = false;
-       }
-    }
+  mark_type_abi_tags (t, false);
 }
 
 /* Run through the base classes of T, updating CANT_HAVE_CONST_CTOR_P,
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag5.C b/gcc/testsuite/g++.dg/abi/abi-tag5.C
new file mode 100644 (file)
index 0000000..de55802
--- /dev/null
@@ -0,0 +1,6 @@
+// { dg-options -Wabi-tag }
+
+struct __attribute__ ((abi_tag ("foo"))) A { };
+template <class T> struct B: T { };
+
+B<A> b;