Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libcxx/include/__config
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 14 additions & 5 deletions libcxx/include/mutex
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ public:
};

template <class _L0, class _L1>
_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()) {
Expand All @@ -335,7 +335,7 @@ _LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) {
# ifndef _LIBCPP_CXX03_LANG

template <class _L0, class _L1, class _L2, class... _L3>
_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()) {
Expand All @@ -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 <class _L0, class _L1>
_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);
Expand All @@ -375,7 +378,7 @@ _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) {
# ifndef _LIBCPP_CXX03_LANG

template <class _L0, class _L1, class _L2, class... _L3>
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: {
Expand Down Expand Up @@ -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 <class _L0, class _L1, class _L2, class... _L3>
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...);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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

// <mutex>

// GCC doesn't have thread safety attributes
// UNSUPPORTED: gcc

// ADDITIONAL_COMPILE_FLAGS: -Wthread-safety -Wno-comment

// XFAIL: FROZEN-CXX03-HEADERS-FIXME

#include <mutex>

#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