diff --git a/libcxx/include/__config b/libcxx/include/__config index 77a71b6cf1cae..c197851f1c8fe 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -934,7 +934,7 @@ typedef __char32_t char32_t; # endif # endif -# if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(__no_thread_safety_analysis__) +# if __has_attribute(__no_thread_safety_analysis__) # define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((__no_thread_safety_analysis__)) # else # define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS diff --git a/libcxx/include/mutex b/libcxx/include/mutex index 78d8c8a9bcc6e..58474e0ca2b7a 100644 --- a/libcxx/include/mutex +++ b/libcxx/include/mutex @@ -320,7 +320,7 @@ public: }; template -_LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) { +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) { unique_lock<_L0> __u0(__l0, try_to_lock_t()); if (__u0.owns_lock()) { if (__l1.try_lock()) { @@ -335,7 +335,7 @@ _LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) { # ifndef _LIBCPP_CXX03_LANG template -_LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { int __r = 0; unique_lock<_L0> __u0(__l0, try_to_lock); if (__u0.owns_lock()) { @@ -350,8 +350,11 @@ _LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3 # endif // _LIBCPP_CXX03_LANG +// We're using unique_lock to implement the functions, which thread annotations don't support. So we have to disable +// the analysis inside the function. template -_LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) { +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) + _LIBCPP_ACQUIRE_CAPABILITY(__l0, __l1) { while (true) { { unique_lock<_L0> __u0(__l0); @@ -375,7 +378,7 @@ _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) { # ifndef _LIBCPP_CXX03_LANG template -void __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS void __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { while (true) { switch (__i) { case 0: { @@ -410,8 +413,14 @@ void __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { } } +// We're using unique_lock to implement the functions, which thread annotations don't support. So we have to disable +// the analysis inside the function. template -inline _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { +_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) +# if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 2101 + _LIBCPP_ACQUIRE_CAPABILITY(__l0, __l1, __l2, __l3...) +# endif +{ std::__lock_first(0, __l0, __l1, __l2, __l3...); } diff --git a/libcxx/test/extensions/clang/thread/thread.mutex/lock.verify.cpp b/libcxx/test/extensions/clang/thread/thread.mutex/lock.verify.cpp new file mode 100644 index 0000000000000..c83a87d4901c3 --- /dev/null +++ b/libcxx/test/extensions/clang/thread/thread.mutex/lock.verify.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// + +// GCC doesn't have thread safety attributes +// UNSUPPORTED: gcc + +// ADDITIONAL_COMPILE_FLAGS: -Wthread-safety -Wno-comment + +// XFAIL: FROZEN-CXX03-HEADERS-FIXME + +#include + +#include "test_macros.h" + +std::mutex m0; +std::mutex m1; +std::mutex m2; +std::mutex m3; + +void f1() { + std::lock(m0, m1); +} // expected-warning {{mutex 'm0' is still held at the end of function}} \ + expected-warning {{mutex 'm1' is still held at the end of function}} + +#if TEST_STD_VER >= 11 && TEST_CLANG_VER >= 2101 +void f2() { + std::lock(m0, m1, m2); +} // expected-warning {{mutex 'm0' is still held at the end of function}} \ + expected-warning {{mutex 'm1' is still held at the end of function}} \ + expected-warning {{mutex 'm2' is still held at the end of function}} + +void f3() { + std::lock(m0, m1, m2, m3); +} // expected-warning {{mutex 'm0' is still held at the end of function}} \ + expected-warning {{mutex 'm1' is still held at the end of function}} \ + expected-warning {{mutex 'm2' is still held at the end of function}} \ + expected-warning {{mutex 'm3' is still held at the end of function}} +#endif