Commit f585f02f by Jason Merrill Committed by Jason Merrill

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
parent c6de6665
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
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
}
......
// { 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>) {}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment