[libcxx-commits] [libcxx] [libcxx] LWG4172 fix self-move-assignment in {unique|shared}_lock (PR #129542)

Mohamed Atef via libcxx-commits libcxx-commits at lists.llvm.org
Sat Nov 8 05:00:10 PST 2025


https://github.com/elhewaty updated https://github.com/llvm/llvm-project/pull/129542

>From 7b8417e47f602a3bc40287a5f31e8f2f5430f02b Mon Sep 17 00:00:00 2001
From: Mohamed Atef <mohamedatef1698 at gmail.com>
Date: Tue, 14 Oct 2025 11:13:58 +0300
Subject: [PATCH 1/2] [libcxx] LWG4172 fix self-move-assignment in
 {unique|shared}_lock

---
 libcxx/include/__mutex/unique_lock.h          |  8 +------
 libcxx/include/shared_mutex                   |  9 +-------
 .../move_assign.pass.cpp                      | 23 +++++++++++++------
 .../move_assign.pass.cpp                      | 11 ++++++++-
 4 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/libcxx/include/__mutex/unique_lock.h b/libcxx/include/__mutex/unique_lock.h
index aea93eb9b8c9b..5fd50282a3f2a 100644
--- a/libcxx/include/__mutex/unique_lock.h
+++ b/libcxx/include/__mutex/unique_lock.h
@@ -74,13 +74,7 @@ class unique_lock {
   }
 
   _LIBCPP_HIDE_FROM_ABI unique_lock& operator=(unique_lock&& __u) _NOEXCEPT {
-    if (__owns_)
-      __m_->unlock();
-
-    __m_        = __u.__m_;
-    __owns_     = __u.__owns_;
-    __u.__m_    = nullptr;
-    __u.__owns_ = false;
+    unique_lock{std::move(__u)}.swap(*this);
     return *this;
   }
 
diff --git a/libcxx/include/shared_mutex b/libcxx/include/shared_mutex
index 8c02e348e4de7..bbcdc6cf554f3 100644
--- a/libcxx/include/shared_mutex
+++ b/libcxx/include/shared_mutex
@@ -340,14 +340,7 @@ public:
   }
 
   _LIBCPP_HIDE_FROM_ABI shared_lock& operator=(shared_lock&& __u) _NOEXCEPT {
-    if (__owns_)
-      __m_->unlock_shared();
-    __m_        = nullptr;
-    __owns_     = false;
-    __m_        = __u.__m_;
-    __owns_     = __u.__owns_;
-    __u.__m_    = nullptr;
-    __u.__owns_ = false;
+    shared_lock{std::move(__u)}.swap(*this);
     return *this;
   }
 
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp
index 6d7838e8c6c95..b0647f06e4c43 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp
@@ -21,22 +21,31 @@
 
 #include "test_macros.h"
 
-
-int main(int, char**)
-{
-    {
+int main(int, char**) {
+  {
     typedef std::shared_timed_mutex M;
     M m0;
     M m1;
     std::shared_lock<M> lk0(m0);
     std::shared_lock<M> lk1(m1);
+
+    // Test self move assignment for lk0.
+    lk0 = std::move(lk0);
+    assert(lk0.mutex() == std::addressof(m0));
+    assert(lk0.owns_lock() == true);
+
     lk1 = std::move(lk0);
     assert(lk1.mutex() == std::addressof(m0));
     assert(lk1.owns_lock() == true);
     assert(lk0.mutex() == nullptr);
     assert(lk0.owns_lock() == false);
-    }
-    {
+
+    // Test self move assignment for lk1.
+    lk1 = std::move(lk1);
+    assert(lk1.mutex() == std::addressof(m0));
+    assert(lk1.owns_lock() == true);
+  }
+  {
     typedef nasty_mutex M;
     M m0;
     M m1;
@@ -47,7 +56,7 @@ int main(int, char**)
     assert(lk1.owns_lock() == true);
     assert(lk0.mutex() == nullptr);
     assert(lk0.owns_lock() == false);
-    }
+  }
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp
index 588d8332c4164..5b25cb6d5940d 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp
@@ -24,13 +24,22 @@ int main(int, char**) {
   std::unique_lock<checking_mutex> lk0(m0);
   std::unique_lock<checking_mutex> lk1(m1);
 
+  // Test self move assignment for lk0.
+  lk0 = std::move(lk0);
+  assert(lk0.mutex() == std::addressof(m0));
+  assert(lk0.owns_lock() == true);
+
   auto& result = (lk1 = std::move(lk0));
 
   assert(&result == &lk1);
   assert(lk1.mutex() == std::addressof(m0));
   assert(lk1.owns_lock());
   assert(lk0.mutex() == nullptr);
-  assert(!lk0.owns_lock());
+  assert(lk0.owns_lock() == false);
 
+  // Test self move assignment for lk1
+  lk1 = std::move(lk1);
+  assert(lk1.mutex() == std::addressof(m0));
+  assert(lk1.owns_lock() == true);
   return 0;
 }

>From dacefbd2a1ccf75c79dfd48593e1574e2f2b49b1 Mon Sep 17 00:00:00 2001
From: Mohamed Atef <mohamedatef1698 at gmail.com>
Date: Sat, 8 Nov 2025 14:15:55 +0200
Subject: [PATCH 2/2] [libcxx] Address comments to fix build failures

---
 libcxx/include/__mutex/unique_lock.h | 4 ++++
 libcxx/include/shared_mutex          | 1 +
 2 files changed, 5 insertions(+)

diff --git a/libcxx/include/__mutex/unique_lock.h b/libcxx/include/__mutex/unique_lock.h
index 5fd50282a3f2a..1dc7f94612eca 100644
--- a/libcxx/include/__mutex/unique_lock.h
+++ b/libcxx/include/__mutex/unique_lock.h
@@ -15,6 +15,7 @@
 #include <__memory/addressof.h>
 #include <__mutex/tag_types.h>
 #include <__system_error/throw_system_error.h>
+#include <__utility/move.h>
 #include <__utility/swap.h>
 #include <cerrno>
 
@@ -22,6 +23,8 @@
 #  pragma GCC system_header
 #endif
 
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Mutex>
@@ -163,5 +166,6 @@ inline _LIBCPP_HIDE_FROM_ABI void swap(unique_lock<_Mutex>& __x, unique_lock<_Mu
 }
 
 _LIBCPP_END_NAMESPACE_STD
+_LIBCPP_POP_MACROS
 
 #endif // _LIBCPP___MUTEX_UNIQUE_LOCK_H
diff --git a/libcxx/include/shared_mutex b/libcxx/include/shared_mutex
index bbcdc6cf554f3..6841a6d7d1887 100644
--- a/libcxx/include/shared_mutex
+++ b/libcxx/include/shared_mutex
@@ -138,6 +138,7 @@ template <class Mutex>
 #    include <__mutex/tag_types.h>
 #    include <__mutex/unique_lock.h>
 #    include <__system_error/throw_system_error.h>
+#    include <__utility/move.h>
 #    include <__utility/swap.h>
 #    include <cerrno>
 #    include <version>



More information about the libcxx-commits mailing list