diff options
author | Eric Fiselier <eric@efcs.ca> | 2017-07-10 04:16:50 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2017-07-10 04:16:50 +0000 |
commit | 3f22e24981f70dbbabe12b009ceb99fa0a35ff2f (patch) | |
tree | 49cfd8dc189ad4d232667a09eb829dae28c219bb | |
parent | 631d697c6262e23ed6789ea613d9dd20b900e512 (diff) | |
download | external_libcxx-3f22e24981f70dbbabe12b009ceb99fa0a35ff2f.tar.gz external_libcxx-3f22e24981f70dbbabe12b009ceb99fa0a35ff2f.tar.bz2 external_libcxx-3f22e24981f70dbbabe12b009ceb99fa0a35ff2f.zip |
Work around PR31864 - ATOMIC_LLONG_LOCK_FREE is incorrect in 32 bit builds
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@307517 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | test/std/atomics/atomics.lockfree/isalwayslockfree.pass.cpp | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/test/std/atomics/atomics.lockfree/isalwayslockfree.pass.cpp b/test/std/atomics/atomics.lockfree/isalwayslockfree.pass.cpp index e42e9f284..7a4090b9c 100644 --- a/test/std/atomics/atomics.lockfree/isalwayslockfree.pass.cpp +++ b/test/std/atomics/atomics.lockfree/isalwayslockfree.pass.cpp @@ -25,6 +25,40 @@ template <typename T> void checkAlwaysLockFree() { assert(std::atomic<T>().is_lock_free()); } +// FIXME: This separate test is needed to work around llvm.org/PR31864 +// which causes ATOMIC_LLONG_LOCK_FREE to be defined as '1' in 32-bit builds +// even though __atomic_always_lock_free returns true for the same type. +constexpr bool NeedWorkaroundForPR31864 = +#if defined(__clang__) +(sizeof(void*) == 4); // Needed on 32 bit builds +#else +false; +#endif + +template <bool Disable = NeedWorkaroundForPR31864, + std::enable_if_t<!Disable>* = nullptr, + class LLong = long long, + class ULLong = unsigned long long> +void checkLongLongTypes() { + static_assert(std::atomic<LLong>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE)); + static_assert(std::atomic<ULLong>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE)); +} + +// Used to make the calls to __atomic_always_lock_free dependent on a template +// parameter. +template <class T> constexpr size_t getSizeOf() { return sizeof(T); } + +template <bool Enable = NeedWorkaroundForPR31864, + std::enable_if_t<Enable>* = nullptr, + class LLong = long long, + class ULLong = unsigned long long> +void checkLongLongTypes() { + constexpr bool ExpectLockFree = __atomic_always_lock_free(getSizeOf<LLong>(), 0); + static_assert(std::atomic<LLong>::is_always_lock_free == ExpectLockFree, ""); + static_assert(std::atomic<ULLong>::is_always_lock_free == ExpectLockFree, ""); + static_assert((0 != ATOMIC_LLONG_LOCK_FREE) == ExpectLockFree, ""); +} + int main() { // structs and unions can't be defined in the template invocation. @@ -94,8 +128,7 @@ int main() static_assert(std::atomic<unsigned int>::is_always_lock_free == (2 == ATOMIC_INT_LOCK_FREE)); static_assert(std::atomic<long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE)); static_assert(std::atomic<unsigned long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE)); - static_assert(std::atomic<long long>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE)); - static_assert(std::atomic<unsigned long long>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE)); + checkLongLongTypes(); static_assert(std::atomic<void*>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE)); static_assert(std::atomic<std::nullptr_t>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE)); } |