Repository navigation
CWG3219 [basic.types.trivial] Overeager no-op when no suitable value for value representation #980
Description
Activity
For the first, consider:
#include <cstring> int main(void) { int x = 42, *p = &x, *q = p + 1; std::memcpy(&p, &q, sizeof(p)); // giving `p` the value of `q` would _not_ lead to the // program having defined behaviour return *p; // Is the value of `p` here still `&x`? Prior to P2434R5, no. // After: Maybe, but no UB if not (could be `&errno`)—seems // unimplementable in general. }
this example contains UB -- the pointer
ppoints past the end of an object and is indirected (expr.unary.op#1).@safocl that's the point. Since giving past-the-end value would lead to UB, it is not given
Reacted by A. JiangReacted by Safocl Stollmannovic@safocl that's the point. Since giving past-the-end value would lead to UB, it is not given
Do you think this applies to the program as a whole? So the implementation should track where the pointer is used later?
In my opinion, no. Why do you think this was done in the first place? (There's a very detailed proposal on this topic, where everything is explained — I haven't seen anything like your reasoning there — the reason, as described there, is completely logical and clear.)In other words, the object's value is unchanged/the object does not receive a value when no such value exists.
AFAIR, I've seen some well-known C++ community members interpreting sentences like «if Condition, then X happens» as «implicit UB» when the Condition is not true. However, do not remember anyone interpreting object replacement as UB if not transparently replaceable, only that name/pointer/reference won't rebind.
It seems that the idea suggested in the initial topic is based solely on an example similar to this:
alignas(int) unsigned char a[sizeof(int)*3]; auto p1 = new(a) int{42}; auto p2 = new(a+sizeof(int)) int{24}; auto p1_past_the_end = p1+1;
Here the pointers
p1_past_the_endandp2may have the same value representation, but different values.Note that the status quo before P2434R5 already made the bit_cast case undefined behaviour when the value representation did not correspond to any value of the object's type.
but here the value of the pointer to int quite accommodates the value pointing past the end of an object
hubert-reinterpretcast commented
on Aug 17, 2026 MemberAuthorMore actionsbut here the value of the pointer to int quite accommodates the value pointing past the end of an object
The note is explaining one of the reasons why the proposed resolution does not provide some sort of replacement value in the case where the value representation did not correspond to any value of the object's type and, thereby, leaves such a case with UB from the
bit_castoperation. That pre-existing UB inbit_castis not strictly needed if the result is subject to a temporary materialization conversion.hubert-reinterpretcast commented
on Aug 17, 2026 MemberAuthorMore actionsHere the pointers
p1_past_the_endandp2may have the same value representation, but different values.Your example (assuming that you adjust it to ensure that
ahas the necessary alignment) is more about https://wg21.link/p0593 than anything else in the discussion.Reacted by A. JiangThe note is explaining one of the reasons why the proposed resolution does not provide some sort of replacement value in the case where the value representation did not correspond to any value of the object's type and, thereby, leaves such a case with UB from the
bit_castoperation. That pre-existing UB inbit_castis not strictly needed if the result is subject to a temporary materialization conversion.but all values of a pointer to int can be reproduced by a pointer to int
(assuming that you adjust it to ensure that
ahas the necessary alignment)Thanks, fixed.
- changed the title
[-][basic.types.trivial] Overeager no-op when no suitable value for value representation[/-][+]CWG3219 [basic.types.trivial] Overeager no-op when no suitable value for value representation[/+]on Aug 17, 2026 The 2nd example seems also addressed in CWG3039.
(so everything was brief and seemed elegant, it all started with the introduction of the [basic.types.trivial] section)
Full name of submitter (unless configured in github; will be published with the issue): Hubert Tong
Reference (section label): [basic.types.trivial]
Link to reflector thread (if any): N/A
Issue description:
The wording says:
In other words, the object's value is unchanged/the object does not receive a value when no such value exists.
This runs into problems with the following:
For the first, consider:
For the second, consider:
Note that the status quo before P2434R5 already made the bit_cast case undefined behaviour when the value representation did not correspond to any value of the object's type.
Suggested resolution: