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.
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