[libcxx-commits] [libcxx] [libc++] Add thread safety annotations for std::lock (PR #154078)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Aug 19 00:48:39 PDT 2025
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/154078
>From 1184792211c0d9a526545514186d6182d4eaffed Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 18 Aug 2025 10:46:02 +0200
Subject: [PATCH] [libc++] Add thread safety annotations for std::lock
---
libcxx/include/__config | 2 +-
libcxx/include/mutex | 12 ++++--
.../clang/thread/thread.mutex/lock.verify.cpp | 43 +++++++++++++++++++
3 files changed, 53 insertions(+), 4 deletions(-)
create mode 100644 libcxx/test/extensions/clang/thread/thread.mutex/lock.verify.cpp
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..8e21076322b6b 100644
--- a/libcxx/include/mutex
+++ b/libcxx/include/mutex
@@ -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);
@@ -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: {
@@ -410,8 +413,11 @@ 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)
+ _LIBCPP_ACQUIRE_CAPABILITY(__l0, __l1, __l2, __l3...) {
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..0b3f87068589a
--- /dev/null
+++ b/libcxx/test/extensions/clang/thread/thread.mutex/lock.verify.cpp
@@ -0,0 +1,43 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+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}}
+
+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}}
More information about the libcxx-commits
mailing list