Yep, working exactly like the C++11 standard would allow it to, which is a pretty major bug IMO for C.
Conversation
It's an even bigger bug for languages like Rust because it breaches memory safety. People can also run into it while trying to use ! to make their code type check by using `loop {}` as a to prove to the compiler that the function doesn't return to avoid unsafe for unreachable().
1
2
Yet, if your code actually hits that case, instead of infinite looping it can fall through to what should be an impossible program state per the semantics of the language because the compiler removed the call to the function. This allows breaching memory safety in safe Rust.
1
2
2
However, Rust code isn't untrusted, so unsoundness like this isn't a security vulnerability. It can definitely become a security vulnerability, but while I think it's likely that people are going to hit this in practice, I don't think it's likely it will ship as a security bug.
1
1
2
On the other hand, (crazy) people use LLVM to implement a VMs with sandbox semantics. So bugs like this can definitely be exploited by attackers. In this case, LLVM explicitly chose to keep the buggy optimization rather than removing it until it's fixed. Don't use LLVM like that.
1
1
Bug #965 from 2006 which has been renamed to "Infinite loops are optimized out in languages without forward progress guarantees (C, Rust)".
bugs.llvm.org/show_bug.cgi?i
Unfortunately, the C++ standard change is now being used to justify this bug as correct or sane for LLVM too.
1
1
2
As far as I can tell, the way it works is a bug for C++ too, due to how it happens with infinite recursion which appears to simply be defined as infinitely recursing in C or C++ and the only sane way to handle that is guaranteeing a stack overflow. That's doubly broken in LLVM.
1
1
2
It also really makes no sense to require other languages to inject an intrinsic causing a side effect into each loop which is going to destroy their compile time and runtime performance. The semantics added to C++ are strange and very niche vs. massively hurting real world perf.
1
1
I think it reflects incredibly poorly on LLVM that they did not simply disable the incorrect, unsafe optimization in 2006 as soon as it was pointed out with the burden placed on people who want the optimization to implement it correctly... it's not even an important optimization.
1
1
3
It only kicks in when there is a function it knows is pure being called, with the result unused. It doesn't apply if it inlines the function. I would be surprised if it had much impact at all and yet it's kept there as a soundness hole. I have other bigger examples of this too.


