Skip to content

Commit 57729dd

Browse files
committed
[libc++] Mark scoped_lock constructors as [[nodiscard]]
It's basically always a bug to discard a scoped_lock. Fixes #89388
1 parent 9a07d7e commit 57729dd

File tree

2 files changed

+44
-6
lines changed

2 files changed

+44
-6
lines changed

libcxx/include/mutex

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -427,10 +427,10 @@ class _LIBCPP_TEMPLATE_VIS scoped_lock;
427427
template <>
428428
class _LIBCPP_TEMPLATE_VIS scoped_lock<> {
429429
public:
430-
explicit scoped_lock() {}
430+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock() {}
431431
~scoped_lock() = default;
432432

433-
_LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t) {}
433+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t) {}
434434

435435
scoped_lock(scoped_lock const&) = delete;
436436
scoped_lock& operator=(scoped_lock const&) = delete;
@@ -445,13 +445,15 @@ private:
445445
mutex_type& __m_;
446446

447447
public:
448-
explicit scoped_lock(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) : __m_(__m) {
448+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(mutex_type& __m)
449+
_LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
450+
: __m_(__m) {
449451
__m_.lock();
450452
}
451453

452454
~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); }
453455

454-
_LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m)
456+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m)
455457
_LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
456458
: __m_(__m) {}
457459

@@ -465,9 +467,11 @@ class _LIBCPP_TEMPLATE_VIS scoped_lock {
465467
typedef tuple<_MArgs&...> _MutexTuple;
466468

467469
public:
468-
_LIBCPP_HIDE_FROM_ABI explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) { std::lock(__margs...); }
470+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) {
471+
std::lock(__margs...);
472+
}
469473

470-
_LIBCPP_HIDE_FROM_ABI scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) {}
474+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) {}
471475

472476
_LIBCPP_HIDE_FROM_ABI ~scoped_lock() {
473477
typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: no-threads
10+
// UNSUPPORTED: c++03, c++11, c++14
11+
12+
// <mutex>
13+
14+
// template <class ...Mutex> class scoped_lock;
15+
16+
// Test that we properly apply [[nodiscard]] to scoped_lock's constructors.
17+
18+
#include <mutex>
19+
20+
void f() {
21+
using M = std::mutex;
22+
M m0, m1, m2;
23+
// clang-format off
24+
std::scoped_lock<>{}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
25+
std::scoped_lock<M>{m0}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
26+
std::scoped_lock<M, M>{m0, m1}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
27+
std::scoped_lock<M, M, M>{m0, m1, m2}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
28+
29+
std::scoped_lock<>{std::adopt_lock}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
30+
std::scoped_lock<M>{std::adopt_lock, m0}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
31+
std::scoped_lock<M, M>{std::adopt_lock, m0, m1}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
32+
std::scoped_lock<M, M, M>{std::adopt_lock, m0, m1, m2}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
33+
// clang-format on
34+
}

0 commit comments

Comments
 (0)