[PATCH] libstdc++: optional: Set _M_engaged after the call to destructor [PR127005]

Andrea Pinski andrew.pinski@oss.qualcomm.com
Tue Aug 25 18:43:49 GMT 2026


On Tue, Aug 25, 2026 at 11:38 AM Andrea Pinski
<andrew.pinski@oss.qualcomm.com> 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]

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 <andrew.pinski@oss.qualcomm.com>
> ---
>  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
>


More information about the Libstdc++ mailing list