In short, the moment you enable integer-to-pointer conversions (assuming your target has a flat address space), you create pointer provenance problems whose only resolution is that some things have to be UB.
In short, the moment you enable integer-to-pointer conversions (assuming your target has a flat address space), you create pointer provenance problems whose only resolution is that some things have to be UB.
It may seem nitpicky, but the downside of relying on implementation defined or unspecified behavior is largely boxed and contained. E.g you might get a memory access error. UB is, in principle, completely unlimited in downside. And because of that, it often interacts badly with optimization passes, resulting in very strange bugs.
> It may seem nitpicky, but the downside of relying on implementation defined or unspecified behavior is largely boxed and contained.
... that is incoherent precisely because the interactions of provenance with optimizations isn't boxed and contained.
It's really not until people started putting the model into formal semantics that they realized "hey, wait a second, this means either most of our optimizations are wrong or our semantics are wrong" and the consensus is that it was the semantics that were broken.