Ah yes, branching on poison
is UB. But that is very different from saying that using poison
is UB. For example, arithmetic on poison
is allowed -- and it returns poison
. Loading poison
from memory into a local variable is also fine. (This is all talking about LLVM, not C/C++).
For undef vs poison, see this paper.
@InfernoDeity thanks for digging this out! But then if we take those lines at face value, how do you explain the UB when branching on poison
, which is present in most compilers (I assume this is what John Regehr explored in the post @zackw referred to above)? Do all compilers just ignore the spec?
I think we all agree on this one. And we also agree that the committee likely wants this to be the case even for a hand-written memcpy
. But the only reason a hand-written memcpy
is fine in modern compilers is that it doesn't branch on the uninitialized values it read from memory -- that's why memcpy
is okay but memcmp
is UB. And the standard doesn't reflect this, to my knowledge.
Btw, in Rust we currently avoid these problems by saying that loading uninit memory into i*
or bool
or so is immediate UB. Loading it into MaybeUninit<u8>
is okay, but you cannot branch on such a value. In other words, we successfully avoid the question.