Skip to content

Commit 22f8ced

Browse files
authored
[libc++] Add the thread safety annotations unconditionally (#117497)
For these annotations to do anything you need `-Wthread-safety`, in which case users most likely enable them anyways. This avoids that users have to explictly define a macro just to use the feature they already had to opt-in to.
1 parent c9d9c3e commit 22f8ced

15 files changed

+138
-124
lines changed

libcxx/.clang-format

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ AllowShortLambdasOnASingleLine: All
1616
AttributeMacros: [
1717
'_ALIGNAS_TYPE',
1818
'_ALIGNAS',
19+
'_LIBCPP_ACQUIRE_CAPABILITY',
20+
'_LIBCPP_ACQUIRE_SHARED_CAPABILITY',
1921
'_LIBCPP_ALIGNOF',
2022
'_LIBCPP_ALWAYS_INLINE',
23+
'_LIBCPP_CAPABILITY',
2124
'_LIBCPP_CONSTEXPR_SINCE_CXX14',
2225
'_LIBCPP_CONSTEXPR_SINCE_CXX17',
2326
'_LIBCPP_CONSTEXPR_SINCE_CXX20',
@@ -41,9 +44,13 @@ AttributeMacros: [
4144
'_LIBCPP_NO_UNIQUE_ADDRESS',
4245
'_LIBCPP_NOALIAS',
4346
'_LIBCPP_OVERRIDABLE_FUNC_VIS',
47+
'_LIBCPP_RELEASE_CAPABILITY',
48+
'_LIBCPP_REQUIRES_CAPABILITY',
49+
'_LIBCPP_SCOPED_LOCKABLE',
4450
'_LIBCPP_STANDALONE_DEBUG',
4551
'_LIBCPP_TEMPLATE_DATA_VIS',
46-
'_LIBCPP_THREAD_SAFETY_ANNOTATION',
52+
'_LIBCPP_TRY_ACQUIRE_CAPABILITY',
53+
'_LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY',
4754
'_LIBCPP_USING_IF_EXISTS',
4855
'_LIBCPP_WEAK',
4956
]

libcxx/docs/UserDocumentation.rst

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,6 @@ enable or disable extended libc++ behavior.
114114
ensure that the appropriate experimental library (usually ``libc++experimental.a``)
115115
is linked into their program.
116116

117-
**_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS**:
118-
This macro is used to enable -Wthread-safety annotations on libc++'s
119-
``std::mutex`` and ``std::lock_guard``. By default, these annotations are
120-
disabled and must be manually enabled by the user.
121-
122117
**_LIBCPP_HARDENING_MODE**:
123118
This macro is used to choose the :ref:`hardening mode <using-hardening-modes>`.
124119

libcxx/include/__config

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -903,23 +903,6 @@ typedef __char32_t char32_t;
903903
# define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
904904
# endif
905905

906-
// Work around the attribute handling in clang. When both __declspec and
907-
// __attribute__ are present, the processing goes awry preventing the definition
908-
// of the types. In MinGW mode, __declspec evaluates to __attribute__, and thus
909-
// combining the two does work.
910-
# if defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) && defined(__clang__) && \
911-
__has_attribute(acquire_capability) && !defined(_MSC_VER)
912-
# define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS 1
913-
# else
914-
# define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS 0
915-
# endif
916-
917-
# if _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS
918-
# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x))
919-
# else
920-
# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x)
921-
# endif
922-
923906
# if _LIBCPP_STD_VER >= 20
924907
# define _LIBCPP_CONSTINIT constinit
925908
# elif __has_attribute(__require_constant_initialization__)
@@ -1147,6 +1130,60 @@ typedef __char32_t char32_t;
11471130
# define _LIBCPP_PREFERRED_NAME(x)
11481131
# endif
11491132

1133+
# if __has_cpp_attribute(_Clang::__scoped_lockable__)
1134+
# define _LIBCPP_SCOPED_LOCKABLE [[_Clang::__scoped_lockable__]]
1135+
# else
1136+
# define _LIBCPP_SCOPED_LOCKABLE
1137+
# endif
1138+
1139+
# if __has_cpp_attribute(_Clang::__capability__)
1140+
# define _LIBCPP_CAPABILITY(...) [[_Clang::__capability__(__VA_ARGS__)]]
1141+
# else
1142+
# define _LIBCPP_CAPABILITY(...)
1143+
# endif
1144+
1145+
# if __has_attribute(__acquire_capability__)
1146+
# define _LIBCPP_ACQUIRE_CAPABILITY(...) __attribute__((__acquire_capability__(__VA_ARGS__)))
1147+
# else
1148+
# define _LIBCPP_ACQUIRE_CAPABILITY(...)
1149+
# endif
1150+
1151+
# if __has_cpp_attribute(_Clang::__try_acquire_capability__)
1152+
# define _LIBCPP_TRY_ACQUIRE_CAPABILITY(...) [[_Clang::__try_acquire_capability__(__VA_ARGS__)]]
1153+
# else
1154+
# define _LIBCPP_TRY_ACQUIRE_CAPABILITY(...)
1155+
# endif
1156+
1157+
# if __has_cpp_attribute(_Clang::__acquire_shared_capability__)
1158+
# define _LIBCPP_ACQUIRE_SHARED_CAPABILITY [[_Clang::__acquire_shared_capability__]]
1159+
# else
1160+
# define _LIBCPP_ACQUIRE_SHARED_CAPABILITY
1161+
# endif
1162+
1163+
# if __has_cpp_attribute(_Clang::__try_acquire_shared_capability__)
1164+
# define _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(...) [[_Clang::__try_acquire_shared_capability__(__VA_ARGS__)]]
1165+
# else
1166+
# define _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(...)
1167+
# endif
1168+
1169+
# if __has_cpp_attribute(_Clang::__release_capability__)
1170+
# define _LIBCPP_RELEASE_CAPABILITY [[_Clang::__release_capability__]]
1171+
# else
1172+
# define _LIBCPP_RELEASE_CAPABILITY
1173+
# endif
1174+
1175+
# if __has_cpp_attribute(_Clang::__release_shared_capability__)
1176+
# define _LIBCPP_RELEASE_SHARED_CAPABILITY [[_Clang::__release_shared_capability__]]
1177+
# else
1178+
# define _LIBCPP_RELEASE_SHARED_CAPABILITY
1179+
# endif
1180+
1181+
# if __has_attribute(__requires_capability__)
1182+
# define _LIBCPP_REQUIRES_CAPABILITY(...) __attribute__((__requires_capability__(__VA_ARGS__)))
1183+
# else
1184+
# define _LIBCPP_REQUIRES_CAPABILITY(...)
1185+
# endif
1186+
11501187
# if defined(_LIBCPP_ABI_MICROSOFT) && __has_declspec_attribute(empty_bases)
11511188
# define _LIBCPP_DECLSPEC_EMPTY_BASES __declspec(empty_bases)
11521189
# else

libcxx/include/__mutex/lock_guard.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,22 @@
1919
_LIBCPP_BEGIN_NAMESPACE_STD
2020

2121
template <class _Mutex>
22-
class _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) lock_guard {
22+
class _LIBCPP_SCOPED_LOCKABLE lock_guard {
2323
public:
2424
typedef _Mutex mutex_type;
2525

2626
private:
2727
mutex_type& __m_;
2828

2929
public:
30-
[[__nodiscard__]]
31-
_LIBCPP_HIDE_FROM_ABI explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
30+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI explicit lock_guard(mutex_type& __m) _LIBCPP_ACQUIRE_CAPABILITY(__m)
3231
: __m_(__m) {
3332
__m_.lock();
3433
}
3534

36-
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI lock_guard(mutex_type& __m, adopt_lock_t)
37-
_LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
35+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_REQUIRES_CAPABILITY(__m)
3836
: __m_(__m) {}
39-
_LIBCPP_HIDE_FROM_ABI ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); }
37+
_LIBCPP_RELEASE_CAPABILITY _LIBCPP_HIDE_FROM_ABI ~lock_guard() { __m_.unlock(); }
4038

4139
lock_guard(lock_guard const&) = delete;
4240
lock_guard& operator=(lock_guard const&) = delete;

libcxx/include/__mutex/mutex.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
_LIBCPP_BEGIN_NAMESPACE_STD
2323

24-
class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex {
24+
class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_CAPABILITY("mutex") mutex {
2525
__libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;
2626

2727
public:
@@ -36,9 +36,9 @@ class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mut
3636
~mutex() _NOEXCEPT;
3737
# endif
3838

39-
void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability());
40-
bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
41-
void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
39+
_LIBCPP_ACQUIRE_CAPABILITY() void lock();
40+
_LIBCPP_TRY_ACQUIRE_CAPABILITY(true) bool try_lock() _NOEXCEPT;
41+
_LIBCPP_RELEASE_CAPABILITY void unlock() _NOEXCEPT;
4242

4343
typedef __libcpp_mutex_t* native_handle_type;
4444
_LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; }

libcxx/include/mutex

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -434,24 +434,23 @@ public:
434434
};
435435

