On Tue, 25 Aug 2026, 19:44 Andrea Pinski, <[email protected]> wrote:
> On Tue, Aug 25, 2026 at 11:38 AM Andrea Pinski > <[email protected]> wrote: > > > > Sometimes the destructor will cause the optimizers not to see that > > _M_engaged has been to set to false (e.g. an external call). This > > means that we might get an uninitialized warning after the destructor > > in some cases. > > Adding `if (_M_engaged) __builtin_unreachable(); ` after the destructor > > will allow for the optimizations to know that the value of _M_engaged > > is 0 afterwards. This helps with optimizations and the uninitialized > warning. > > One minor change I did to this patch, the subject/summary line is now: > libstdc++: optional: Treat _M_engaged as being assumed to be false > after the destructor [PR127005] > OK with that summary line, thanks > I had forgot to update it before sending it out. Sorry about that. > > > > > PR libstdc++/127005 > > > > libstdc++-v3/ChangeLog: > > > > * include/std/optional (optional::_M_destroy): Add an assumption > on _M_engaged > > being false after the destructor call. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/warn/Wuninitialized-36.C: New test. > > > > Signed-off-by: Andrea Pinski <[email protected]> > > --- > > gcc/testsuite/g++.dg/warn/Wuninitialized-36.C | 26 +++++++++++++++++++ > > libstdc++-v3/include/std/optional | 3 +++ > > 2 files changed, 29 insertions(+) > > create mode 100644 gcc/testsuite/g++.dg/warn/Wuninitialized-36.C > > > > diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-36.C > b/gcc/testsuite/g++.dg/warn/Wuninitialized-36.C > > new file mode 100644 > > index 00000000000..aacb3f4e6a4 > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-36.C > > @@ -0,0 +1,26 @@ > > +// PR tree-optimization/127005 > > +// { dg-do compile { target c++17 } } > > +// { dg-options "-O2 -W -Wall" } > > + > > +#include <optional> > > + > > +void f(int *); > > +struct s1 > > +{ > > + int *a; > > + ~s1() > > + { > > + f(a); // { dg-bogus "uninitialized" } > > + } > > +}; > > + > > +struct conn { > > + void close() { guard.reset(); } > > + std::optional<s1> guard; > > +}; > > +extern conn make_conn(); > > +int main() > > +{ > > + conn c = make_conn(); > > + c.close(); > > +} > > diff --git a/libstdc++-v3/include/std/optional > b/libstdc++-v3/include/std/optional > > index d6fd33e8c2e..b56a3366ab7 100644 > > --- a/libstdc++-v3/include/std/optional > > +++ b/libstdc++-v3/include/std/optional > > @@ -303,6 +303,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > { > > _M_engaged = false; > > _M_payload._M_value.~_Stored_type(); > > + // After the destructor, _M_engaged should always be false, see > PR 127005. > > + if (_M_engaged) > > + __builtin_unreachable(); > > #if defined(__clang__) && __cpp_lib_optional >= 202106L // full > constexpr support > > if (std::is_constant_evaluated()) > > // Work around PR124910 for Clang. > > -- > > 2.43.0 > > >
