[Bug c++/80635] std::optional and bogus -Wmaybe-uninitialized warning
dushistov at mail dot ru
gcc-bugzilla@gcc.gnu.org
Wed Jul 3 19:51:00 GMT 2019
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
More information about the Gcc-bugs
mailing list