436436
template <class _Mutex>
437-
class _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> {
437+
class _LIBCPP_SCOPED_LOCKABLE scoped_lock<_Mutex> {
438438
public:
439439
typedef _Mutex mutex_type;
440440

441441
private:
442442
mutex_type& __m_;
443443

444444
public:
445-
[[nodiscard]]
446-
_LIBCPP_HIDE_FROM_ABI explicit scoped_lock(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
445+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(mutex_type& __m) _LIBCPP_ACQUIRE_CAPABILITY(__m)
447446
: __m_(__m) {
448447
__m_.lock();
449448
}
450449

451-
~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); }
450+
_LIBCPP_RELEASE_CAPABILITY _LIBCPP_HIDE_FROM_ABI ~scoped_lock() { __m_.unlock(); }
452451

453-
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m)
454-
_LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
452+
[[nodiscard]]
453+
_LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_REQUIRES_CAPABILITY(__m)
455454
: __m_(__m) {}
456455

457456
scoped_lock(scoped_lock const&) = delete;

libcxx/include/shared_mutex

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ struct _LIBCPP_EXPORTED_FROM_ABI __shared_mutex_base {
183183
};
184184

185185
# if _LIBCPP_STD_VER >= 17
186-
class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_THREAD_SAFETY_ANNOTATION(__capability__("shared_mutex")) shared_mutex {
186+
class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_CAPABILITY("shared_mutex") shared_mutex {
187187
__shared_mutex_base __base_;
188188

189189
public:
@@ -194,35 +194,23 @@ public:
194194
shared_mutex& operator=(const shared_mutex&) = delete;
195195

196196
// Exclusive ownership
197-
_LIBCPP_HIDE_FROM_ABI void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_capability__()) {
198-
return __base_.lock();
199-
}
200-
_LIBCPP_HIDE_FROM_ABI bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) {
201-
return __base_.try_lock();
202-
}
203-
_LIBCPP_HIDE_FROM_ABI void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_capability__()) {
204-
return __base_.unlock();
205-
}
197+
_LIBCPP_ACQUIRE_CAPABILITY() _LIBCPP_HIDE_FROM_ABI void lock() { return __base_.lock(); }
198+
_LIBCPP_TRY_ACQUIRE_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool try_lock() { return __base_.try_lock(); }
199+
_LIBCPP_RELEASE_CAPABILITY _LIBCPP_HIDE_FROM_ABI void unlock() { return __base_.unlock(); }
206200

