Skip to content

Commit 685824d

Browse files
committed
Implement P1831R1: deprecate many uses of volatile
1 parent cf79aba commit 685824d

File tree

12 files changed

+467
-110
lines changed

12 files changed

+467
-110
lines changed

libcxx/include/__atomic/atomic.h

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct atomic : public __atomic_base<_Tp> {
4747
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {}
4848

4949
_LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile _NOEXCEPT {
50+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
5051
__base::store(__d);
5152
return __d;
5253
}
@@ -72,6 +73,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
7273
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}
7374

7475
_LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) volatile _NOEXCEPT {
76+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp*, __base::is_always_lock_free);
7577
__base::store(__d);
7678
return __d;
7779
}
@@ -81,6 +83,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
8183
}
8284

8385
_LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
86+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp*, __base::is_always_lock_free);
8487
// __atomic_fetch_add accepts function pointers, guard against them.
8588
static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
8689
return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
@@ -93,6 +96,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
9396
}
9497

9598
_LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
99+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp*, __base::is_always_lock_free);
96100
// __atomic_fetch_add accepts function pointers, guard against them.
97101
static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
98102
return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
@@ -104,18 +108,41 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
104108
return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
105109
}
106110

107-
_LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT { return fetch_add(1); }
108111
_LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) _NOEXCEPT { return fetch_add(1); }
109-
_LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) volatile _NOEXCEPT { return fetch_sub(1); }
112+
_LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT {
113+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp*, __base::is_always_lock_free);
114+
return fetch_add(1);
115+
}
116+
110117
_LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) _NOEXCEPT { return fetch_sub(1); }
111-
_LIBCPP_HIDE_FROM_ABI _Tp* operator++() volatile _NOEXCEPT { return fetch_add(1) + 1; }
118+
_LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) volatile _NOEXCEPT {
119+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp*, __base::is_always_lock_free);
120+
return fetch_sub(1);
121+
}
122+
112123
_LIBCPP_HIDE_FROM_ABI _Tp* operator++() _NOEXCEPT { return fetch_add(1) + 1; }
113-
_LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT { return fetch_sub(1) - 1; }
124+
_LIBCPP_HIDE_FROM_ABI _Tp* operator++() volatile _NOEXCEPT {
125+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp*, __base::is_always_lock_free);
126+
return fetch_add(1) + 1;
127+
}
128+
114129
_LIBCPP_HIDE_FROM_ABI _Tp* operator--() _NOEXCEPT { return fetch_sub(1) - 1; }
115-
_LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; }
130+
_LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT {
131+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp*, __base::is_always_lock_free);
132+
return fetch_sub(1) - 1;
133+
}
134+
116135
_LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT { return fetch_add(__op) + __op; }
117-
_LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; }
136+
_LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT {
137+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp*, __base::is_always_lock_free);
138+
return fetch_add(__op) + __op;
139+
}
140+
118141
_LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT { return fetch_sub(__op) - __op; }
142+
_LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT {
143+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp*, __base::is_always_lock_free);
144+
return fetch_sub(__op) - __op;
145+
}
119146

