[PATCH] c++: Implement P0466R5 __cpp_lib_is_layout_compatible compiler helpers [PR101539]

Jason Merrill jason@redhat.com
Thu Aug 12 16:06:33 GMT 2021

On 8/12/21 11:16 AM, Jakub Jelinek wrote:
> On Thu, Aug 12, 2021 at 10:33:20AM -0400, Jason Merrill wrote:
>>> The following patch implements __is_layout_compatible trait and
>>> __builtin_is_corresponding_member helper function for the
>>> std::is_corresponding_member template function.
>>> For now it implements the IMHO buggy but
>>> standard definition of layout-compatible and std::is_layout_compatible
>>> requirements (that Jonathan was discussing to change),
>>> including ignoring of alignment differences, mishandling of bitfields in unions
>>> and [[no_unique_address]] issues with empty classes.
>>> Until we know what exactly is decided in a CWG that seems better to trying
>>> to guess what the standard will say, but of course if you have different
>>> ideas, the patch can change.
>> I think it's clear that if corresponding fields have different offsets or
>> sizes, their containing types can't plausibly be layout-compatible. And if
>> two types have different sizes or alignments, they can't be
>> layout-compatible.
>> That leaves open the question of whether the presence or absence of no-op
>> alignment specifiers makes a difference; Richard Smith's proposal would make
>> that incompatible, I lean the other way, but don't feel strongly about it.
> Ok, so you prefer to change layout_compatible_type_p in anticipation of the
> future DR.

Yes; if the standard says something nonsensical, I prefer to figure out 
something more sensible to propose as a change.

> Given the g++.dg/cpp2a/is-layout-compatible3.C cases, shall that include:
>    if (TYPE_ALIGN (type1) != TYPE_ALIGN (type2))
>      return false;  /* Types with different alignment aren't layout-compatible.  */
>    if (!tree_int_cst_equal (TYPE_SIZE_UNIT (type1), TYPE_SIZE_UNIT (type2)))
>      return false;  /* Types with different sizes aren't layout-compatible.  */
> cases inside both the ENUMERAL_TYPE and CLASS_TYPE_P ifs (as e.g. the
> enumeral types can have the same underlying type including alignment and
> size, but the enumeral type itself could have different alignas)?
> I think I can't compare TYPE_SIZE_UNIT for the fallthrough same_type_p case
> because the type could be array with unspecified bounds and I expect
> same_type_p fails if the sizes or alignments are different.

Sounds good.

> And then also compare field offsets in struct and say members with different
> offsets aren't part of the common initial sequence (that would cover the
> struct S {};
> struct T {};
> struct U { [[no_unique_address]] S a1; [[no_unique_address]] S a2; [[no_unique_address]] S a3; };
> struct V { [[no_unique_address]] S b1; [[no_unique_address]] T b2; [[no_unique_address]] S b3; };
> case or alignas on the members as opposed to types)?


> What about DECL_ALIGN?  Shall that be relevant even when it doesn't change
> anything further (TYPE_ALIGN of the whole struct is already the same and
> field with higher DECL_ALIGN has the same field offset as in another struct
> where it has that offset because of the previous fields or is at start)?

I'm inclined to accept that.

> And finally, what about the union case?  Shall it check also bitfield vs.
> non-bitfield, bitfield size if bitfields?


> What about [[no_unique_address]]
> on the union members, shall that be relevant or not?  And DECL_ALIGN?
> E.g. the whole union can have the alignment,
> union alignas (16) A { short a; alignas (8) int b; };
> vs.
> union alignas (16) B { int a; short b; };
> All union fields have the same field offset of course (0), but above A::b
> has different alignment requirement than B::a.

I'd allow these differences.


More information about the Gcc-patches mailing list