207201
// Shared ownership
208-
_LIBCPP_HIDE_FROM_ABI void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_shared_capability__()) {
209-
return __base_.lock_shared();
210-
}
211-
_LIBCPP_HIDE_FROM_ABI bool try_lock_shared()
212-
_LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) {
202+
_LIBCPP_ACQUIRE_SHARED_CAPABILITY _LIBCPP_HIDE_FROM_ABI void lock_shared() { return __base_.lock_shared(); }
203+
_LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool try_lock_shared() {
213204
return __base_.try_lock_shared();
214205
}
215-
_LIBCPP_HIDE_FROM_ABI void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_shared_capability__()) {
216-
return __base_.unlock_shared();
217-
}
206+
_LIBCPP_RELEASE_SHARED_CAPABILITY _LIBCPP_HIDE_FROM_ABI void unlock_shared() { return __base_.unlock_shared(); }
218207

219208
// typedef __shared_mutex_base::native_handle_type native_handle_type;
220209
// _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return __base::unlock_shared(); }
221210
};
222211
# endif
223212

224-
class _LIBCPP_EXPORTED_FROM_ABI
225-
_LIBCPP_THREAD_SAFETY_ANNOTATION(__capability__("shared_timed_mutex")) shared_timed_mutex {
213+
class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_CAPABILITY("shared_timed_mutex") shared_timed_mutex {
226214
__shared_mutex_base __base_;
227215

228216
public:
@@ -233,17 +221,17 @@ public:
233221
shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
234222

235223
// Exclusive ownership
236-
void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_capability__());
237-
bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true));
224+
void lock() _LIBCPP_ACQUIRE_CAPABILITY();
225+
_LIBCPP_TRY_ACQUIRE_CAPABILITY(true) bool try_lock();
238226
template <class _Rep, class _Period>
239-
_LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
240-
_LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) {
227+
_LIBCPP_TRY_ACQUIRE_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool
228+
try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) {
241229
return try_lock_until(chrono::steady_clock::now() + __rel_time);
242230
}
243231

