https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88223
--- Comment #11 from rguenther at suse dot de <rguenther at suse dot de> --- On Wed, 28 Nov 2018, joseph at codesourcery dot com wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88223 > > --- Comment #10 from joseph at codesourcery dot com <joseph at codesourcery > dot com> --- > On Wed, 28 Nov 2018, rguenth at gcc dot gnu.org wrote: > > > Hmm, OTOH the C standard specifies that the store to u.b.b makes it the > > u.b the active member and it makes the old contents undefined. That > > would mean when loading u.a.b after the store we cannot rely on the > > exact value we get but at least the bits touched by u.b.b should be > > up-to-date (which is enough to show breakage). I thought about > > using > > In my view, storing to u.b.b should be equivalent to loading u.b (a > type-punning operation if u.a was previously the active member), storing > the new value of u.b.b in a copy of the loaded value of u.b, and storing > that result back in u.b (making u.b the active member of u). (So if bits > set in u.a are not padding in u.b, and not part of the space occupied by > u.b.b, they should be preserved.) OK, that's convenient enough to support for the compiler. Unfortunately that means my testcases become valid and we still miscompile them... Now, for type-punning to be valid the union has to be visible in the access, but this visibility can be lost in the middle-end given the middle-end implements sth more conservative. Still that a store is a punning access makes the following valid? union u { struct { int i; int j; } x; struct { float f; float g; } y; }; union u A; float foo (union u *B) { u->x.i = 0; A.y.g = 1.0; return u->y.f; } is this valid punning of u->x.i to u->y.f (int->float) because the actual type-punning is implicitely done via A.y.g = 1.0? Of course the constraint is that B points to A. We certainly happily re-order the store and load via u.