(out of order quoting in hopes of a better narrative)

https://gist.github.com/rygorous/e0f055bfb74e3d5f0af20690759...

A fine link, but oddly one that the two of us have already referenced in a different subthread. As stated there, I think there is room for a non-fwrapv approach that works just as well.

I try to use signed for all _numeric_ values (leaving unsigned for "bit strings"), because I'm quite sure that the number of bugs caused by the discontinuity at zero (for unsigned values) is much larger than the number caused by the discontinuity or UB at INT_MIN/INT_MAX.

I was probably unclear. I don't prefer unsigned to avoid the UB, but to get better generated assembly. While the unnecessary sign extension moves frequently come for free, occasionally they don't. I think the bugs are as likely to bite (or not bite) in either case, and need to be avoided by other means.

To see that with pretty much any program, just compare compiling with and without optimizations, or perhaps compare against a 20 or 30 year old C compiler if you can find one.

I'm less sure of that. You saw, for example, the current thread on RWT: https://www.realworldtech.com/forum/?threadid=182093&curpost...? I think the situation is rather that recent compilers do a better job with naive code, but are more likely to pessimize consciously constructed code. One major example of this is the most important micro-performance issue I've seen, which is the failure of GCC and Clang to reliably get µop macro-fusion bottom of loop branches. ICC does a much better job of keeping a decrement to zero tight to a fused jz, making the loop body one µop smaller.

These people are smart enough to get us into this
situation, so one would imagine they'd be smart enough
to least discuss this better way if it exists.

I lack that belief, but I'm not sure if that makes me more or less cynical than you. I think the issue is that almost everyone involved in standards process is likely to share a set of core philosophical beliefs about programming that may be self-consistent but not cover the full range of possibility. Consider as not quite parallels who becomes a US Supreme Court Justice or military commander, and how the selection process of being appointable affects the range of ideas espoused.

So what is this better way?

It might not be the solution, but I think that what you are not seeing is that there are other interpretations of "implementation defined" besides "always wrap" or saturate. You (and I think the standards committees) seem to want all non-UB programs to be fully deterministic, such that an emulator can always be written that will produce the same results as a real processor. I think there's room for an approach that says "if you stray beyond these rules, the real processor will decide your fate" without the "electric fence of death" approach currently taken by UB. I might be wrong to call this "implementation defined", but I think that's where it best fits in.

Consider a simple example: deallocating (e.g., free() in C, delete in C++) the same memory twice is UB, as is deallocating memory that was never allocated.

Let's use that an as example. What I want is for a standards compliant compiler to adopt this attitude: "It is unpredictable what happens if you call free twice in succession on the same pointer. Our compiler will try to issue a warning if it sees this happening, but the generated assembly is guaranteed to call free() twice. What happens after that is between you and your god."

I don't want is for it to be a guaranteed no-op. Nor do I want it the compiler to eliminate code based on the assumption that the second call never happens. I want it to warn if it can (which can be a fatal warning if desired) but to always generate assembly that makes the potentially crashing call. My contract with the compiler is limited to determinism of the assembly it generates on my behalf, and does not include any guarantees or restrictions on the runtime behavior.

My worry is that you (and others) don't consider this to be a standards compliant interpretation of "implementation defined", nor can it be "undefined behavior" if the compiler also reasons that UB can be assumed to never occur. Despite this, I think it would make the frequently make the compiler into a more useful tool.