> Any time a compiler has elided some code it's because it has detected that it can because it's undefined, so in the context of this argument saying that the compiler cannot determine undefined behavior is not useful, as we are only talking about the times it already has.

No, you have it all backwards, and that's not what's happening. The compiler doesn't elide code because it is undefined. The compiler elides code because it would never be executed unless it happens to be called with arguments that would produce undefined behaviour anyway.

Take this, for example:

void foo(int *x){
*x=5;
if(x==NULL)abort();
}

The operation that is potentially UB here is the *x=5--if x happens to be NULL. But the compiler doesn't remove that assignment, it removes the check following it. And it does so because execution could never reach that check in a defined manner unless it is false: Either x is NULL, then the behaviour of the assignment is undefined (and commonly would cause a segfault, for example), or it is not NULL, then the check is superfluous.

And there is nothing necessarily wrong with that code: It could be (and such code is common) that it is actually never called with a NULL pointer, in which case the behaviour is perfectly defined.

If a compiler actually determines that your code will always exhibit undefined behaviour, then chances are it will indeed warn you, but that just isn't what usually happens, and it's not the cause of such bugs. The compiler doesn't say "this is undefined, therefore, let's screw it up", it's exactly the opposite: It says "if we assume that this code is never called with arguments that would cause undefined behaviour, what is the most efficient machine code that we could map it to?"

> The obvious interpretation of the request to have the compiler error is to have the compiler error in any case it would elide statements.

That would be plain idiotic. It is perfectly normal to have tons of dead code, erroring out in that case would just make it impossible to compile anything.

You have to consider that the compiler isn't interested in the elegant structure of your code, so it mashes it all up to figure out the most efficient machine code for the whole thing. So, you might have code that calls lots of functions on an array, say, where each function does a bounds check. Now, the compiler potentially will inline it all into one big spaghetti function. And then it will figure out that many of the bounds checks are actually redundant (again, under the assumption that the code doesn't invoke undefined behaviour), so it will remove any checks and corresponding error handling paths that it can prove to be implied by preceding checks, or it might try and combine multiple checks into one.

That does not mean that there is anything wrong with your code, or that you should manually remove all the redundant checks (which might not be redundant for other call sites, after all). The code is perfectly fine, and the compiler tries its best to remove anything that you don't actually need.

> Hard is not the same as impossible, and imperfect is often better than nothing.

True, but also besides the point. Compilers do issue warnings for lots of stuff, and more are added regularly, but much of what you are suggesting is actually not in any way even a coherent idea, and as such, is indeed not just hard, but impossible.