Clang Solves the Collatz Conjecture?
godbolt.org
godbolt.org
> An iteration statement whose controlling expression is not a constant expression, that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to terminate.
But this only applies to some iteration statements, not recursive functions. I don't know about C++ rules but since this optimization is also applied when compiling as C code (https://godbolt.org/z/K3uT2G), it seems to be invalid.
Yes, that's probably what happens internally.
> If the loop is infinite then you’re back in UB land.
I don't think so. At some point, clang forgets that the loop actually comes from a recursive function call, so it shouldn't be allowed to assume a finite loop.
https://blog.regehr.org/archives/140
https://news.ycombinator.com/item?id=1310105
Or is this one because "unsigned int" is not the same as a [0...infinity) "Integer" ?
The optimisation seems to be wrong; clang returns a constant 1, which assumes that the function is never called with n=0. Which is true for the Collatz conjecture (it starts at 1), but surely clang has no right to assume that n≥1?
https://en.cppreference.com/w/cpp/language/memory_model
https://en.cppreference.com/w/cpp/language/ub#Infinite_loop_...
clang appears to correctly detect that `collatz` only directly defines a result for `1`, and any other input expands to yet another recursive call to `collatz` (the parameter is irrelevant). To avoid infinite recursion, `collatz` must eventually be called with the value 1, so that's what clang concludes.