https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62077

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jason at gcc dot gnu.org

--- Comment #26 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #24)
> Or "real" fix for the type_hash_canon issue (untested)
> 
> Index: gcc/tree.c
> ===================================================================
> --- gcc/tree.c  (revision 213814)
> +++ gcc/tree.c  (working copy)
> @@ -6593,7 +6593,9 @@ type_hash_eq (const void *va, const void
>        || !attribute_list_equal (TYPE_ATTRIBUTES (a->type),
>                                  TYPE_ATTRIBUTES (b->type))
>        || (TREE_CODE (a->type) != COMPLEX_TYPE
> -          && TYPE_NAME (a->type) != TYPE_NAME (b->type)))
> +          && TYPE_NAME (a->type) != TYPE_NAME (b->type))
> +      || ((TYPE_MAIN_VARIANT (a->type) == TYPE_MAIN_VARIANT (a->type))
> +         != (TYPE_MAIN_VARIANT (b->type) == TYPE_MAIN_VARIANT (b->type))))
>      return 0;
>  
>    /* Be careful about comparing arrays before and after the element type

Hmpf, that doesn't fix it.  But the following makes us ICE:

Index: tree.c
===================================================================
--- tree.c      (revision 213814)
+++ tree.c      (working copy)
@@ -6759,6 +6761,7 @@ type_hash_canon (unsigned int hashcode,
   t1 = type_hash_lookup (hashcode, type);
   if (t1 != 0)
     {
+      gcc_assert (TYPE_MAIN_VARIANT (t1) == t1);
       if (GATHER_STATISTICS)
        {
          tree_code_counts[(int) TREE_CODE (type)]--;

which means somebody mangles TYPE_MAIN_VARIANT of a type already in
the type hash table.

build_cplus_array_type is it:

  /* We want TYPE_MAIN_VARIANT of an array to strip cv-quals from the
     element type as well, so fix it up if needed.  */
  if (elt_type != TYPE_MAIN_VARIANT (elt_type))
    {
      tree m = build_cplus_array_type (TYPE_MAIN_VARIANT (elt_type),
                                       index_type);
...
          TYPE_MAIN_VARIANT (t) = m;

Jason?  Something like

Index: cp/tree.c
===================================================================
--- cp/tree.c   (revision 213814)
+++ cp/tree.c   (working copy)
@@ -824,7 +824,11 @@ build_cplus_array_type (tree elt_type, t
        build_cplus_array_type
          (TYPE_CANONICAL (elt_type),
           index_type ? TYPE_CANONICAL (index_type) : index_type);
-      t = build_array_type (elt_type, index_type);
+      if (elt_type != TYPE_MAIN_VARIANT (elt_type))
+       t = build_cplus_array_type (TYPE_MAIN_VARIANT (elt_type),
+                                   index_type);
+      else
+       t = build_array_type (elt_type, index_type);
     }

   /* Push these needs up so that initialization takes place
@@ -840,37 +844,19 @@ build_cplus_array_type (tree elt_type, t
      element type as well, so fix it up if needed.  */
   if (elt_type != TYPE_MAIN_VARIANT (elt_type))
     {
-      tree m = build_cplus_array_type (TYPE_MAIN_VARIANT (elt_type),
-                                      index_type);
-
-      if (TYPE_MAIN_VARIANT (t) != m)
+      /* ???  We didn't even try to re-use existing types?
+         ???  Ah, we did via the type_hash_canon that this breaks.  */
+      tree t1;
+      for (t1 = TYPE_MAIN_VARIANT (t); t1; t1 = TYPE_NEXT_VARIANT (t1))
+       if (TREE_TYPE (t1) == elt_type)
+         {
+           t = t1;
+           break;
+         }
+      if (!t1)
        {
-         if (COMPLETE_TYPE_P (TREE_TYPE (t)) && !COMPLETE_TYPE_P (m))
-           {
-             /* m was built before the element type was complete, so we
-                also need to copy the layout info from t.  We might
-                end up doing this multiple times if t is an array of
-                unknown bound.  */
-             tree size = TYPE_SIZE (t);
-             tree size_unit = TYPE_SIZE_UNIT (t);
-             unsigned int align = TYPE_ALIGN (t);
-             unsigned int user_align = TYPE_USER_ALIGN (t);
-             enum machine_mode mode = TYPE_MODE (t);
-             for (tree var = m; var; var = TYPE_NEXT_VARIANT (var))
-               {
-                 TYPE_SIZE (var) = size;
-                 TYPE_SIZE_UNIT (var) = size_unit;
-                 TYPE_ALIGN (var) = align;
-                 TYPE_USER_ALIGN (var) = user_align;
-                 SET_TYPE_MODE (var, mode);
-                 TYPE_NEEDS_CONSTRUCTING (var) = needs_ctor;
-                 TYPE_HAS_NONTRIVIAL_DESTRUCTOR (var) = needs_dtor;
-               }
-           }
-
-         TYPE_MAIN_VARIANT (t) = m;
-         TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
-         TYPE_NEXT_VARIANT (m) = t;
+         t = build_variant_type_copy (t);
+         TREE_TYPE (t) = elt_type;
        }
     }

fixes that - but eventually breaks whatever needed that odd type completion,
which we also can't allow on types that are recorded in the type_hash_canon
hashtable.  Not sure how that code can trigger when we build m right
before using elt_type which is now either not complete or complete (and so is
t).

The above fixes the LTO miscompares.  Let's see if it survives LTO bootstrap.

Reply via email to