Here is a short program to count the number of divisors of an integer. The program does work correctly. The problem is, however, that under the -O3
optimization flag of the current trunk of the Clang C++ compiler (version 3.3, trunk 180686) the behavior of the program changes and the result is no longer correct.
Code
Here's the code:
#include <iostream>
constexpr unsigned long divisors(unsigned long n, unsigned long c)
{
// This is supposed to sum 1 anytime a divisor shows up
// in the recursion
return !c ? 0 : !(n % c) + divisors(n, c - 1);
}
int main()
{
// Here I print the number of divisors of 9 numbers! (from 1 to 9)
for (unsigned long i = 1; i < 10; ++i)
std::cout << i << " has " << divisors(i, i) << " divisors" << std::endl;
}
Correct Behavior
Here's the compile command used, and the correct and expected output, which the program exhibits under normal circumstances:
clang++ -O2 -std=c++11 -stdlib=libc++ -lcxxrt -ldl sample.cpp -o sample
./sample
1 has 1 divisors
2 has 2 divisors
3 has 2 divisors
4 has 3 divisors
5 has 2 divisors
6 has 4 divisors
7 has 2 divisors
8 has 4 divisors
9 has 3 divisors
Incorrect Behavior
This is the command line used that produces the binary that gives incorrect output. Notice that the only change is the optimization flag (-O2
to -O3
.)
clang++ -O3 -std=c++11 -stdlib=libc++ -lcxxrt -ldl sample.cpp -o sample
./sample
1 has 1 divisors
2 has 2 divisors
3 has 2 divisors
4 has 1 divisors
5 has 2 divisors
6 has 3 divisors
7 has 2 divisors
8 has 2 divisors
9 has 2 divisors
EDIT
I've updated to tip of trunk, clang version 3.4 (trunk 183073). The behavior does not reproduce anymore, it should have been fixed somehow already. Anyone who knows what issue was it, if there was one actually verified and fixed, please feel free to provide an answer. If there was none verified, a regression may happen.