Index: boost/atomic/detail/config.hpp =================================================================== --- boost/atomic/detail/config.hpp 2018-05-09 16:17:05.000000000 -0600 +++ boost/atomic/detail/config.hpp 2018-05-16 16:23:16.000000000 -0600 @@ -36,10 +36,17 @@ #define BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA #endif -#if (defined(__i386__) || defined(__x86_64__)) && (defined(__clang__) || (defined(BOOST_GCC) && (BOOST_GCC+0) < 40500) || defined(__SUNPRO_CC)) // This macro indicates that the compiler does not support allocating eax:edx or rax:rdx register pairs ("A") in asm blocks +#if defined(__i386__) || defined(__x86_64__) +#if defined(__clang__) && defined(__has_feature) +// Clang introduced this feature after it started supporting rax:rdx register pairs, so can use it to make this determination. +#if !__has_feature(__attribute_diagnose_if_objc__) #define BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS #endif +#elif (defined(BOOST_GCC) && (BOOST_GCC+0) < 40500) || defined(__SUNPRO_CC) +#define BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS +#endif +#endif #if defined(__i386__) && (defined(__PIC__) || defined(__PIE__)) && !(defined(__clang__) || (defined(BOOST_GCC) && (BOOST_GCC+0) >= 50100)) // This macro indicates that asm blocks should preserve ebx value unchanged. Some compilers are able to maintain ebx themselves Index: boost/atomic/detail/ops_gcc_x86_dcas.hpp ================================================================== --- boost/atomic/detail/ops_gcc_x86_dcas.hpp 2018-05-09 16:17:05.000000000 -0600 +++ boost/atomic/detail/ops_gcc_x86_dcas.hpp 2018-05-16 16:43:51.000000000 -0600 @@ -158,10 +158,11 @@ } else { +#if defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) #if defined(__clang__) - // Clang cannot allocate eax:edx register pairs but it has sync intrinsics + // Older versions of Clang cannot allocate eax:edx register pairs, but they do have sync intrinsics value = __sync_val_compare_and_swap(&storage, (storage_type)0, (storage_type)0); -#elif defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) +#else // defined(__clang__) uint32_t value_bits[2]; // We don't care for comparison result here; the previous value will be stored into value anyway. // Also we don't care for ebx and ecx values, they just have to be equal to eax and edx before cmpxchg8b. @@ -175,6 +176,7 @@ : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" ); BOOST_ATOMIC_DETAIL_MEMCPY(&value, value_bits, sizeof(value)); +#endif // defined(__clang__) #else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) // We don't care for comparison result here; the previous value will be stored into value anyway. // Also we don't care for ebx and ecx values, they just have to be equal to eax and edx before cmpxchg8b. @@ -196,9 +198,9 @@ static BOOST_FORCEINLINE bool compare_exchange_strong( storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT { -#if defined(__clang__) +#if defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) && defined(__clang__) - // Clang cannot allocate eax:edx register pairs but it has sync intrinsics + // Older versions of Clang cannot allocate eax:edx register pairs, but they do have sync intrinsics storage_type old_expected = expected; expected = __sync_val_compare_and_swap(&storage, old_expected, desired); return expected == old_expected; @@ -401,13 +403,15 @@ static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT { +#if defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + #if defined(__clang__) - // Clang cannot allocate rax:rdx register pairs but it has sync intrinsics + // Older versions of Clang cannot allocate rax:rdx register pairs, but they do have sync intrinsics storage_type value = storage_type(); return __sync_val_compare_and_swap(&storage, value, value); -#elif defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) +#else // defined(__clang__) // Some compilers can't allocate rax:rdx register pair either and also don't support 128-bit __sync_val_compare_and_swap uint64_t value_bits[2]; @@ -428,6 +432,8 @@ BOOST_ATOMIC_DETAIL_MEMCPY(&value, value_bits, sizeof(value)); return value; +#endif // defined(__clang__) + #else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) storage_type value; @@ -452,14 +458,16 @@ static BOOST_FORCEINLINE bool compare_exchange_strong( storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT { +#if defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + #if defined(__clang__) - // Clang cannot allocate rax:rdx register pairs but it has sync intrinsics + // Older versions of Clang cannot allocate rax:rdx register pairs, but they do have sync intrinsics storage_type old_expected = expected; expected = __sync_val_compare_and_swap(&storage, old_expected, desired); return expected == old_expected; -#elif defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) +#else // defined(__clang__) // Some compilers can't allocate rax:rdx register pair either but also don't support 128-bit __sync_val_compare_and_swap bool success; @@ -474,6 +482,8 @@ return success; +#endif // defined(__clang__) + #else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) bool success;