]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/59614 (Explostion in compile time of heavily templated code)
authorJason Merrill <jason@redhat.com>
Wed, 8 Jan 2014 18:48:31 +0000 (13:48 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 8 Jan 2014 18:48:31 +0000 (13:48 -0500)
PR c++/59614
* class.c (abi_tag_data): Add tags field.
(check_abi_tags): Initialize it.
(find_abi_tags_r): Support collecting missing tags.
(mark_type_abi_tags): Don't look at template args.
(inherit_targ_abi_tags): New.
(check_bases_and_members): Use it.
* cp-tree.h (ABI_TAG_IMPLICIT): New.
* mangle.c (write_abi_tags): Check it.

From-SVN: r206439

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/mangle.c
gcc/testsuite/g++.dg/abi/abi-tag5.C

index bf2a593917c1f6221d315f6e9715a55fa5bb64d6..b6ee8754c6fee8a76e61edd39d2f0e5591fe9727 100644 (file)
@@ -1,3 +1,15 @@
+2014-01-08  Jason Merrill  <jason@redhat.com>
+
+       PR c++/59614
+       * class.c (abi_tag_data): Add tags field.
+       (check_abi_tags): Initialize it.
+       (find_abi_tags_r): Support collecting missing tags.
+       (mark_type_abi_tags): Don't look at template args.
+       (inherit_targ_abi_tags): New.
+       (check_bases_and_members): Use it.
+       * cp-tree.h (ABI_TAG_IMPLICIT): New.
+       * mangle.c (write_abi_tags): Check it.
+
 2014-01-07  Jason Merrill  <jason@redhat.com>
 
        PR c++/58856
index c961b2268e7a24100e37cd050e5dfcc839005762..0c3ce47bc756be930d768cdc2d8b5b423285fde7 100644 (file)
@@ -1340,14 +1340,20 @@ 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)
+find_abi_tags_r (tree *tp, int *walk_subtrees, void *data)
 {
   if (!OVERLOAD_TYPE_P (*tp))
     return NULL_TREE;
 
+  /* walk_tree shouldn't be walking into any subtrees of a RECORD_TYPE
+     anyway, but let's make sure of it.  */
+  *walk_subtrees = false;
+
   if (tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (*tp)))
     {
       struct abi_tag_data *p = static_cast<struct abi_tag_data*>(data);
@@ -1358,7 +1364,20 @@ find_abi_tags_r (tree *tp, int */*walk_subtrees*/, void *data)
          tree id = get_identifier (TREE_STRING_POINTER (tag));
          if (!IDENTIFIER_MARKED (id))
            {
-             if (TYPE_P (p->subob))
+             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))
                {
                  warning (OPT_Wabi_tag, "%qT does not have the %E abi tag "
                           "that base %qT has", p->t, tag, p->subob);
@@ -1397,22 +1416,6 @@ mark_type_abi_tags (tree t, bool val)
          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
@@ -1424,13 +1427,50 @@ 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 };
+  struct abi_tag_data data = { t, subob, error_mark_node };
 
   cp_walk_tree_without_duplicates (&subtype, find_abi_tags_r, &data);
 
   mark_type_abi_tags (t, false);
 }
 
+void
+inherit_targ_abi_tags (tree t)
+{
+  if (CLASSTYPE_TEMPLATE_INFO (t) == NULL_TREE)
+    return;
+
+  mark_type_abi_tags (t, true);
+
+  tree args = CLASSTYPE_TI_ARGS (t);
+  struct abi_tag_data data = { t, NULL_TREE, NULL_TREE };
+  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);
+         data.subob = arg;
+         cp_walk_tree_without_duplicates (&arg, find_abi_tags_r, &data);
+       }
+    }
+
+  // If we found some tags on our template arguments, add them to our
+  // abi_tag attribute.
+  if (data.tags)
+    {
+      tree attr = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (t));
+      if (attr)
+       TREE_VALUE (attr) = chainon (data.tags, TREE_VALUE (attr));
+      else
+       TYPE_ATTRIBUTES (t)
+         = tree_cons (get_identifier ("abi_tag"), data.tags,
+                      TYPE_ATTRIBUTES (t));
+    }
+
+  mark_type_abi_tags (t, false);
+}
+
 /* Run through the base classes of T, updating CANT_HAVE_CONST_CTOR_P,
    and NO_CONST_ASN_REF_P.  Also set flag bits in T based on
    properties of the bases.  */
@@ -5431,6 +5471,9 @@ check_bases_and_members (tree t)
   bool saved_nontrivial_dtor;
   tree fn;
 
+  /* Pick up any abi_tags from our template arguments before checking.  */
+  inherit_targ_abi_tags (t);
+
   /* By default, we use const reference arguments and generate default
      constructors.  */
   cant_have_const_ctor = 0;
index bdae500d374a5a4d779e0a92a6b1cf1c0d812baa..96af562f245e7022df0a9b1263513bce96cc6334 100644 (file)
@@ -65,6 +65,7 @@ c-common.h, not after.
       TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR)
       TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX)
       ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute)
+      ABI_TAG_IMPLICIT (in the TREE_LIST for the argument of abi_tag)
       CONSTRUCTOR_IS_DIRECT_INIT (in CONSTRUCTOR)
       LAMBDA_EXPR_CAPTURES_THIS_P (in LAMBDA_EXPR)
       DECLTYPE_FOR_LAMBDA_CAPTURE (in DECLTYPE_TYPE)
@@ -2589,6 +2590,10 @@ struct GTY((variable_size)) lang_decl {
    must be applied at instantiation time.  */
 #define ATTR_IS_DEPENDENT(NODE) TREE_LANG_FLAG_0 (TREE_LIST_CHECK (NODE))
 
+/* In a TREE_LIST in the argument of attribute abi_tag, indicates that the tag
+   was inherited from a template parameter, not explicitly indicated.  */
+#define ABI_TAG_IMPLICIT(NODE) TREE_LANG_FLAG_0 (TREE_LIST_CHECK (NODE))
+
 extern tree decl_shadowed_for_var_lookup (tree);
 extern void decl_shadowed_for_var_insert (tree, tree);
 
index dc7d4eab9013da1315e4aa00152f881b30c75e65..be3c698f4b619d0da8dec667db339510fbc9f3e7 100644 (file)
@@ -1338,6 +1338,8 @@ write_abi_tags (tree tags)
 
   for (tree t = tags; t; t = TREE_CHAIN (t))
     {
+      if (ABI_TAG_IMPLICIT (t))
+       continue;
       tree str = TREE_VALUE (t);
       vec_safe_push (vec, str);
     }
index de5580239dd76fbcd216d865e917d07cb5e2685a..95e367ef935fef0eaa39a14b3828d8e582648e5b 100644 (file)
@@ -1,6 +1,7 @@
 // { dg-options -Wabi-tag }
+// { dg-final { scan-assembler "_Z1f1BI1AB3fooE" } }
 
 struct __attribute__ ((abi_tag ("foo"))) A { };
 template <class T> struct B: T { };
 
-B<A> b;
+void f(B<A>) {}