aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2016-01-31 15:53:26 +0100
committerJason Merrill <jason@gcc.gnu.org>2016-01-31 09:53:26 -0500
commit75a27d3584e4c8565a838d4623e12ba1602e8a92 (patch)
tree104b280c259f5583ca744225d29936a58f595805 /gcc
parent6978c505d01ec65a1465a196e35f27eb5cc79c66 (diff)
downloadgcc-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/ChangeLog7
-rw-r--r--gcc/cp/tree.c38
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));