Hi!

The following patches (included or attached) fix a regression on WebKit
compilation.
The first hunk basically reverts Honza's patch from December/January,
because layout_type when the variants are already linked in doesn't layout
just the current type, but also forcefully overwrites all the other
variants, which is clearly highly undesirable.  The attached
patch has an alternate hunk for that, where it doesn't call layout_type at
all and just copies over the needed fields from the main variant.

The second hunk (the same in between both patches) fixes a problem that
alignof (const T) is incorrect, but it has been that way already in 4.8 at
least.

I've been wondering if it would be possible that build_cplus_array_type
would see incomplete element type on the main variant and complete qualified
element type, but have not succeeded with e.g.
struct S
{
  typedef S T[4][4] __attribute__((aligned (16)));
  static T t;
  static volatile T v;
};
void foo (const S::T);
volatile const S::T w;
S::T S::t;
volatile S::T S::v;

The included (first) patch has been successfully bootstrapped/regtested on
x86_64-linux and i686-linux, the attached patch not, but I can
bootstrap/regtest it if you prefer it.

2015-04-08  Jakub Jelinek  <ja...@redhat.com>
            Jan Hubicka  <hubi...@ucw.cz>

        PR c++/65690
        * tree.c (build_cplus_array_type): Layout type before variants are
        set, but copy over TYPE_SIZE and TYPE_SIZE_UNIT from the main
        variant.
        (cp_build_qualified_type_real): Use check_base_type.  Build a
        variant and copy over even TYPE_CONTEXT and
        TYPE_ALIGN/TYPE_USER_ALIGN if any of those are different.

        * c-c++-common/attr-aligned-1.c: New test.

--- gcc/cp/tree.c.jj    2015-04-01 15:29:33.000000000 +0200
+++ gcc/cp/tree.c       2015-04-08 09:09:45.326939354 +0200
@@ -880,12 +880,19 @@ build_cplus_array_type (tree elt_type, t
        {
          t = build_min_array_type (elt_type, index_type);
          set_array_type_canon (t, elt_type, index_type);
+         if (!dependent)
+           {
+             layout_type (t);
+             /* Make sure sizes are shared with the main variant.
+                layout_type can't be called after setting TYPE_NEXT_VARIANT,
+                as it will overwrite alignment etc. of all variants.  */
+             TYPE_SIZE (t) = TYPE_SIZE (m);
+             TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (m);
+           }
 
          TYPE_MAIN_VARIANT (t) = m;
          TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
          TYPE_NEXT_VARIANT (m) = t;
-         if (!dependent)
-           layout_type (t);
        }
     }
 
@@ -1057,21 +1064,23 @@ cp_build_qualified_type_real (tree type,
         should be equivalent to those in check_qualified_type.  */
       for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
        if (TREE_TYPE (t) == element_type
-           && TYPE_NAME (t) == TYPE_NAME (type)
-           && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
-           && attribute_list_equal (TYPE_ATTRIBUTES (t),
-                                    TYPE_ATTRIBUTES (type)))
+           && check_base_type (t, type))
          break;
 
       if (!t)
        {
          t = build_cplus_array_type (element_type, TYPE_DOMAIN (type));
 
-         /* Keep the typedef name.  */
-         if (TYPE_NAME (t) != TYPE_NAME (type))
+         /* Keep the typedef name, context and alignment.  */
+         if (TYPE_NAME (t) != TYPE_NAME (type)
+             || TYPE_CONTEXT (t) != TYPE_CONTEXT (type)
+             || TYPE_ALIGN (t) != TYPE_ALIGN (type))
            {
              t = build_variant_type_copy (t);
              TYPE_NAME (t) = TYPE_NAME (type);
+             TYPE_CONTEXT (t) = TYPE_CONTEXT (type);
+             TYPE_ALIGN (t) = TYPE_ALIGN (type);
+             TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (type);
            }
        }
 
