https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80635
Evgeniy Dushistov <dushistov at mail dot ru> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |dushistov at mail dot ru --- Comment #19 from Evgeniy Dushistov <dushistov at mail dot ru> --- I saw problem similar `std::optional` may be unitialized case as desribed here with boost::variant/boost::optional (c++11) and std::variant/std::optional (c++17), but in my case I have not only gcc warning, but valgrind also reports problem, is it the same problem or gcc code generation bug? ``` //Foo.cpp #include "Foo.hpp" struct FooOpaque {}; FooOpaque *Foo_new() { auto p = new FooOpaque; return p; } void Foo_free(FooOpaque *p) { delete p; } std::variant<std::optional<Foo>, std::string> f_res_opt(int var) { switch (var) { case 0: return {std::optional<Foo>{Foo{Foo_new()}}}; case 1: return {std::optional<Foo>{}}; case 2: return {std::string{}}; default: std::abort(); } } ``` ``` //Foo.hpp #include <memory> #include <optional> #include <variant> struct FooOpaque; FooOpaque *Foo_new(); void Foo_free(FooOpaque *); struct FooDeleter { void operator()(FooOpaque *p) { Foo_free(p); } }; using Foo = std::unique_ptr<FooOpaque, FooDeleter>; std::variant<std::optional<Foo>, std::string> f_res_opt(int var); ``` ``` //main.cpp #include "Foo.hpp" int main() { auto res1 = f_res_opt(0); auto res1_ok = std::get<std::optional<Foo>>(std::move(res1)); printf("step 2\n"); auto res2 = f_res_opt(1); auto res2_ok = std::get<std::optional<Foo>>(std::move(res2)); printf("step 3\n"); auto res3 = f_res_opt(2); auto res3_ok = std::get<std::string>(std::move(res3)); } ``` gcc reports: ``` g++ -ggdb -Ofast -Wall -Wextra -std=c++17 -pedantic main.cpp Foo.cpp In file included from main.cpp:1: Foo.hpp: In function 'int main()': Foo.hpp:10:43: warning: 'res2_ok.std::_Head_base<0, FooOpaque*, false>::_M_head_impl' may be used uninitialized in this function [-Wmaybe-uninitialized] 10 | void operator()(FooOpaque *p) { Foo_free(p); } | ~~~~~~~~^~~ main.cpp:12:8: note: 'res2_ok.std::_Head_base<0, FooOpaque*, false>::_M_head_impl' was declared here 12 | auto res2_ok = std::get<std::optional<Foo>>(std::move(res2)); | ^~~~~~~ In file included from main.cpp:1: Foo.hpp:10:43: warning: 'res1_ok.std::_Head_base<0, FooOpaque*, false>::_M_head_impl' may be used uninitialized in this function [-Wmaybe-uninitialized] 10 | void operator()(FooOpaque *p) { Foo_free(p); } | ~~~~~~~~^~~ main.cpp:6:8: note: 'res1_ok.std::_Head_base<0, FooOpaque*, false>::_M_head_impl' was declared here 6 | auto res1_ok = std::get<std::optional<Foo>>(std::move(res1)); | ^~~~~~~ ``` but valgrind also reports: valgrind -v ./a.out ``` ==7858== Conditional jump or move depends on uninitialised value(s) ==7858== at 0x109374: ~unique_ptr (unique_ptr.h:288) ==7858== by 0x109374: _M_destroy (optional:257) ==7858== by 0x109374: _M_reset (optional:277) ==7858== by 0x109374: ~_Optional_payload (optional:398) ==7858== by 0x109374: ~_Optional_base (optional:471) ==7858== by 0x109374: ~optional (optional:656) ==7858== by 0x109374: main (main.cpp:12) ``` gcc 9.1.0 and valgrind 3.15.0.GIT