Comment by kzrdude
19 hours ago
Well you leave the C++ realm (execution model), as you should with UB and it depends on implementation. The implementation of the compiler was such that the two functions are placed after each other in the machine code; and if the first function doesn't return, then you continue executing into the code for the next function.
But the compiler assumes the function will make forward progress. If the function does that, it will return, so why doesn’t the compiler emit a function epilogue?
Because there is an infinite loop that makes the epilogue unreachable, so it is safe for the compiler to remove it!
Sure, that optimization interacts badly with the optimization that removes the infinite loop. But half the point of UB is to avoid needing to deal with such interactions, because they are defined out of existence.
The compiler can assume that the function will return, but it can also statically deduce that the function cannot return. That's a contradiction, so the compiler deduces that the function is simply UB when called, i.e. no need to emit an epilogue. It's the logical principle of explosion in compiler format, basically.
This makes no sense to me
If I think about asm:
function1:
function2:
main:
the 2nd call might happen internally due to branch prediction but in practice it shouldn't and the processor fixes this
Oh yeah and TFA also goes with:
> The funny bit is that C got this right.(...) but C included one more rule: loops whose controlling expression is a constant expression may not be assumed to terminate.
Well, duh! A broken clock is right twice a day it seems
With UB the compiler has no particular requirement to emit the 'ret'. (or, in the example, anything at all for the function)