aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2022-11-16 14:49:47 +0100
committerJakub Jelinek <jakub@redhat.com>2022-11-16 14:49:47 +0100
commitc5e8c6c193d9a1ab80ef1a05e5158ddf35d54009 (patch)
treee8774dbe7aa3dbd2ae1b59534a4f6a5fdcf6435d
parent0e2c5510e001e5ccbde9e4b7df757e2bba2fdb00 (diff)
downloadgcc-c5e8c6c193d9a1ab80ef1a05e5158ddf35d54009.zip
gcc-c5e8c6c193d9a1ab80ef1a05e5158ddf35d54009.tar.gz
gcc-c5e8c6c193d9a1ab80ef1a05e5158ddf35d54009.tar.bz2
c++: Alignment changes to layout compatibility/common initial sequence - DR2583
When trying to figure out what to do about alignment, layout_compatible_type_p returns false if TYPE_ALIGN on ENUMERAL_TYPE/CLASS_TYPE_P (but not scalar types?) differ, or if members don't have the same positions. What is in DR2583 doesn't say anything like that though, on the other side it says that if the corresponding entities don't have the same alignment requirements, they aren't part of the common initial sequence. So, my understanding of this is we shouldn't check TYPE_ALIGN in layout_compatible_type_p, but instead DECL_ALIGN in next_common_initial_seqence. 2022-11-16 Jakub Jelinek <jakub@redhat.com> * typeck.cc (next_common_initial_sequence): Return false members have different DECL_ALIGN. (layout_compatible_type_p): Don't test TYPE_ALIGN of ENUMERAL_TYPE or CLASS_TYPE_P. * g++.dg/cpp2a/is-layout-compatible3.C: Expect enums with different alignas to be layout compatible, while classes with different alignas on members layout incompatible. * g++.dg/DRs/dr2583.C: New test.
-rw-r--r--gcc/cp/typeck.cc6
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2583.C45
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/is-layout-compatible3.C4
3 files changed, 50 insertions, 5 deletions
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 6c91182..281d281 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -1833,6 +1833,8 @@ next_common_initial_sequence (tree &memb1, tree &memb2)
if ((!lookup_attribute ("no_unique_address", DECL_ATTRIBUTES (memb1)))
!= !lookup_attribute ("no_unique_address", DECL_ATTRIBUTES (memb2)))
return false;
+ if (DECL_ALIGN (memb1) != DECL_ALIGN (memb2))
+ return false;
if (!tree_int_cst_equal (bit_position (memb1), bit_position (memb2)))
return false;
return true;
@@ -1854,15 +1856,13 @@ layout_compatible_type_p (tree type1, tree type2)
type2 = cp_build_qualified_type (type2, TYPE_UNQUALIFIED);
if (TREE_CODE (type1) == ENUMERAL_TYPE)
- return (TYPE_ALIGN (type1) == TYPE_ALIGN (type2)
- && tree_int_cst_equal (TYPE_SIZE (type1), TYPE_SIZE (type2))
+ return (tree_int_cst_equal (TYPE_SIZE (type1), TYPE_SIZE (type2))
&& same_type_p (finish_underlying_type (type1),
finish_underlying_type (type2)));
if (CLASS_TYPE_P (type1)
&& std_layout_type_p (type1)
&& std_layout_type_p (type2)
- && TYPE_ALIGN (type1) == TYPE_ALIGN (type2)
&& tree_int_cst_equal (TYPE_SIZE (type1), TYPE_SIZE (type2)))
{
tree field1 = TYPE_FIELDS (type1);
diff --git a/gcc/testsuite/g++.dg/DRs/dr2583.C b/gcc/testsuite/g++.dg/DRs/dr2583.C
new file mode 100644
index 0000000..e80834c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2583.C
@@ -0,0 +1,45 @@
+// DR 2583 - Common initial sequence should consider over-alignment.
+// { dg-do compile { target c++11 } }
+
+#include <type_traits>
+
+struct A {
+ int i;
+ char c;
+};
+
+struct B {
+ int i;
+ alignas(8) char c;
+};
+
+struct C {
+ int i;
+ alignas(alignof(char)) char c;
+};
+
+struct D {
+ alignas(alignof(int)) int i;
+ char c;
+};
+
+struct S0 {
+ alignas(16) char x[128];
+ int i;
+};
+
+struct alignas(16) S1 {
+ char x[128];
+ int i;
+};
+
+#if __cpp_lib_is_layout_compatible >= 201907L
+static_assert (std::is_corresponding_member (&A::i, &B::i), "");
+static_assert (std::is_corresponding_member (&A::c, &B::c) == (alignof (char) == 8), "");
+static_assert (std::is_corresponding_member (&A::i, &C::i), "");
+static_assert (std::is_corresponding_member (&A::c, &C::c), "");
+static_assert (std::is_corresponding_member (&A::i, &D::i), "");
+static_assert (std::is_corresponding_member (&A::c, &D::c), "");
+static_assert (std::is_corresponding_member (&S0::x, &S1::x) == (alignof (char) == 16), "");
+static_assert (std::is_corresponding_member (&S0::i, &S1::i) == (alignof (char) == 16), "");
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp2a/is-layout-compatible3.C b/gcc/testsuite/g++.dg/cpp2a/is-layout-compatible3.C
index c548587..8f48ba8 100644
--- a/gcc/testsuite/g++.dg/cpp2a/is-layout-compatible3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/is-layout-compatible3.C
@@ -55,10 +55,10 @@ static_assert (!std::is_layout_compatible_v<K, L>);
static_assert (!std::is_layout_compatible_v<M, N>);
static_assert (!std::is_layout_compatible_v<O, P>);
static_assert (!std::is_layout_compatible_v<P, D>);
-static_assert (!std::is_layout_compatible_v<Q, R>);
+static_assert (std::is_layout_compatible_v<Q, R>);
static_assert (!std::is_layout_compatible_v<U, V>);
static_assert (!std::is_layout_compatible_v<A, I>);
static_assert (!std::is_layout_compatible_v<C, I>);
-static_assert (std::is_layout_compatible_v<E, F>);
+static_assert (!std::is_layout_compatible_v<E, F>);
static_assert (std::is_layout_compatible_v<G, H>);
static_assert (std::is_layout_compatible_v<C1, D1>);