On Mon, Feb 18, 2019 at 03:01:14PM -1000, Jason Merrill wrote: > But it's not clear to me that the standard actually allows this. I don't > think changing the active member of a union in the mem-initializer for > another member is reasonable.
There is in [expr.const]/2: an lvalue-to-rvalue conversion (7.1) that is applied to a glvalue that refers to a non-active member of a union or a subobject thereof; an assignment expression (8.18) or invocation of an assignment operator (15.8) that would change the active member of a union; in C++17 it seems, so maybe my union testcases are accepts-invalid. This has been introduced in P0137R1 and removed again in P1330R0. Does that mean e.g. following is valid in C++14, invalid in C++17 and valid again in C++20? Or has one of the above papers changed retroactively previous standards? // PR c++/89336 // { dg-do compile { target c++14 } } constexpr int foo () { union U { int a; long b; }; union V { union U u; short v; }; V w {}; w.u.a = w.v = w.u.b = 5L; return w.u.a; } static_assert (foo () == 5, ""); constexpr int bar () { union U { int a[5]; long b; }; union V { union U u; short v; }; V w {}; w.v = 5; w.u.a[3] = w.u.a[1] = w.v; return w.u.a[1] + w.u.a[3]; } static_assert (bar () == 10, ""); struct Z { int x, y; }; constexpr Z baz () { union W { Z a; long long w; }; W w {}; w.a = { 5, 0 }; w.a = { (int) (w.w = 17LL + w.a.x), 2 }; return w.a; } static_assert (baz ().x == 22, ""); static_assert (baz ().y == 2, ""); Jakub