@@ -42,6 +42,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD
42
42
43
43
#if _LIBCPP_STD_VER >= 20
44
44
45
+ // These types are required to make __atomic_is_always_lock_free work across GCC and Clang.
46
+ // GCC won't allow the reinterpret_cast<_Tp*>(-required_alignment) trick initially used,
47
+ // so we need to actually fake up an instance of a type with the correct alignment.
48
+ template <size_t _Alignment>
49
+ struct __alignment_checker_type {
50
+ alignas (_Alignment) char __data;
51
+ };
52
+
53
+ template <size_t _Alignment>
54
+ struct __get_aligner_instance {
55
+ static constexpr __alignment_checker_type<_Alignment> __instance{};
56
+ };
57
+
45
58
template <class _Tp >
46
59
struct __atomic_ref_base {
47
60
protected:
@@ -105,7 +118,7 @@ struct __atomic_ref_base {
105
118
// that the pointer is going to be aligned properly at runtime because that is a (checked) precondition
106
119
// of atomic_ref's constructor.
107
120
static constexpr bool is_always_lock_free =
108
- __atomic_always_lock_free (sizeof (_Tp), reinterpret_cast <_Tp*>(- required_alignment) );
121
+ __atomic_always_lock_free (sizeof (_Tp), &__get_aligner_instance< required_alignment>::__instance );
109
122
110
123
_LIBCPP_HIDE_FROM_ABI bool is_lock_free () const noexcept { return __atomic_is_lock_free (sizeof (_Tp), __ptr_); }
111
124
@@ -322,6 +335,7 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> {
322
335
_LIBCPP_HIDE_FROM_ABI _Tp operator -=(_Tp __arg) const noexcept { return fetch_sub (__arg) - __arg; }
323
336
};
324
337
338
+
325
339
template <class _Tp >
326
340
struct atomic_ref <_Tp*> : public __atomic_ref_base<_Tp*> {
327
341
using __base = __atomic_ref_base<_Tp*>;
0 commit comments