Let's say that's too difficult for compiler writers, so we bring back time travelling UB. That implies UB on a future execution path means the entire execution path has no semantics. We now have to ensure there is no UB on any future execution path to meet our goal. There are basically 4 options:
1. Rely on programmers to never write UB. This has not worked out historically.
2. Compilers must detect and/or prevent all UB statically. This is obviously impossible.
3. Runtimes must exhaustively detect and/or prevent all UB. This is both infeasible and expensive.
4. Give up on semantics for essentially all nontrivial programs. This is the situation today, but if we're going to make this the official position why should we even have a standard?
1. Make a list of all UB
2. Define the sensible compiler behavior in each case (for example, let MAX_INT+1 to calculate into MIN_INT on x86_64, just because `add` on x86_64 does that)
3. Treat this as a part of a standard, when compiling the code.
This approach allows to have different compiler behavior on different architectures, which are better suited for the architecture. Maybe on some architectures `add` on signed numbers will generate a CPU exception on overflow, so define this as a way to behave and go with it.
What if there’s UB & it is aliased? Some other pointer of a different type in scope also references the same value. The “sensible” thing to do when the value is updated through the alias is…?
int f(int x) {
static int y[] = {42, 43};
return y[x];
}
What behavior should `f(-1)` or `f(100)` have? What is sensible? *(y-1)
and more than likely segfault, or return the value at that address if it's somehow valid.