[gcc r15-7868] libstdc++: Make std::unique_lock self-move-assignable

Jonathan Wakely redi@gcc.gnu.org
Thu Mar 6 16:47:13 GMT 2025


https://gcc.gnu.org/g:1ccbf8e2c2496779862a0153ed95459f72794521

commit r15-7868-g1ccbf8e2c2496779862a0153ed95459f72794521
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Mar 6 13:29:41 2025 +0000

    libstdc++: Make std::unique_lock self-move-assignable
    
    LWG 4172 was approved in Hagenberg, February 2025, fixing
    std::unique_lock and std::shared_lock to work correctly for
    self-move-assignment.
    
    Our std::shared_lock was already doing the right thing (contradicting
    the standard) so just add a comment there. Our std::unique_lock needs to
    be fixed to do the right thing.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/unique_lock.h (unique_lock::operator=): Fix for
            self-move-assignment.
            * include/std/shared_mutex (shared_lock::operator=): Add
            comment.
            * testsuite/30_threads/shared_lock/cons/lwg4172.cc: New test.
            * testsuite/30_threads/unique_lock/cons/lwg4172.cc: New test.
    
    Reviewed-by: Patrick Palka <ppalka@redhat.com>

Diff:
---
 libstdc++-v3/include/bits/unique_lock.h            |  9 ++-----
 libstdc++-v3/include/std/shared_mutex              |  2 ++
 .../30_threads/shared_lock/cons/lwg4172.cc         | 28 ++++++++++++++++++++++
 .../30_threads/unique_lock/cons/lwg4172.cc         | 27 +++++++++++++++++++++
 4 files changed, 59 insertions(+), 7 deletions(-)

diff --git a/libstdc++-v3/include/bits/unique_lock.h b/libstdc++-v3/include/bits/unique_lock.h
index 22ea7e9d7726..5b1518745caf 100644
--- a/libstdc++-v3/include/bits/unique_lock.h
+++ b/libstdc++-v3/include/bits/unique_lock.h
@@ -126,14 +126,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       unique_lock& operator=(unique_lock&& __u) noexcept
       {
-	if(_M_owns)
-	  unlock();
-
+	// _GLIBCXX_RESOLVE_LIB_DEFECTS
+	// 4172. unique_lock self-move-assignment is broken
 	unique_lock(std::move(__u)).swap(*this);
-
-	__u._M_device = 0;
-	__u._M_owns = false;
-
 	return *this;
       }
 
diff --git a/libstdc++-v3/include/std/shared_mutex b/libstdc++-v3/include/std/shared_mutex
index cbdf58f403b3..94c8532399d9 100644
--- a/libstdc++-v3/include/std/shared_mutex
+++ b/libstdc++-v3/include/std/shared_mutex
@@ -780,6 +780,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       shared_lock&
       operator=(shared_lock&& __sl) noexcept
       {
+	// _GLIBCXX_RESOLVE_LIB_DEFECTS
+	// 4172. unique_lock self-move-assignment is broken
 	shared_lock(std::move(__sl)).swap(*this);
 	return *this;
       }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/lwg4172.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/lwg4172.cc
new file mode 100644
index 000000000000..0a3bf10b8bb5
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/lwg4172.cc
@@ -0,0 +1,28 @@
+// { dg-do run { target c++14 } }
+
+// LWG 4172. unique_lock self-move-assignment is broken
+
+#include <shared_mutex>
+#include <testsuite_hooks.h>
+
+void
+test_self_move()
+{
+  struct Lockable
+  {
+    bool locked = false;
+    void lock_shared() { locked = true; }
+    void unlock_shared() { locked = false; }
+    bool try_lock_shared() { if (locked) return false; return locked = true; }
+  };
+
+  Lockable x;
+  std::shared_lock<Lockable> l(x);
+  l = std::move(l);
+  VERIFY(x.locked);
+}
+
+int main()
+{
+  test_self_move();
+}
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/lwg4172.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/lwg4172.cc
new file mode 100644
index 000000000000..37542b586a98
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/lwg4172.cc
@@ -0,0 +1,27 @@
+// { dg-do run { target c++11 } }
+
+// LWG 4172. unique_lock self-move-assignment is broken
+
+#include <mutex>
+#include <testsuite_hooks.h>
+
+void
+test_self_move()
+{
+  struct Lockable
+  {
+    bool locked = false;
+    void lock() { locked = true; }
+    void unlock() { locked = false; }
+  };
+
+  Lockable x;
+  std::unique_lock<Lockable> l(x);
+  l = std::move(l);
+  VERIFY(x.locked);
+}
+
+int main()
+{
+  test_self_move();
+}


More information about the Gcc-cvs mailing list