> Having implementation defined behavior would imply non-portability.
Not any more than UB does. Ie if you avoid the implementation defined behaviour, your code is perfectly portable.
(And otherwise your code could probe for what the implementation defined behaviour is, and adjust accordingly. No such luck with UB.)
However I do agree with you that it's hard to remove UB from the spec. The spec's failing is in having so much UB in the first place.
If that is what you want, compilers have various flags that let you in essence do that. But the next problem with that is (1) that it's possible existing code may be suddenly and unpredictably lose performance, and (2) now you need to provide some other well-defined behavior for those UB cases, and (3) the selling point of generics/macros/inlining may be reduced.
How many relevant UB's are there? I don't know. How much perf would code common lose? I don't know. To be sure, I fully acknowledge that removing UB from the spec may be the right thing to do, but it's also easy enough to find possible problems with that strategy; I'm just pointing out the complexities, which is a lot easier than solving them or knowing which are irrelevant.