--- gcc/testsuite/c-c++-common/attr-aligned-1.c.jj      2015-04-08 
09:22:46.181427189 +0200
+++ gcc/testsuite/c-c++-common/attr-aligned-1.c 2015-04-08 09:26:41.315627195 
+0200
@@ -0,0 +1,24 @@
+/* PR c++/65690 */
+/* { dg-do run } */
+
+typedef double T[4][4] __attribute__((aligned (2 * __alignof__ (double))));
+void foo (const T);
+struct S { T s; };
+
+int
+main ()
+{
+  if (__alignof__ (struct S) != 2 * __alignof__ (double)
+      || __alignof__ (T) != 2 * __alignof__ (double)
+      || __alignof__ (const struct S) != 2 * __alignof__ (double)
+      || __alignof__ (const T) != 2 * __alignof__ (double))
+    __builtin_abort ();
+  return 0;
+}
+
+#if defined(__cplusplus) && __cplusplus >= 201103L
+static_assert (alignof (S) == 2 * alignof (double), "alignment of S");
+static_assert (alignof (T) == 2 * alignof (double), "alignment of T");
+static_assert (alignof (const S) == 2 * alignof (double), "alignment of const 
S");
+static_assert (alignof (const T) == 2 * alignof (double), "alignment of const 
T");
+#endif

        Jakub
2015-04-08  Jakub Jelinek  <ja...@redhat.com>
            Jan Hubicka  <hubi...@ucw.cz>

        PR c++/65690
        * tree.c (build_cplus_array_type): Don't layout the type,
        instead copy everything over from the main variant.
        (cp_build_qualified_type_real): Use check_base_type.  Build a
        variant and copy over even TYPE_CONTEXT and
        TYPE_ALIGN/TYPE_USER_ALIGN if any of those are different.

        * c-c++-common/attr-aligned-1.c: New test.

--- gcc/cp/tree.c.jj    2015-04-01 15:29:33.000000000 +0200
+++ gcc/cp/tree.c       2015-04-08 09:09:45.326939354 +0200
@@ -880,12 +880,19 @@ build_cplus_array_type (tree elt_type, t
        {
          t = build_min_array_type (elt_type, index_type);
          set_array_type_canon (t, elt_type, index_type);
+         if (!dependent)
+           {
+             TYPE_SIZE (t) = TYPE_SIZE (m);
+             TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (m);
+             TYPE_ALIGN (t) = TYPE_ALIGN (m);
+             TYPE_PRECISION (t) = TYPE_PRECISION (m);
+             TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (m);
+             SET_TYPE_MODE (t, TYPE_MODE (m));
+           }
 
          TYPE_MAIN_VARIANT (t) = m;
          TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
          TYPE_NEXT_VARIANT (m) = t;
-         if (!dependent)
-           layout_type (t);
        }
     }
 
@@ -1057,21 +1064,23 @@ cp_build_qualified_type_real (tree type,
         should be equivalent to those in check_qualified_type.  */
       for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
        if (TREE_TYPE (t) == element_type
-           && TYPE_NAME (t) == TYPE_NAME (type)
-           && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
-           && attribute_list_equal (TYPE_ATTRIBUTES (t),
-                                    TYPE_ATTRIBUTES (type)))
+           && check_base_type (t, type))
          break;
 
       if (!t)
        {
          t = build_cplus_array_type (element_type, TYPE_DOMAIN (type));
 
-         /* Keep the typedef name.  */
-         if (TYPE_NAME (t) != TYPE_NAME (type))
+         /* Keep the typedef name, context and alignment.  */
+         if (TYPE_NAME (t) != TYPE_NAME (type)
+             || TYPE_CONTEXT (t) != TYPE_CONTEXT (type)
+             || TYPE_ALIGN (t) != TYPE_ALIGN (type))
            {
              t = build_variant_type_copy (t);
              TYPE_NAME (t) = TYPE_NAME (type);
+             TYPE_CONTEXT (t) = TYPE_CONTEXT (type);
+             TYPE_ALIGN (t) = TYPE_ALIGN (type);
+             TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (type);
            }
        }
 
--- gcc/testsuite/c-c++-common/attr-aligned-1.c.jj      2015-04-08 
09:22:46.181427189 +0200
+++ gcc/testsuite/c-c++-common/attr-aligned-1.c 2015-04-08 09:26:41.315627195 
+0200
@@ -0,0 +1,24 @@
+/* PR c++/65690 */
+/* { dg-do run } */
+
+typedef double T[4][4] __attribute__((aligned (2 * __alignof__ (double))));
+void foo (const T);
+struct S { T s; };
+
+int
+main ()
+{
+  if (__alignof__ (struct S) != 2 * __alignof__ (double)
+      || __alignof__ (T) != 2 * __alignof__ (double)
+      || __alignof__ (const struct S) != 2 * __alignof__ (double)
+      || __alignof__ (const T) != 2 * __alignof__ (double))
+    __builtin_abort ();
+  return 0;
+}
+
+#if defined(__cplusplus) && __cplusplus >= 201103L
+static_assert (alignof (S) == 2 * alignof (double), "alignment of S");
+static_assert (alignof (T) == 2 * alignof (double), "alignment of T");
+static_assert (alignof (const S) == 2 * alignof (double), "alignment of const 
S");
+static_assert (alignof (const T) == 2 * alignof (double), "alignment of const 
T");
+#endif

Reply via email to