> As an example, a simple statement like "int a = b + c;" cannot cause a compile-time error about integer overflow, because the values of b and c are unknown.
Then there is no problem, because to use your terminology what happens is implementation defined. The compiler will emit the appropriate instructions and I will get whatever the hardware gives me. That is the K&R behaviour I said I was happy with.
The problem happens precisely under the conditions you side stepped: when the compiler does know the behaviour is undefined. The standard says the runtime can assume that undefined behaviour never happens; therefore, the compiler can do whatever it pleases should the UB condition arise. If the compiler takes that option it generally does whatever is fastest, which is typically to delete the code.
Consider this example:
if (buffer + len >= buffer_end || buffer + len < buffer)
loud_screaming_panic("len is out of range\n");
The second part of that condition can be true if len is negative or huge (beyond the end of the array), but adding a negative number to a pointer and indexing beyond the end of an array both yield undefined behaviour. Ergo the compiler is free to do what it damned well pleases with that condition, and gcc chose to delete it.
Unfortunately, the example is real. The buffer was a packet received from the internet, "len" was a field read from that packet. If the code accepted a garbage value in len, it would then index beyond the array and bad things would happen. The programmer put a test in there to prevent that. Gcc deleted it. A CVE was the result.
The point being: gcc knew the code triggered undefined behaviour. I guess there are three options when you see code like that: do what it did with your "int a = b + c;" example and just emit the instructions (which is what it would do with -O0), or print an error and refuse to compile the code because it has UB, or merrily do whatever it damned well pleased without so much as a warning and continue on its merry way. The first option is K&R behaviour. The second is very Rust like. Either of those would have been fine in this case. The third option lead to disaster, and I think the standard allowing it is inexplicable.
And now we get to the point where I have to say it: I don't think you know as much about C as you think you do. The C standard defines a lot of undefined behaviour, so much it would be near impossible to avoid it even if you wanted to. Worse as it happens, C programmers very deliberately don't avoid it. Instead they exploit it by assuming K&R behaviour.
Take your illustration as an example, "int a = b + c;". You conveniently assumed the compiler knew nothing about "b" and "c", but lets say we had some if tests above that constrained "b" and "c" values so that "b + c" must overflow. In that case the standard says a is undefined, and it can throw everything that depends on it's value away. But as a C programmer you must know C programmers regularly rely on the fact that integer overflow yields exactly the same result on all C implementations. For example, if we are calculating a checksum of a buffer modulo 256, every C programmer will just "uint8_t checksum" and sum every byte into it. But if you are right about overflow being UB (and you are), then every C compiler could put a check to see if the next add did overflow "checksum", and stop the loop immediately if so. There is no need to tell the programmer about this because it is UB, and the compiler can do whatever it damned well pleases in the name of speed.
No compiler does particular optimisation of course. Not because the standard doesn't allow it, but because they would be lynched. Unfortunately the threat of lynching didn't stop them from deleting the code above.
> Unless you accept that your expectations are wrong, you are condemned to live the same stress over and over and over! Good luck to you!
I didn't say you were wrong about what the standard says. I'm saying the stance taken by the standard on how undefined behaviour can be handled is insane. This attitude taken by the committee is one of the factors leading to government agencies saying C should be dropped. I am also saying you are wrong when you claim the compiler could not emit an error when it classified something as UB, and then deleted code or whatever. I think that is self evident from the points I made above.