When the following (reduced) code is compiled with Clang 8.0.0, with -O1 optimization level (or above), Valgrind detects a Conditional jump or move depends on uninitialised value(s) error in the resulting binary. No warnings are printed, even with the -Wall -pedantic arguments enabled. Adding -fsanitize=undefined just makes the issue go away, but doesn't report anything useful. And it is most likely not a false positive (from Valgrind), since this reduced version originated from a real codebase, where it caused a noticeable error.
When compiled with GCC 9.1.1, there is no UB.
#include <algorithm>
#include <iostream>
class X {
public:
int a, b;
X(int a) : a(a), b(0) {}
bool h() {
std::initializer_list<bool> bs({a == 0, a != 0 || b == 0});
return std::any_of(bs.begin(), bs.end(), [](bool t) { return t; });
}
};
void f(X g) {
std::cout << "";
}
int main(int argc, const char **) {
X i(argc);
f(i);
if (i.h())
std::cout << "";
}
Sure, the std::initializer_list<bool> bs({a == 0, a != 0 || b == 0}); line is a bit weird, and the outer parentheses are unnecessary. But according to cppinsights.io, this just adds a copy constructor call, so it should be fine? (See the same code in Compiler Explorer.)
Also, note that all of the seemingly useless details in the code are necessary to trigger the issue.
So, even if in most cases, the answer to this question is "no": Is this a bug in Clang? Or are we just missing something about the quirkiness of modern C++?
I think we ran into an issue that is already reported thrice in the LLVM bug tracker:
And is most likely related to (or might even be the same as) this SO question:
The current standing of the LLVM people on this, is: "... we ought to issue a warning on this." Well, yes, I agree.
Oh, C++... :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With