Skip to content

Commit c8bd1b5

Browse files
committed
Fake up a pointer to give to GCC for __atomic_is_always_lock_free.
While clang will let us get away with the reinterpret_cast<_Tp*>(-required_alignment); GCC will not. This approach appears to work for both
1 parent bf36a36 commit c8bd1b5

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

libcxx/include/__atomic/atomic_ref.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD
4242

4343
#if _LIBCPP_STD_VER >= 20
4444

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+
4558
template <class _Tp>
4659
struct __atomic_ref_base {
4760
protected:
@@ -105,7 +118,7 @@ struct __atomic_ref_base {
105118
// that the pointer is going to be aligned properly at runtime because that is a (checked) precondition
106119
// of atomic_ref's constructor.
107120
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);
109122

110123
_LIBCPP_HIDE_FROM_ABI bool is_lock_free() const noexcept { return __atomic_is_lock_free(sizeof(_Tp), __ptr_); }
111124

@@ -322,6 +335,7 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> {
322335
_LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __arg) const noexcept { return fetch_sub(__arg) - __arg; }
323336
};
324337

338+
325339
template <class _Tp>
326340
struct atomic_ref<_Tp*> : public __atomic_ref_base<_Tp*> {
327341
using __base = __atomic_ref_base<_Tp*>;

0 commit comments

Comments
 (0)