The clang-tidy packaged in ubuntu 20.04 (10.0.0) seems to be choking on a fairly simple block of code that involves structured bindings and move operations:
#include <memory>
#include <tuple>
struct T {
~T() {
if(ptr != nullptr) { // clang-tidy is convinced ptr is uninitialized when the tuple is destroyed.
}
}
T(T&& rhs) : ptr(rhs.ptr) {
rhs.ptr = nullptr;
}
// Be very explicit for the sake of the MCVE.
T() = default;
T(const T&) = delete;
T& operator=(T&&) = delete;
T& operator=(const T&) = delete;
int* ptr = nullptr;
};
std::tuple<T, T> foo();
void bar() {
auto [a, b] = foo();
T x = std::move(a);
T y = std::move(b);
}
void baz() {
auto a_b = foo();
auto& a = std::get<0>(a_b);
auto& b = std::get<1>(a_b);
T x = std::move(a);
T y = std::move(b);
}
Clang-tidy is flagging bar()
with:
warning: The left operand of '!=' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult] if(ptr != nullptr) {
Whereas baz()
is just fine.
I would rather not turn off that test altogether, and adding a NOLINT on that comparison line is... iffy at best, especially since it lives in an unrelated library. (as in the library has no idea these objects will end up in a tuple).
So my question is: Is there some way to fix this while keeping the structured binding? Or alternatively, is clang-tidy actually right here, and I am horribly misunderstanding how structured bindings work?
FWIW, clang-tidy is being invoked through cmake like so:
set(CMAKE_CXX_CLANG_TIDY clang-tidy;--format-style=file)