]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/68763 (ICE: in verify_unstripped_args, at cp/pt.c:1132)
authorJakub Jelinek <jakub@redhat.com>
Sun, 31 Jan 2016 14:53:26 +0000 (15:53 +0100)
committerJason Merrill <jason@gcc.gnu.org>
Sun, 31 Jan 2016 14:53:26 +0000 (09:53 -0500)
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

gcc/cp/ChangeLog
gcc/cp/tree.c

index 783fe72ff53d56d5ddf0702b4228fa95c7dbc047..804deb068efa95079dbe79eb211de1505f9c68e4 100644 (file)
@@ -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
index d4cf3102a03171b9d101ab26d34aa47fbb933ada..2bf37bcabc1689d52a43dca54a6eba7fe192f1ce 100644 (file)
@@ -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));