https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106385

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I was about to add the following to Bug 125236 (detect common misuses of the
C++ lib) and realized we already have this one for std::optional. Here's what I
was going to write in the other bug ...


Accessing the value of a std::optional<T> or std::expected<T,E> without
checking if it contains a value (an optional might be empty and an expected
might contain an error instead of a value).

void foo(int);
std::optional<int> o;
foo(*o);                      // UB
foo(o.value());               // throws std::bad_optional_access
if (o) foo(*o);               // OK
if (o.has_value()) foo(*o);   // OK

std::expected<int, std::error_code> e;
foo(*e);                      // UB
foo(e.value());               // throws std::bad_expected_access
if (e) foo(*e);               // OK
if (e.has_value()) foo(*e);   // OK


The monadic operations (and_then, or_else, transform, transform_error) are all
safe, they do the has_value() check internally.

It might be worth flagging the .value() cases that throw. Technically, they
have no UB because they check for a value, but it might still be a bug that the
user didn't check (they might not be prepared to handle an exception there).

The UB cases (*o and *e) would automatically by diagnosed by the analyzer if it
used the __glibcxx_assert assertions inside those operator* functions, as
suggested in Bug 106386.

Reply via email to