Closed
Description
#include <memory>
#include <vector>
#include <cassert>
template <class T> struct foo { T x; };
class bar : public foo<double> {
public:
bar(double x) : foo{x} { }
std::shared_ptr<std::vector<char>> y;
};
int main(int argc, char **argv)
{
bar test = {12.34};
assert(test.x == 12.34);
assert(!test.y);
return 0;
}
I used clang-tidy based on Debian LLVM version 15.0.7 for my testing. (UPDATE: same for 17.0.1 and master branch)
Here is a short reproducer for clang-tidy misdiagnosing an uninitialized member in a constructor [clang-analyzer-optin.cplusplus.UninitializedObject] as well as misdiagnosing a garbage value in test.x [clang-analyzer-core.UndefinedBinaryOperatorResult] even though the assert verifies that the member is being initialized correctly in the constructor.
To reproduce the bug, execute
clang-tidy repro.cpp
2 warnings generated.
/home/buchner/repro/repro.cpp:9:4: warning: 1 uninitialized field at the end of the constructor call [clang-analyzer-optin.cplusplus.UninitializedObject]
bar(double x) : foo{x} { }
^
/home/buchner/repro/repro.cpp:5:35: note: uninitialized field 'this->foo::x'
template <class T> struct foo { T x; };
^
/home/buchner/repro/repro.cpp:15:15: note: Calling constructor for 'bar'
bar test = {12.34};
^~~~~~~
/home/buchner/repro/repro.cpp:9:4: note: 1 uninitialized field at the end of the constructor call
bar(double x) : foo{x} { }
^~~
/home/buchner/repro/repro.cpp:16:18: warning: The left operand of '==' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult]
assert(test.x == 12.34);
^
/usr/include/assert.h:93:27: note: expanded from macro 'assert'
(static_cast <bool> (expr) \
^~~~
/home/buchner/repro/repro.cpp:15:15: note: Calling constructor for 'bar'
bar test = {12.34};
^~~~~~~
/home/buchner/repro/repro.cpp:9:29: note: Returning without writing to 'this->x'
bar(double x) : foo{x} { }
^
/home/buchner/repro/repro.cpp:15:15: note: Returning from constructor for 'bar'
bar test = {12.34};
^~~~~~~
/home/buchner/repro/repro.cpp:16:18: note: The left operand of '==' is a garbage value
assert(test.x == 12.34);
^
/usr/include/assert.h:93:27: note: expanded from macro 'assert'
(static_cast <bool> (expr) \
The culprit appears to be the brace initialization of the base struct foo within the constructor initializer list of class bar.
To verify result correctness, execute the following, which does not hit the assert.
clang++ -g -o repro repro.cpp && ./repro