aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-01-08 13:48:31 -0500
committerJason Merrill <jason@gcc.gnu.org>2014-01-08 13:48:31 -0500
commitf585f02f977fc342e45853d2d1789c710399a24e (patch)
treef8c9ab5b0d7fb73bddb92a211736419393866ea9 /gcc/cp
parentc6de66659813cd840c2e1f5fe9698ba857618627 (diff)
downloadgcc-f585f02f977fc342e45853d2d1789c710399a24e.zip
gcc-f585f02f977fc342e45853d2d1789c710399a24e.tar.gz
gcc-f585f02f977fc342e45853d2d1789c710399a24e.tar.bz2
re PR c++/59614 (Explostion in compile time of heavily templated code)
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/class.c81
-rw-r--r--gcc/cp/cp-tree.h5
-rw-r--r--gcc/cp/mangle.c2
4 files changed, 81 insertions, 19 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bf2a593..b6ee875 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index c961b22..0c3ce47 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index bdae500..96af562f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index dc7d4ea..be3c698 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -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);
}