Skip to content

Conversation

ldionne
Copy link
Member

@ldionne ldionne commented Apr 19, 2024

It's basically always a bug to discard a scoped_lock or a unique_lock.

Fixes #89388

@ldionne ldionne requested a review from a team as a code owner April 19, 2024 15:06
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Apr 19, 2024
@llvmbot
Copy link
Member

llvmbot commented Apr 19, 2024

@llvm/pr-subscribers-libcxx

Author: Louis Dionne (ldionne)

Changes

It's basically always a bug to discard a scoped_lock.

Fixes #89388


Full diff: https://github.com/llvm/llvm-project/pull/89397.diff

2 Files Affected:

  • (modified) libcxx/include/mutex (+10-6)
  • (added) libcxx/test/libcxx/thread/thread.lock/thread.lock.scoped/nodiscard.verify.cpp (+34)
diff --git a/libcxx/include/mutex b/libcxx/include/mutex
index 12fae9a88b9d7e..0d2b5914bc4fd5 100644
--- a/libcxx/include/mutex
+++ b/libcxx/include/mutex
@@ -427,10 +427,10 @@ class _LIBCPP_TEMPLATE_VIS scoped_lock;
 template <>
 class _LIBCPP_TEMPLATE_VIS scoped_lock<> {
 public:
-  explicit scoped_lock() {}
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock() {}
   ~scoped_lock() = default;
 
-  _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t) {}
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t) {}
 
   scoped_lock(scoped_lock const&)            = delete;
   scoped_lock& operator=(scoped_lock const&) = delete;
@@ -445,13 +445,15 @@ private:
   mutex_type& __m_;
 
 public:
-  explicit scoped_lock(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) : __m_(__m) {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(mutex_type& __m)
+      _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
+      : __m_(__m) {
     __m_.lock();
   }
 
   ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); }
 
-  _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m)
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m)
       _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
       : __m_(__m) {}
 
@@ -465,9 +467,11 @@ class _LIBCPP_TEMPLATE_VIS scoped_lock {
   typedef tuple<_MArgs&...> _MutexTuple;
 
 public:
-  _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) { std::lock(__margs...); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) {
+    std::lock(__margs...);
+  }
 
-  _LIBCPP_HIDE_FROM_ABI scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) {}
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) {}
 
   _LIBCPP_HIDE_FROM_ABI ~scoped_lock() {
     typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
diff --git a/libcxx/test/libcxx/thread/thread.lock/thread.lock.scoped/nodiscard.verify.cpp b/libcxx/test/libcxx/thread/thread.lock/thread.lock.scoped/nodiscard.verify.cpp
new file mode 100644
index 00000000000000..86c1953457837f
--- /dev/null
+++ b/libcxx/test/libcxx/thread/thread.lock/thread.lock.scoped/nodiscard.verify.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-threads
+// UNSUPPORTED: c++03, c++11, c++14
+
+// <mutex>
+
+// template <class ...Mutex> class scoped_lock;
+
+// Test that we properly apply [[nodiscard]] to scoped_lock's constructors.
+
+#include <mutex>
+
+void f() {
+  using M = std::mutex;
+  M m0, m1, m2;
+  // clang-format off
+  std::scoped_lock<>{}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
+  std::scoped_lock<M>{m0}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
+  std::scoped_lock<M, M>{m0, m1}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
+  std::scoped_lock<M, M, M>{m0, m1, m2}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
+
+  std::scoped_lock<>{std::adopt_lock}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
+  std::scoped_lock<M>{std::adopt_lock, m0}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
+  std::scoped_lock<M, M>{std::adopt_lock, m0, m1}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
+  std::scoped_lock<M, M, M>{std::adopt_lock, m0, m1, m2}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
+  // clang-format on
+}

Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! LGTM!

Copy link
Contributor

@philnik777 philnik777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we wait with this until I land #87094? It should be just about ready to go. Also, IMO this patch should cover unique_lock too, since it's basically the same.

@ldionne ldionne changed the title [libc++] Mark scoped_lock constructors as [[nodiscard]] [libc++] Mark scoped_lock and unique_lock constructors as [[nodiscard]] Apr 25, 2024
@ldionne ldionne force-pushed the review/nodiscard-scoped-lock branch from 57729dd to 71e59be Compare April 25, 2024 14:44
It's basically always a bug to discard a scoped_lock.

Fixes llvm#89388
@ldionne ldionne force-pushed the review/nodiscard-scoped-lock branch from 71e59be to 5d0cb37 Compare April 25, 2024 14:52
@ldionne ldionne merged commit 7eac39f into llvm:main Apr 29, 2024
@ldionne ldionne deleted the review/nodiscard-scoped-lock branch April 29, 2024 18:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

scoped_lock constructor could be nodiscard like in libstdc++

4 participants