Date: Sun, 1 May 2022 21:29:55 -0400
The standard has the following to say about the common initial sequence,
[class.mem.general] paragraphs 23 through 26:
The common initial sequence of two standard-layout struct ([class.prop])
> types is the longest sequence of non-static data members and bit-fields in
> declaration order, starting with the first such entity in each of the
> structs, such that corresponding entities have layout-compatible types
> ([basic.types]), either both entities are declared with the
> no_unique_address attribute ([dcl.attr.nouniqueaddr]) or neither is, and
> either both entities are bit-fields with the same width or neither is a
> bit-field.
>
> Two standard-layout struct ([class.prop]) types are layout-compatible
> classes if their common initial sequence comprises all members and
> bit-fields of both classes ([basic.types]).
>
> Two standard-layout unions are layout-compatible if they have the same
> number of non-static data members and corresponding non-static data members
> (in any order) have layout-compatible types ([basic.types.general]).
>
> In a standard-layout union with an active member of struct type T1, it is
> permitted to read a non-static data member m of another union member of
> struct type T2 provided m is part of the common initial sequence of T1 and
> T2; the behavior is as if the corresponding member of T1 were nominated.
There is no requirement that corresponding non-static members have the same
alignment, so it appears that these two structs are layout-compatible, for
example:
struct A {
int i;
char c;
};
struct B {
int i;
alignas(8) char c;
};
However, typically, A will be laid out as iiiic... while B will be laid out
as iiii....c....... .
GCC actually reports <https://godbolt.org/z/dP9rE1e4c> that these two types
are *not* layout-compatible, but nothing in the standard says that they're
not. I think this is a defect in the standard and it should say that
corresponding entities must have the same alignment. Otherwise, I don't see
how paragraph 26 could make sense: it is not reasonable to expect that if a
union has members of types A and B, and one of those members is active, we
can read c from the other one, considering that the offsets are different.
If I'm right, it's sort of surprising that the GCC developers haven't
already reported an issue. Maybe it's been reported already and it's on a
version of the CWG issues list that hasn't been made public yet? Hopefully
someone on this list can tell me whether that's the case. If not, I will
submit this as a core issue according to the instructions here:
https://isocpp.org/std/submit-issue
[class.mem.general] paragraphs 23 through 26:
The common initial sequence of two standard-layout struct ([class.prop])
> types is the longest sequence of non-static data members and bit-fields in
> declaration order, starting with the first such entity in each of the
> structs, such that corresponding entities have layout-compatible types
> ([basic.types]), either both entities are declared with the
> no_unique_address attribute ([dcl.attr.nouniqueaddr]) or neither is, and
> either both entities are bit-fields with the same width or neither is a
> bit-field.
>
> Two standard-layout struct ([class.prop]) types are layout-compatible
> classes if their common initial sequence comprises all members and
> bit-fields of both classes ([basic.types]).
>
> Two standard-layout unions are layout-compatible if they have the same
> number of non-static data members and corresponding non-static data members
> (in any order) have layout-compatible types ([basic.types.general]).
>
> In a standard-layout union with an active member of struct type T1, it is
> permitted to read a non-static data member m of another union member of
> struct type T2 provided m is part of the common initial sequence of T1 and
> T2; the behavior is as if the corresponding member of T1 were nominated.
There is no requirement that corresponding non-static members have the same
alignment, so it appears that these two structs are layout-compatible, for
example:
struct A {
int i;
char c;
};
struct B {
int i;
alignas(8) char c;
};
However, typically, A will be laid out as iiiic... while B will be laid out
as iiii....c....... .
GCC actually reports <https://godbolt.org/z/dP9rE1e4c> that these two types
are *not* layout-compatible, but nothing in the standard says that they're
not. I think this is a defect in the standard and it should say that
corresponding entities must have the same alignment. Otherwise, I don't see
how paragraph 26 could make sense: it is not reasonable to expect that if a
union has members of types A and B, and one of those members is active, we
can read c from the other one, considering that the offsets are different.
If I'm right, it's sort of surprising that the GCC developers haven't
already reported an issue. Maybe it's been reported already and it's on a
version of the CWG issues list that hasn't been made public yet? Hopefully
someone on this list can tell me whether that's the case. If not, I will
submit this as a core issue according to the instructions here:
https://isocpp.org/std/submit-issue
-- *Brian Bi*
Received on 2022-05-02 01:30:08