120147
atomic& operator=(const atomic&) = delete;
121148
atomic& operator=(const atomic&) volatile = delete;
@@ -201,9 +228,8 @@ struct atomic<_Tp> : __atomic_base<_Tp> {
201228
atomic& operator=(const atomic&) = delete;
202229
atomic& operator=(const atomic&) volatile = delete;
203230

204-
_LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile noexcept
205-
requires __base::is_always_lock_free
206-
{
231+
_LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile noexcept {
232+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
207233
__base::store(__d);
208234
return __d;
209235
}
@@ -212,37 +238,33 @@ struct atomic<_Tp> : __atomic_base<_Tp> {
212238
return __d;
213239
}
214240

215-
_LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept
216-
requires __base::is_always_lock_free
217-
{
241+
_LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept {
242+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
218243
return __fetch_add(*this, __op, __m);
219244
}
220245

221246
_LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {
222247
return __fetch_add(*this, __op, __m);
223248
}
224249

225-
_LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept
226-
requires __base::is_always_lock_free
227-
{
250+
_LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept {
251+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
228252
return __fetch_sub(*this, __op, __m);
229253
}
230254

231255
_LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {
232256
return __fetch_sub(*this, __op, __m);
233257
}
234258

235-
_LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile noexcept
236-
requires __base::is_always_lock_free
237-
{
259+
_LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile noexcept {
260+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
238261
return fetch_add(__op) + __op;
239262
}
240263

241264
_LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) noexcept { return fetch_add(__op) + __op; }
242265

243-
_LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile noexcept
244-
requires __base::is_always_lock_free
245-
{
266+
_LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile noexcept {
267+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
246268
return fetch_sub(__op) - __op;
247269
}
248270

@@ -272,8 +294,7 @@ atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NO
272294
}
273295

274296
template <class _Tp>
275-
_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void
276-
atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
297+
_LIBCPP_HIDE_FROM_ABI void atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
277298
std::__cxx_atomic_init(std::addressof(__o->__a_), __d);
278299
}
279300

libcxx/include/__atomic/atomic_base.h

Lines changed: 92 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,20 @@
2727

2828
_LIBCPP_BEGIN_NAMESPACE_STD
2929

30+
#if _LIBCPP_STD_VER >= 20
31+
template <class _Tp, bool __lock_free>
32+
inline constexpr bool __deprecated_if_not_always_lock_free = true;
33+
34+
template <class _Tp>
35+
[[deprecated("volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false")]]
36+
inline constexpr bool __deprecated_if_not_always_lock_free<_Tp, false> = true;
37+
# define _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __is_always_lock_free) \
38+
static_assert(__deprecated_if_not_always_lock_free<_Tp, __is_always_lock_free>)
39+
#else
40+
# define _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __is_always_lock_free) \
41+
{}
42+
#endif
43+
3044
template <class _Tp, bool = is_integral<_Tp>::value && !is_same<_Tp, bool>::value>
3145
struct __atomic_base // false
3246
{
@@ -44,6 +58,7 @@ struct __atomic_base // false
4458
}
4559
_LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
4660
_LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
61+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, is_always_lock_free);
4762
std::__cxx_atomic_store(std::addressof(__a_), __d, __m);
4863
}
4964
_LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT
@@ -52,15 +67,20 @@ struct __atomic_base // false
5267
}
5368
_LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT
5469
_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
70+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, is_always_lock_free);
5571
return std::__cxx_atomic_load(std::addressof(__a_), __m);
5672
}
5773
_LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT
5874
_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
5975
return std::__cxx_atomic_load(std::addressof(__a_), __m);
6076
}
61-
_LIBCPP_HIDE_FROM_ABI operator _Tp() const volatile _NOEXCEPT { return load(); }
77+
_LIBCPP_HIDE_FROM_ABI operator _Tp() const volatile _NOEXCEPT {
78+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, is_always_lock_free);
79+
return load();
80+
}
6281
_LIBCPP_HIDE_FROM_ABI operator _Tp() const _NOEXCEPT { return load(); }
6382
_LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
83+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, is_always_lock_free);
6484
return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m);
6585
}
6686
_LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
@@ -69,6 +89,7 @@ struct __atomic_base // false
6989
_LIBCPP_HIDE_FROM_ABI bool
7090
compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
7191
_LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
92+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, is_always_lock_free);
7293
return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
7394
}
7495
_LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT
@@ -78,6 +99,7 @@ struct __atomic_base // false
7899
_LIBCPP_HIDE_FROM_ABI bool
79100
compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
80101
_LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
102+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, is_always_lock_free);
81103
return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
82104
}
83105
_LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT
@@ -86,6 +108,7 @@ struct __atomic_base // false
86108
}
87109
_LIBCPP_HIDE_FROM_ABI bool
88110
compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
111+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, is_always_lock_free);
89112
return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
90113
}
91114
_LIBCPP_HIDE_FROM_ABI bool
@@ -94,6 +117,7 @@ struct __atomic_base // false
94117
}
95118
_LIBCPP_HIDE_FROM_ABI bool
96119
compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
120+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, is_always_lock_free);
97121
return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
98122
}
99123
_LIBCPP_HIDE_FROM_ABI bool
@@ -142,54 +166,112 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
142166
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {}
143167

144168
_LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
169+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
145170
return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
146171
}
172+
147173
_LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
148174
return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
149175
}
176+
150177
_LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
178+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
151179
return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
152180
}
181+
153182
_LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
154183
return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
155184
}
185+
156186
_LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
187+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
157188
return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m);
158189
}
190+
159191
_LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
160192
return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m);
161193
}
194+
162195
_LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
196+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
163197
return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m);
164198
}
199+
165200
_LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
166201
return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m);
167202
}
203+
168204
_LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
205+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
169206
return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m);
170207
}
208+
171209
_LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
172210
return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m);
173211
}
174212

