1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // UNSUPPORTED: libcpp-has-no-threads, c++98, c++03, c++11, c++14 11 12 // <atomic> 13 14 // static constexpr bool is_always_lock_free; 15 16 #include <atomic> 17 #include <cassert> 18 19 #if !defined(__cpp_lib_atomic_is_always_lock_free) 20 # error Feature test macro missing. 21 #endif 22 23 template <typename T> void checkAlwaysLockFree() { 24 if (std::atomic<T>::is_always_lock_free) 25 assert(std::atomic<T>().is_lock_free()); 26 } 27 28 // FIXME: This separate test is needed to work around llvm.org/PR31864 29 // which causes ATOMIC_LLONG_LOCK_FREE to be defined as '1' in 32-bit builds 30 // even though __atomic_always_lock_free returns true for the same type. 31 constexpr bool NeedWorkaroundForPR31864 = 32 #if defined(__clang__) 33 (sizeof(void*) == 4); // Needed on 32 bit builds 34 #else 35 false; 36 #endif 37 38 template <bool Disable = NeedWorkaroundForPR31864, 39 std::enable_if_t<!Disable>* = nullptr, 40 class LLong = long long, 41 class ULLong = unsigned long long> 42 void checkLongLongTypes() { 43 static_assert(std::atomic<LLong>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE)); 44 static_assert(std::atomic<ULLong>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE)); 45 } 46 47 // Used to make the calls to __atomic_always_lock_free dependent on a template 48 // parameter. 49 template <class T> constexpr size_t getSizeOf() { return sizeof(T); } 50 51 template <bool Enable = NeedWorkaroundForPR31864, 52 std::enable_if_t<Enable>* = nullptr, 53 class LLong = long long, 54 class ULLong = unsigned long long> 55 void checkLongLongTypes() { 56 constexpr bool ExpectLockFree = __atomic_always_lock_free(getSizeOf<LLong>(), 0); 57 static_assert(std::atomic<LLong>::is_always_lock_free == ExpectLockFree, ""); 58 static_assert(std::atomic<ULLong>::is_always_lock_free == ExpectLockFree, ""); 59 static_assert((0 != ATOMIC_LLONG_LOCK_FREE) == ExpectLockFree, ""); 60 } 61 62 void run() 63 { 64 // structs and unions can't be defined in the template invocation. 65 // Work around this with a typedef. 66 #define CHECK_ALWAYS_LOCK_FREE(T) \ 67 do { \ 68 typedef T type; \ 69 checkAlwaysLockFree<type>(); \ 70 } while (0) 71 72 CHECK_ALWAYS_LOCK_FREE(bool); 73 CHECK_ALWAYS_LOCK_FREE(char); 74 CHECK_ALWAYS_LOCK_FREE(signed char); 75 CHECK_ALWAYS_LOCK_FREE(unsigned char); 76 CHECK_ALWAYS_LOCK_FREE(char16_t); 77 CHECK_ALWAYS_LOCK_FREE(char32_t); 78 CHECK_ALWAYS_LOCK_FREE(wchar_t); 79 CHECK_ALWAYS_LOCK_FREE(short); 80 CHECK_ALWAYS_LOCK_FREE(unsigned short); 81 CHECK_ALWAYS_LOCK_FREE(int); 82 CHECK_ALWAYS_LOCK_FREE(unsigned int); 83 CHECK_ALWAYS_LOCK_FREE(long); 84 CHECK_ALWAYS_LOCK_FREE(unsigned long); 85 CHECK_ALWAYS_LOCK_FREE(long long); 86 CHECK_ALWAYS_LOCK_FREE(unsigned long long); 87 CHECK_ALWAYS_LOCK_FREE(std::nullptr_t); 88 CHECK_ALWAYS_LOCK_FREE(void*); 89 CHECK_ALWAYS_LOCK_FREE(float); 90 CHECK_ALWAYS_LOCK_FREE(double); 91 CHECK_ALWAYS_LOCK_FREE(long double); 92 #if __has_attribute(vector_size) && defined(_LIBCPP_VERSION) 93 CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(1 * sizeof(int))))); 94 CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(2 * sizeof(int))))); 95 CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(4 * sizeof(int))))); 96 CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(16 * sizeof(int))))); 97 CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(32 * sizeof(int))))); 98 CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(1 * sizeof(float))))); 99 CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(2 * sizeof(float))))); 100 CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(4 * sizeof(float))))); 101 CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(16 * sizeof(float))))); 102 CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(32 * sizeof(float))))); 103 CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(1 * sizeof(double))))); 104 CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(2 * sizeof(double))))); 105 CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(4 * sizeof(double))))); 106 CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(16 * sizeof(double))))); 107 CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(32 * sizeof(double))))); 108 #endif // __has_attribute(vector_size) && defined(_LIBCPP_VERSION) 109 CHECK_ALWAYS_LOCK_FREE(struct Empty {}); 110 CHECK_ALWAYS_LOCK_FREE(struct OneInt { int i; }); 111 CHECK_ALWAYS_LOCK_FREE(struct IntArr2 { int i[2]; }); 112 CHECK_ALWAYS_LOCK_FREE(struct LLIArr2 { long long int i[2]; }); 113 CHECK_ALWAYS_LOCK_FREE(struct LLIArr4 { long long int i[4]; }); 114 CHECK_ALWAYS_LOCK_FREE(struct LLIArr8 { long long int i[8]; }); 115 CHECK_ALWAYS_LOCK_FREE(struct LLIArr16 { long long int i[16]; }); 116 CHECK_ALWAYS_LOCK_FREE(struct Padding { char c; /* padding */ long long int i; }); 117 CHECK_ALWAYS_LOCK_FREE(union IntFloat { int i; float f; }); 118 119 // C macro and static constexpr must be consistent. 120 static_assert(std::atomic<bool>::is_always_lock_free == (2 == ATOMIC_BOOL_LOCK_FREE)); 121 static_assert(std::atomic<char>::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE)); 122 static_assert(std::atomic<signed char>::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE)); 123 static_assert(std::atomic<unsigned char>::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE)); 124 static_assert(std::atomic<char16_t>::is_always_lock_free == (2 == ATOMIC_CHAR16_T_LOCK_FREE)); 125 static_assert(std::atomic<char32_t>::is_always_lock_free == (2 == ATOMIC_CHAR32_T_LOCK_FREE)); 126 static_assert(std::atomic<wchar_t>::is_always_lock_free == (2 == ATOMIC_WCHAR_T_LOCK_FREE)); 127 static_assert(std::atomic<short>::is_always_lock_free == (2 == ATOMIC_SHORT_LOCK_FREE)); 128 static_assert(std::atomic<unsigned short>::is_always_lock_free == (2 == ATOMIC_SHORT_LOCK_FREE)); 129 static_assert(std::atomic<int>::is_always_lock_free == (2 == ATOMIC_INT_LOCK_FREE)); 130 static_assert(std::atomic<unsigned int>::is_always_lock_free == (2 == ATOMIC_INT_LOCK_FREE)); 131 static_assert(std::atomic<long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE)); 132 static_assert(std::atomic<unsigned long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE)); 133 checkLongLongTypes(); 134 static_assert(std::atomic<void*>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE)); 135 static_assert(std::atomic<std::nullptr_t>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE)); 136 } 137 138 int main() { run(); } 139