re PR c++/65734 (Yet another case of lost alignment by stor_layout)
authorJason Merrill <jason@redhat.com>
Tue, 28 Apr 2015 14:43:48 +0000 (10:43 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 28 Apr 2015 14:43:48 +0000 (10:43 -0400)
PR c++/65734
gcc/
* stor-layout.c (layout_type): Layout the TYPE_MAIN_VARIANT.
(finalize_type_size): Respect TYPE_USER_ALIGN.
(layout_type) [ARRAY_TYPE]: Likewise.
gcc/cp/
* class.c (fixup_attribute_variants): Respect TYPE_USER_ALIGN.

From-SVN: r222529

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/stor-layout.c
gcc/testsuite/g++.dg/cpp0x/alignas1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/alignas2.C [new file with mode: 0644]

index b1c59fd..3857fa0 100644 (file)
@@ -1,3 +1,10 @@
+2015-04-28  Jason Merrill  <jason@redhat.com>
+
+       PR c++/65734
+       * stor-layout.c (layout_type): Layout the TYPE_MAIN_VARIANT.
+       (finalize_type_size): Respect TYPE_USER_ALIGN.
+       (layout_type) [ARRAY_TYPE]: Likewise.
+
 2015-04-28  Yvan Roux  <yvan.roux@linaro.org>
 
        * config/arm/arm.md (*arm_movt): Fix type attribute.
index 3f91187..b7c4720 100644 (file)
@@ -1,3 +1,8 @@
+2015-04-28  Jason Merrill  <jason@redhat.com>
+
+       PR c++/65734
+       * class.c (fixup_attribute_variants): Respect TYPE_USER_ALIGN.
+
 2015-04-27  Trevor Saunders  <tbsaunde+gcc@tbsaunde.org>
 
        * class.c (layout_class_type): Remove check if
index be5f5c2..c1548a0 100644 (file)
@@ -1989,14 +1989,23 @@ fixup_attribute_variants (tree t)
   if (!t)
     return;
 
+  tree attrs = TYPE_ATTRIBUTES (t);
+  unsigned align = TYPE_ALIGN (t);
+  bool user_align = TYPE_USER_ALIGN (t);
+
   for (variants = TYPE_NEXT_VARIANT (t);
        variants;
        variants = TYPE_NEXT_VARIANT (variants))
     {
       /* These are the two fields that check_qualified_type looks at and
         are affected by attributes.  */
-      TYPE_ATTRIBUTES (variants) = TYPE_ATTRIBUTES (t);
-      TYPE_ALIGN (variants) = TYPE_ALIGN (t);
+      TYPE_ATTRIBUTES (variants) = attrs;
+      unsigned valign = align;
+      if (TYPE_USER_ALIGN (variants))
+       valign = MAX (valign, TYPE_ALIGN (variants));
+      else
+       TYPE_USER_ALIGN (variants) = user_align;
+      TYPE_ALIGN (variants) = valign;
     }
 }
 \f
index 1d1de99..38760b2 100644 (file)
@@ -1826,9 +1826,13 @@ finalize_type_size (tree type)
        {
          TYPE_SIZE (variant) = size;
          TYPE_SIZE_UNIT (variant) = size_unit;
-         TYPE_ALIGN (variant) = align;
+         unsigned valign = align;
+         if (TYPE_USER_ALIGN (variant))
+           valign = MAX (valign, TYPE_ALIGN (variant));
+         else
+           TYPE_USER_ALIGN (variant) = user_align;
+         TYPE_ALIGN (variant) = valign;
          TYPE_PRECISION (variant) = precision;
-         TYPE_USER_ALIGN (variant) = user_align;
          SET_TYPE_MODE (variant, mode);
        }
     }
@@ -2149,6 +2153,10 @@ layout_type (tree type)
   if (type == error_mark_node)
     return;
 
+  /* We don't want finalize_type_size to copy an alignment attribute to
+     variants that don't have it.  */
+  type = TYPE_MAIN_VARIANT (type);
+
   /* Do nothing if type has been laid out before.  */
   if (TYPE_SIZE (type))
     return;
@@ -2345,13 +2353,17 @@ layout_type (tree type)
        /* Now round the alignment and size,
           using machine-dependent criteria if any.  */
 
+       unsigned align = TYPE_ALIGN (element);
+       if (TYPE_USER_ALIGN (type))
+         align = MAX (align, TYPE_ALIGN (type));
+       else
+         TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element);
 #ifdef ROUND_TYPE_ALIGN
-       TYPE_ALIGN (type)
-         = ROUND_TYPE_ALIGN (type, TYPE_ALIGN (element), BITS_PER_UNIT);
+       align = ROUND_TYPE_ALIGN (type, align, BITS_PER_UNIT);
 #else
-       TYPE_ALIGN (type) = MAX (TYPE_ALIGN (element), BITS_PER_UNIT);
+       align = MAX (align, BITS_PER_UNIT);
 #endif
-       TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element);
+       TYPE_ALIGN (type) = align;
        SET_TYPE_MODE (type, BLKmode);
        if (TYPE_SIZE (type) != 0
            && ! targetm.member_type_forces_blk (type, VOIDmode)
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignas1.C b/gcc/testsuite/g++.dg/cpp0x/alignas1.C
new file mode 100644 (file)
index 0000000..d73c875
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/65734
+// { dg-do compile { target c++11 } }
+
+template <class T> struct A
+{
+  T t;
+};
+
+typedef A<int> T[4] alignas (2 * alignof (int));
+A<int> a[4];
+
+typedef A<char> T2[4] alignas (2 * alignof (int));
+
+#define SA(X) static_assert((X),#X)
+SA(alignof (T) == 2 * alignof(int));
+SA(alignof (T2) == 2 * alignof(int));
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignas2.C b/gcc/testsuite/g++.dg/cpp0x/alignas2.C
new file mode 100644 (file)
index 0000000..2e7d051
--- /dev/null
@@ -0,0 +1,20 @@
+// PR c++/65734
+// { dg-do compile { target c++11 } }
+
+template <typename T>
+struct BVector
+{
+  T t;
+};
+BVector<int> m;
+
+template <template <class> class T>
+struct BV2
+{
+  typedef T<float> value_type alignas (16);
+  value_type v;
+};
+BV2<BVector> m2;
+
+#define SA(X) static_assert((X),#X)
+SA(alignof (BV2<BVector>::value_type) == 16);