244232
template <class _Clock, class _Duration>
245-
_LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time)
246-
_LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) {
233+
_LIBCPP_TRY_ACQUIRE_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool
234+
try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) {
247235
unique_lock<mutex> __lk(__base_.__mut_);
248236
if (__base_.__state_ & __base_.__write_entered_) {
249237
while (true) {
@@ -270,20 +258,20 @@ public:
270258
return true;
271259
}
272260

273-
void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_capability__());
261+
_LIBCPP_RELEASE_CAPABILITY void unlock();
274262

275263
// Shared ownership
276-
void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_shared_capability__());
277-
bool try_lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true));
264+
_LIBCPP_ACQUIRE_SHARED_CAPABILITY void lock_shared();
265+
_LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(true) bool try_lock_shared();
278266
template <class _Rep, class _Period>
279-
_LIBCPP_HIDE_FROM_ABI bool try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
280-
_LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) {
267+
_LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool
268+
try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time) {
281269
return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
282270
}
283271

284272
template <class _Clock, class _Duration>
285-
_LIBCPP_HIDE_FROM_ABI bool try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time)
286-
_LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) {
273+
_LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool
274+
try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time) {
287275
unique_lock<mutex> __lk(__base_.__mut_);
288276
if ((__base_.__state_ & __base_.__write_entered_) ||
289277
(__base_.__state_ & __base_.__n_readers_) == __base_.__n_readers_) {
@@ -302,7 +290,7 @@ public:
302290
return true;
303291
}
304292

305-
void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_shared_capability__());
293+
_LIBCPP_RELEASE_SHARED_CAPABILITY void unlock_shared();
306294
};
307295

308296
template <class _Mutex>

libcxx/test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@
1111

1212
// <mutex>
1313

14-
// This test does not define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS so it
15-
// should compile without any warnings or errors even though this pattern is not
16-
// understood by the thread safety annotations.
14+
// This test does not set -Wthread-safety so it should compile without any warnings or errors even though this pattern
15+
// is not understood by the thread safety annotations.
1716

1817
#include <mutex>
1918

libcxx/test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// On Windows Clang bugs out when both __declspec and __attribute__ are present,
10-
// the processing goes awry preventing the definition of the types.
11-
// XFAIL: msvc
12-
139
// UNSUPPORTED: no-threads
14-
// REQUIRES: thread-safety
1510

1611
// <mutex>
1712

18-
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
13+
// GCC doesn't have thread safety attributes
14+
// UNSUPPORTED: gcc
15+
16+
// ADDITIONAL_COMPILE_FLAGS: -Wthread-safety
17+
18+
// XFAIL: FROZEN-CXX03-HEADERS-FIXME
1919

2020
#include <mutex>
2121

libcxx/test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// On Windows Clang bugs out when both __declspec and __attribute__ are present,
10-
// the processing goes awry preventing the definition of the types.
11-
// XFAIL: msvc
12-
139
// UNSUPPORTED: no-threads
14-
// REQUIRES: thread-safety
1510

1611
// <mutex>
1712

18-
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
13+
// GCC doesn't have thread safety attributes
14+
// UNSUPPORTED: gcc
15+
16+
// ADDITIONAL_COMPILE_FLAGS: -Wthread-safety
17+
18+
// XFAIL: FROZEN-CXX03-HEADERS-FIXME
1919

2020
#include <mutex>
2121

0 commit comments

Comments
 (0)