This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115f. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-12-06
[Accepted as a DR at the November, 2023 meeting.]
Subclause 11.5.1 [class.union.general] paragraph 6 describes how union member subobjects are implicitly created by certain assignment operations that assign to union members. However, this description does not appear to properly handle the case of an anonymous union appearing within a union:
union A { int x; union { int y; }; }; void f() { A a = {.x = 1}; a.y = 2; }
Here, the expectation is that the assignment to a.y starts the lifetime of the anonymous union member subobject within A and also the int member subobject of the anonymous union member subobject. But the algorithm for computing S(a.y) determines that it is {a.y} and does not include the anonymous union member subobject.
Proposed resolution (approved by CWG 2023-06-17):
Change in 11.5.1 [class.union.general] paragraph 6 as follows:
In an assignment expression of the form E1 = E2 that uses either the built-in assignment operator (7.6.19 [expr.ass]) or a trivial assignment operator (11.4.6 [class.copy.assign]), for each element X of S(E1) and each anonymous union member X (11.5.2 [class.union.anon]) that is a member of a union and has such an element as an immediate subobject (recursively), if modification of X would have undefined behavior under 6.7.3 [basic.life], an object of the type of X is implicitly created in the nominated storage; no initialization is performed and the beginning of its lifetime is sequenced after the value computation of the left and right operands and before the assignment.
Editing note: Adding this rule into the definition of S would be more logical, but S(E) is a set of subexpressions of E and there is no form of expression that names an anonymous union member. Redefining S(E) to be a set of objects might be a better option.