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.
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.

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)?

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.

        Jakub

Reply via email to