https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65892
Melissa <myriachan at gmail dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |myriachan at gmail dot com --- Comment #12 from Melissa <myriachan at gmail dot com> --- This is broken in C++ as well, and in C++, the rules are much more clear that GCC isn't following them. Quoting the C++ Standard, revision 4296 (post-C++14?): 16. The "common initial sequence" of two standard-layout struct (Clause 9) 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 the corresponding entries have layout-compatible types and either neither entity is a bit-field or both are bit-fields with the same width. 19. In a standard-layout union with an active member (9.5) 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. A C++ conversion of the original example is below. I asked about the word "read" on the C++ Standard Discussion (std-discussion) mailing list, because it probably should also allow writing if it allows reads. As a result, I modified the below to only *read* in an aliasing way, to fully comply with the written word of the Standard. #include <cassert> struct t1 { int m; }; struct t2 { int m; }; union U { t1 s1; t2 s2; }; int f (t1 *p1, t2 *p2) { // union U visible here, p1->m and p2->m may alias // p1 is the active member; read from p2 per [class.mem]/19. if (p2->m < 0) p1->m = -p1->m; return p2->m; } int main (void) { union U u = { { -1 } }; int n = f (&u.s1, &u.s2); assert (1 == n); return 0; }