diff options
author | Jakub Jelinek <jakub@redhat.com> | 2016-01-31 15:53:26 +0100 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-01-31 09:53:26 -0500 |
commit | 75a27d3584e4c8565a838d4623e12ba1602e8a92 (patch) | |
tree | 104b280c259f5583ca744225d29936a58f595805 /gcc | |
parent | 6978c505d01ec65a1465a196e35f27eb5cc79c66 (diff) | |
download | gcc-75a27d3584e4c8565a838d4623e12ba1602e8a92.zip gcc-75a27d3584e4c8565a838d4623e12ba1602e8a92.tar.gz gcc-75a27d3584e4c8565a838d4623e12ba1602e8a92.tar.bz2 |
re PR c++/68763 (ICE: in verify_unstripped_args, at cp/pt.c:1132)
PR c++/68763
* tree.c (strip_typedefs) [FUNCTION_TYPE]: Avoid building a new
function type if nothing is changing.
Co-Authored-By: Jason Merrill <jason@redhat.com>
From-SVN: r233020
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/tree.c | 38 |
2 files changed, 41 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 783fe72..804deb0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2016-01-31 Jakub Jelinek <jakub@redhat.com> + Jason Merrill <jason@redhat.com> + + PR c++/68763 + * tree.c (strip_typedefs) [FUNCTION_TYPE]: Avoid building a new + function type if nothing is changing. + 2016-01-31 Jason Merrill <jason@redhat.com> PR c++/69009 diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index d4cf310..2bf37bc 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1314,7 +1314,22 @@ strip_typedefs (tree t, bool *remove_attributes) case FUNCTION_TYPE: case METHOD_TYPE: { - tree arg_types = NULL, arg_node, arg_type; + tree arg_types = NULL, arg_node, arg_node2, arg_type; + bool changed; + + /* Because we stomp on TREE_PURPOSE of TYPE_ARG_TYPES in many places + around the compiler (e.g. cp_parser_late_parsing_default_args), we + can't expect that re-hashing a function type will find a previous + equivalent type, so try to reuse the input type if nothing has + changed. If the type is itself a variant, that will change. */ + bool is_variant = typedef_variant_p (t); + if (remove_attributes + && (TYPE_ATTRIBUTES (t) || TYPE_USER_ALIGN (t))) + is_variant = true; + + type = strip_typedefs (TREE_TYPE (t), remove_attributes); + changed = type != TREE_TYPE (t) || is_variant; + for (arg_node = TYPE_ARG_TYPES (t); arg_node; arg_node = TREE_CHAIN (arg_node)) @@ -1324,11 +1339,27 @@ strip_typedefs (tree t, bool *remove_attributes) arg_type = strip_typedefs (TREE_VALUE (arg_node), remove_attributes); gcc_assert (arg_type); + if (arg_type == TREE_VALUE (arg_node) && !changed) + continue; + + if (!changed) + { + changed = true; + for (arg_node2 = TYPE_ARG_TYPES (t); + arg_node2 != arg_node; + arg_node2 = TREE_CHAIN (arg_node2)) + arg_types + = tree_cons (TREE_PURPOSE (arg_node2), + TREE_VALUE (arg_node2), arg_types); + } - arg_types = - tree_cons (TREE_PURPOSE (arg_node), arg_type, arg_types); + arg_types + = tree_cons (TREE_PURPOSE (arg_node), arg_type, arg_types); } + if (!changed) + return t; + if (arg_types) arg_types = nreverse (arg_types); @@ -1337,7 +1368,6 @@ strip_typedefs (tree t, bool *remove_attributes) if (arg_node) arg_types = chainon (arg_types, void_list_node); - type = strip_typedefs (TREE_TYPE (t), remove_attributes); if (TREE_CODE (t) == METHOD_TYPE) { tree class_type = TREE_TYPE (TREE_VALUE (arg_types)); |