Compiling the following example with -O2 on Clang 3.9 results in the reproFunction returning garbage (1.9038e+185) when called in main:
Code
double reproFunction(const Eigen::Matrix3d& R_in)
{
const Eigen::Matrix3d R = R_in;
Eigen::Matrix3d Q = R.cwiseAbs();
if(R(1,2) < 2) {
Eigen::Vector3d n{0, 1, R(1, 2)};
double s2 = R(1,2);
s2 /= n.norm();
}
return R(1, 2);
}
int main() {
Eigen::Matrix3d R;
R = Eigen::Matrix3d::Zero(3,3);
// This fails - reproFunction(R) returns 0
R(1, 2) = 0.7;
double R12 = reproFunction(R);
bool are_they_equal = (R12 == R(1,2));
std::cout << "R12 == R(1,2): " << are_they_equal << std::endl;
std::cout << "R12: " << R12 << std::endl;
std::cout << "R(1, 2): " << R(1, 2) << std::endl;
}
Output
R12 == R(1,2): 0
R12: 1.9036e+185
R(1, 2): 0.7
reproFunction, initializes R (which is const) by assignment from R_in. It returns R(1, 2). Between the assignment and the return, reproFunction uses R in several operations, but none of them should be able to change R. Removing any of those operations results in reproFunction returning the correct value.
This behavior does not appear in any of the following cases:
- The program is compiled with Clang 3.5, Clang 4.0,or g++-5.4.
- The optimization level is
-O1or lower - Eigen 3.2.10 is used instead of Eigen 3.3.3
Now the question: Is this behavior due to a bug I've missed in the code above, a bug in Eigen 3.3.3, or a bug in Clang 3.9?
A self-contained reproduction example can be found at https://github.com/avalenzu/eigen-clang-weirdness.