diff options
author | Jason Merrill <jason@redhat.com> | 2014-01-08 13:48:31 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2014-01-08 13:48:31 -0500 |
commit | f585f02f977fc342e45853d2d1789c710399a24e (patch) | |
tree | f8c9ab5b0d7fb73bddb92a211736419393866ea9 /gcc/cp | |
parent | c6de66659813cd840c2e1f5fe9698ba857618627 (diff) | |
download | gcc-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/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cp/class.c | 81 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 5 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 2 |
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); } |