175-
_LIBCPP_HIDE_FROM_ABI _Tp operator++(int) volatile _NOEXCEPT { return fetch_add(_Tp(1)); }
176213
_LIBCPP_HIDE_FROM_ABI _Tp operator++(int) _NOEXCEPT { return fetch_add(_Tp(1)); }
177-
_LIBCPP_HIDE_FROM_ABI _Tp operator--(int) volatile _NOEXCEPT { return fetch_sub(_Tp(1)); }
214+
215+
_LIBCPP_HIDE_FROM_ABI _Tp operator++(int) volatile _NOEXCEPT {
216+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
217+
return fetch_add(_Tp(1));
218+
}
219+
178220
_LIBCPP_HIDE_FROM_ABI _Tp operator--(int) _NOEXCEPT { return fetch_sub(_Tp(1)); }
179-
_LIBCPP_HIDE_FROM_ABI _Tp operator++() volatile _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); }
221+
222+
_LIBCPP_HIDE_FROM_ABI _Tp operator--(int) volatile _NOEXCEPT {
223+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
224+
return fetch_sub(_Tp(1));
225+
}
226+
180227
_LIBCPP_HIDE_FROM_ABI _Tp operator++() _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); }
181-
_LIBCPP_HIDE_FROM_ABI _Tp operator--() volatile _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); }
228+
229+
_LIBCPP_HIDE_FROM_ABI _Tp operator++() volatile _NOEXCEPT {
230+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
231+
return fetch_add(_Tp(1)) + _Tp(1);
232+
}
233+
182234
_LIBCPP_HIDE_FROM_ABI _Tp operator--() _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); }
183-
_LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; }
235+
236+
_LIBCPP_HIDE_FROM_ABI _Tp operator--() volatile _NOEXCEPT {
237+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
238+
return fetch_sub(_Tp(1)) - _Tp(1);
239+
}
240+
184241
_LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) _NOEXCEPT { return fetch_add(__op) + __op; }
185-
_LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; }
242+
243+
_LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile _NOEXCEPT {
244+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
245+
return fetch_add(__op) + __op;
246+
}
247+
186248
_LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) _NOEXCEPT { return fetch_sub(__op) - __op; }
187-
_LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) volatile _NOEXCEPT { return fetch_and(__op) & __op; }
249+
250+
_LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile _NOEXCEPT {
251+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
252+
return fetch_sub(__op) - __op;
253+
}
254+
188255
_LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) _NOEXCEPT { return fetch_and(__op) & __op; }
189-
_LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) volatile _NOEXCEPT { return fetch_or(__op) | __op; }
256+
257+
_LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) volatile _NOEXCEPT {
258+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
259+
return fetch_and(__op) & __op;
260+
}
261+
190262
_LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) _NOEXCEPT { return fetch_or(__op) | __op; }
191-
_LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) volatile _NOEXCEPT { return fetch_xor(__op) ^ __op; }
263+
264+
_LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) volatile _NOEXCEPT {
265+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
266+
return fetch_or(__op) | __op;
267+
}
268+
192269
_LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) _NOEXCEPT { return fetch_xor(__op) ^ __op; }
270+
271+
_LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) volatile _NOEXCEPT {
272+
_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE(_Tp, __base::is_always_lock_free);
273+
return fetch_xor(__op) ^ __op;
274+
}
193275
};
194276

195277
// Here we need _IsIntegral because the default template argument is not enough

libcxx/include/__config

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,15 @@ typedef __char32_t char32_t;
741741
# define _LIBCPP_DEPRECATED_WITH_CHAR8_T
742742
# endif
743743

744+
// P1831R1 deprecated many uses of volatile, but the way attributes work with template specializations require this
745+
// work-around to always raise warnings in cases where templates are specialized for volatile variants of STL types.
746+
template <class _Tp, bool __cxx20 = _LIBCPP_STD_VER >= 20>
747+
_LIBCPP_HIDE_FROM_ABI constexpr bool __volatile_deprecated_since_cxx20_warning = true;
748+
template <class _Tp>
749+
_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI constexpr bool __volatile_deprecated_since_cxx20_warning<_Tp, true> = true;
750+
# define _LIBCPP_VOLATILE_DEPRECATED_WARNING static_assert(__volatile_deprecated_since_cxx20_warning<volatile _Tp>)
751+
# define _LIBCPP_CONST_VOLATILE_DEPRECATED_WARNING static_assert(__volatile_deprecated_since_cxx20_warning<const volatile _Tp>)
752+
744753
// Macros to enter and leave a state where deprecation warnings are suppressed.
745754
# if defined(_LIBCPP_COMPILER_CLANG_BASED) || defined(_LIBCPP_COMPILER_GCC)
746755
# define _LIBCPP_SUPPRESS_DEPRECATED_PUSH \

libcxx/include/__tuple/tuple_element.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const _Tp> {
3030

3131
template <size_t _Ip, class _Tp>
3232
struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, volatile _Tp> {
33+
_LIBCPP_VOLATILE_DEPRECATED_WARNING;
3334
typedef _LIBCPP_NODEBUG volatile typename tuple_element<_Ip, _Tp>::type type;
3435
};
3536

3637
template <size_t _Ip, class _Tp>
3738
struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const volatile _Tp> {
39+
_LIBCPP_CONST_VOLATILE_DEPRECATED_WARNING;
3840
typedef _LIBCPP_NODEBUG const volatile typename tuple_element<_Ip, _Tp>::type type;
3941
};
4042

0 commit comments

Comments
 (0)