This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
According to 6.7.1 [intro.memory] paragraph 3,
A memory location is either an object of scalar type or a maximal sequence of adjacent bit-fields all having non-zero width. [Note: Various features of the language, such as references and virtual functions, might involve additional memory locations that are not accessible to programs but are managed by the implementation. —end note] Two or more threads of execution (6.9.2 [intro.multithread]) can update and access separate memory locations without interfering with each other.
It is not clear how this relates to the permission granted in 11.4 [class.mem] paragraph 18 to inspect the common initial sequence of standard-layout structs that are members of a standard-layout union. If one thread is writing to the common initial sequence and another is reading from it via a different struct, that should constitute a data race, but the current wording does not clearly state that.
Additional notes (October, 2024)
(From submission #621.)
A similar concern arises for the following example:
union U { int x, y; } u; (u.x = 1, 0) + (u.y = 2, 0);
Possible resolution [SUPERSEDED]:
Change in 6.7.1 [intro.memory] paragraph 3 as follows:
A memory location is the storage occupied by the object representation of either an object of scalar type that is not a bit-field or a maximal sequence of adjacent bit-fields all having nonzero width. ...
CWG 2024-10-25
Subclause 6.9.1 [intro.execution] paragraph 10 does not cover unsequenced object creation that does not change any bits of storage, such as a placement new invoking a trivial default constructor. The original concern in this issue was addressed by P0137R1, adding the following in 11.4.2 [class.mfct] paragraph 28:
In a standard-layout union with an active member (11.5 [class.union]) 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.
Proposed resolution (approved by CWG 2024-11-08):
Change in 6.7.1 [intro.memory] paragraph 3 as follows:
A memory location is the storage occupied by the object representation of either an object of scalar type that is not a bit-field or a maximal sequence of adjacent bit-fields all having nonzero width. ...
Change in 6.9.1 [intro.execution] paragraph 10 and add bullets as follows:
... The value computations of the operands of an operator are sequenced before the value computation of the result of the operator.IfThe behavior is undefined ifis unsequenced relative to
- a side effect on a memory location (6.7.1 [intro.memory]) or
- starting or ending the lifetime of an object in a memory location
eitherand
- another side effect on the same memory location,
- starting or ending the lifetime of an object occupying storage that overlaps with the memory location, or
- a value computation using the value of any object in the same memory location,
theythe two evaluations are not potentially concurrent (6.9.2 [intro.multithread]), the behavior is undefined. [ Note: Starting the lifetime of an object in a memory location can end the lifetime of objects in other memory locations (6.7.3 [basic.life]). -- end note ][ Note: ... ]
[ Example:
void g(int i) { i = 7, i++, i++; // i becomes 9 i = i++ + 1; // the value of i is incremented i = i++ + i; // undefined behavior i = i + 1; // the value of i is incremented union U { int x, y; } u; (u.x = 1, 0) + (u.y = 2, 0); // undefined behavior }-- end example ]
Change in 6.9.2.2 [intro.races] paragraph 2 as follows, adding bullets:
Two expression evaluations conflict if one of themand the other one
- modifies (3.1 [defns.access]) a memory location (6.7.1 [intro.memory]) or
- starts or ends the lifetime of an object in a memory location
[Note 2: A modification can still conflict even if it does not alter the value of any bits. —end note]
- reads or modifies the same memory location or
- starts or ends the lifetime of an object occupying storage that overlaps with the memory location.