* [PATCH] c++: Alignment changes to layout compatibility/common initial sequence - DR2583 @ 2022-11-14 11:28 Jakub Jelinek 2022-11-15 22:57 ` Jason Merrill 0 siblings, 1 reply; 4+ messages in thread From: Jakub Jelinek @ 2022-11-14 11:28 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches Hi! Working virtually out of Baker Island. 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. Lightly tested (on is-layout*/is-corresponding*/dr2583.C only) so far, ok if it passes full bootstrap/regtest? Or do we need different rules? 2022-11-14 Jakub Jelinek <jakub@redhat.com> * typeck.cc (next_common_initial_seqence): 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. --- gcc/cp/typeck.cc.jj 2022-11-13 04:53:46.010682269 -1200 +++ gcc/cp/typeck.cc 2022-11-13 23:14:41.355180354 -1200 @@ -1833,6 +1833,8 @@ next_common_initial_seqence (tree &memb1 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, tr 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); --- gcc/testsuite/g++.dg/cpp2a/is-layout-compatible3.C.jj 2021-08-18 21:42:27.414421719 -1200 +++ gcc/testsuite/g++.dg/cpp2a/is-layout-compatible3.C 2022-11-13 23:20:05.008776825 -1200 @@ -55,10 +55,10 @@ static_assert (!std::is_layout_compatibl 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>); --- gcc/testsuite/g++.dg/DRs/dr2583.C.jj 2022-11-13 22:58:11.977640606 -1200 +++ gcc/testsuite/g++.dg/DRs/dr2583.C 2022-11-13 23:18:04.630414835 -1200 @@ -0,0 +1,31 @@ +// 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 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 (alignof (char) == 8 || !std::is_corresponding_member (&A::c, &B::c), ""); +static_assert (alignof (char) == 16 || !std::is_corresponding_member (&S0::x, &S1::x), ""); +static_assert (alignof (char) == 16 || !std::is_corresponding_member (&S0::i, &S1::i), ""); +#endif Jakub ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] c++: Alignment changes to layout compatibility/common initial sequence - DR2583 2022-11-14 11:28 [PATCH] c++: Alignment changes to layout compatibility/common initial sequence - DR2583 Jakub Jelinek @ 2022-11-15 22:57 ` Jason Merrill 2022-11-16 10:35 ` [PATCH] c++, v2: " Jakub Jelinek 0 siblings, 1 reply; 4+ messages in thread From: Jason Merrill @ 2022-11-15 22:57 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches On 11/14/22 01:28, Jakub Jelinek wrote: > Hi! > > Working virtually out of Baker Island. > > 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. Agreed. > Lightly tested (on is-layout*/is-corresponding*/dr2583.C only) so far, > ok if it passes full bootstrap/regtest? > Or do we need different rules? > > 2022-11-14 Jakub Jelinek <jakub@redhat.com> > > * typeck.cc (next_common_initial_seqence): 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. > > --- gcc/cp/typeck.cc.jj 2022-11-13 04:53:46.010682269 -1200 > +++ gcc/cp/typeck.cc 2022-11-13 23:14:41.355180354 -1200 > @@ -1833,6 +1833,8 @@ next_common_initial_seqence (tree &memb1 > 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, tr > 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); > --- gcc/testsuite/g++.dg/cpp2a/is-layout-compatible3.C.jj 2021-08-18 21:42:27.414421719 -1200 > +++ gcc/testsuite/g++.dg/cpp2a/is-layout-compatible3.C 2022-11-13 23:20:05.008776825 -1200 > @@ -55,10 +55,10 @@ static_assert (!std::is_layout_compatibl > 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>); > --- gcc/testsuite/g++.dg/DRs/dr2583.C.jj 2022-11-13 22:58:11.977640606 -1200 > +++ gcc/testsuite/g++.dg/DRs/dr2583.C 2022-11-13 23:18:04.630414835 -1200 > @@ -0,0 +1,31 @@ > +// 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 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 (alignof (char) == 8 || !std::is_corresponding_member (&A::c, &B::c), ""); Maybe std_is_corresponding_member (&A::c, &B::c) == (alignof (char) == 8) ? Could also use an alignas(alignof(type)) case to verify that it matches a member with no alignas. > +static_assert (alignof (char) == 16 || !std::is_corresponding_member (&S0::x, &S1::x), ""); > +static_assert (alignof (char) == 16 || !std::is_corresponding_member (&S0::i, &S1::i), ""); > +#endif > > Jakub > ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] c++, v2: Alignment changes to layout compatibility/common initial sequence - DR2583 2022-11-15 22:57 ` Jason Merrill @ 2022-11-16 10:35 ` Jakub Jelinek 2022-11-16 13:09 ` Jason Merrill 0 siblings, 1 reply; 4+ messages in thread From: Jakub Jelinek @ 2022-11-16 10:35 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches On Tue, Nov 15, 2022 at 05:57:26PM -0500, Jason Merrill wrote: > > 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. > > Agreed. > > > +#if __cpp_lib_is_layout_compatible >= 201907L > > +static_assert (std::is_corresponding_member (&A::i, &B::i), ""); > > +static_assert (alignof (char) == 8 || !std::is_corresponding_member (&A::c, &B::c), ""); > > Maybe > > std_is_corresponding_member (&A::c, &B::c) == (alignof (char) == 8) > > ? > > Could also use an alignas(alignof(type)) case to verify that it matches a > member with no alignas. So like this? The previous patch successfully bootstrapped/regtested on x86_64-linux and i686-linux, only the new testcase changed and that one passes make check, ok for trunk? 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. --- gcc/cp/typeck.cc.jj 2022-11-13 04:53:46.010682269 -1200 +++ gcc/cp/typeck.cc 2022-11-13 23:14:41.355180354 -1200 @@ -1833,6 +1833,8 @@ next_common_initial_sequence (tree &memb1 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, tr 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); --- gcc/testsuite/g++.dg/cpp2a/is-layout-compatible3.C.jj 2021-08-18 21:42:27.414421719 -1200 +++ gcc/testsuite/g++.dg/cpp2a/is-layout-compatible3.C 2022-11-13 23:20:05.008776825 -1200 @@ -55,10 +55,10 @@ static_assert (!std::is_layout_compatibl 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>); --- gcc/testsuite/g++.dg/DRs/dr2583.C.jj 2022-11-16 11:28:03.200831332 +0100 +++ gcc/testsuite/g++.dg/DRs/dr2583.C 2022-11-16 11:31:34.421978999 +0100 @@ -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 Jakub ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] c++, v2: Alignment changes to layout compatibility/common initial sequence - DR2583 2022-11-16 10:35 ` [PATCH] c++, v2: " Jakub Jelinek @ 2022-11-16 13:09 ` Jason Merrill 0 siblings, 0 replies; 4+ messages in thread From: Jason Merrill @ 2022-11-16 13:09 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches On 11/16/22 05:35, Jakub Jelinek wrote: > On Tue, Nov 15, 2022 at 05:57:26PM -0500, Jason Merrill wrote: >>> 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. >> >> Agreed. >> >>> +#if __cpp_lib_is_layout_compatible >= 201907L >>> +static_assert (std::is_corresponding_member (&A::i, &B::i), ""); >>> +static_assert (alignof (char) == 8 || !std::is_corresponding_member (&A::c, &B::c), ""); >> >> Maybe >> >> std_is_corresponding_member (&A::c, &B::c) == (alignof (char) == 8) >> >> ? >> >> Could also use an alignas(alignof(type)) case to verify that it matches a >> member with no alignas. > > So like this? > The previous patch successfully bootstrapped/regtested on x86_64-linux and > i686-linux, only the new testcase changed and that one passes make check, ok > for trunk? OK. > 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. > > --- gcc/cp/typeck.cc.jj 2022-11-13 04:53:46.010682269 -1200 > +++ gcc/cp/typeck.cc 2022-11-13 23:14:41.355180354 -1200 > @@ -1833,6 +1833,8 @@ next_common_initial_sequence (tree &memb1 > 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, tr > 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); > --- gcc/testsuite/g++.dg/cpp2a/is-layout-compatible3.C.jj 2021-08-18 21:42:27.414421719 -1200 > +++ gcc/testsuite/g++.dg/cpp2a/is-layout-compatible3.C 2022-11-13 23:20:05.008776825 -1200 > @@ -55,10 +55,10 @@ static_assert (!std::is_layout_compatibl > 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>); > --- gcc/testsuite/g++.dg/DRs/dr2583.C.jj 2022-11-16 11:28:03.200831332 +0100 > +++ gcc/testsuite/g++.dg/DRs/dr2583.C 2022-11-16 11:31:34.421978999 +0100 > @@ -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 > > > Jakub > ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-11-16 13:09 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-11-14 11:28 [PATCH] c++: Alignment changes to layout compatibility/common initial sequence - DR2583 Jakub Jelinek 2022-11-15 22:57 ` Jason Merrill 2022-11-16 10:35 ` [PATCH] c++, v2: " Jakub Jelinek 2022-11-16 13:09 ` Jason Merrill
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).