[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