When I answered this question, I wrote:
First, it is important to note that it is not only the behaviour of the user program that is undefined, it is
That's a pretty blurry line as a whole. The point is that the source code does not have a defined behaviour, which means the behaviour of the generated code is not well defined.
The compiler should, by all accounts behave in some defined way - but of course, that could be rather "random" (e.g. the compiler may choose to insert a random number into your calculation - or even a call to rand
- and it's still perfectly within the rights of the compiler). There are certainly cases where the compiler (ab)uses the fact that it knows something is undefined to make optimisations.
I would consider it a very poor implementation of the compiler if, for example, the compiler crashes or causes the hard-disk to be formatted, but I believe the compiler may be still "right" if it says "This is undefined, I refuse to compile it" [in some manner].
Of course, there are (quite a lot of) situations where something is undefined, not because the construct itself is undefined, but because it's "hard to define a single behaviour that is possible to implement in many places" - for example, using an invalid pointer (int* p = (int*) rand();
or use-after-free) is undefined, but the compiler may not know and understand if it's correct or not. Instead, it's up to the processor architecture what happens if you use a pointer at a random address, or after it has been freed. Both cases may result in a crash on one machine, not a crash, but an erroneous result on another, and in some cases "you won't notice that anything is wrong". This is clearly not the compiler's behaviour that is undefined, but the resulting program.