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 11 // ... test case crashes clang. 12 13 // <atomic> 14 15 // template <class T> 16 // struct atomic<T*> 17 // { 18 // bool is_lock_free() const volatile; 19 // bool is_lock_free() const; 20 // void store(T* desr, memory_order m = memory_order_seq_cst) volatile; 21 // void store(T* desr, memory_order m = memory_order_seq_cst); 22 // T* load(memory_order m = memory_order_seq_cst) const volatile; 23 // T* load(memory_order m = memory_order_seq_cst) const; 24 // operator T*() const volatile; 25 // operator T*() const; 26 // T* exchange(T* desr, memory_order m = memory_order_seq_cst) volatile; 27 // T* exchange(T* desr, memory_order m = memory_order_seq_cst); 28 // bool compare_exchange_weak(T*& expc, T* desr, 29 // memory_order s, memory_order f) volatile; 30 // bool compare_exchange_weak(T*& expc, T* desr, 31 // memory_order s, memory_order f); 32 // bool compare_exchange_strong(T*& expc, T* desr, 33 // memory_order s, memory_order f) volatile; 34 // bool compare_exchange_strong(T*& expc, T* desr, 35 // memory_order s, memory_order f); 36 // bool compare_exchange_weak(T*& expc, T* desr, 37 // memory_order m = memory_order_seq_cst) volatile; 38 // bool compare_exchange_weak(T*& expc, T* desr, 39 // memory_order m = memory_order_seq_cst); 40 // bool compare_exchange_strong(T*& expc, T* desr, 41 // memory_order m = memory_order_seq_cst) volatile; 42 // bool compare_exchange_strong(T*& expc, T* desr, 43 // memory_order m = memory_order_seq_cst); 44 // T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile; 45 // T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst); 46 // T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile; 47 // T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst); 48 // 49 // atomic() = default; 50 // constexpr atomic(T* desr); 51 // atomic(const atomic&) = delete; 52 // atomic& operator=(const atomic&) = delete; 53 // atomic& operator=(const atomic&) volatile = delete; 54 // 55 // T* operator=(T*) volatile; 56 // T* operator=(T*); 57 // T* operator++(int) volatile; 58 // T* operator++(int); 59 // T* operator--(int) volatile; 60 // T* operator--(int); 61 // T* operator++() volatile; 62 // T* operator++(); 63 // T* operator--() volatile; 64 // T* operator--(); 65 // T* operator+=(ptrdiff_t op) volatile; 66 // T* operator+=(ptrdiff_t op); 67 // T* operator-=(ptrdiff_t op) volatile; 68 // T* operator-=(ptrdiff_t op); 69 // }; 70 71 #include <atomic> 72 #include <new> 73 #include <type_traits> 74 #include <cassert> 75 76 #include <cmpxchg_loop.h> 77 78 template <class A, class T> 79 void 80 do_test() 81 { 82 typedef typename std::remove_pointer<T>::type X; 83 A obj(T(0)); 84 bool b0 = obj.is_lock_free(); 85 ((void)b0); // mark as unused 86 assert(obj == T(0)); 87 std::atomic_init(&obj, T(1)); 88 assert(obj == T(1)); 89 std::atomic_init(&obj, T(2)); 90 assert(obj == T(2)); 91 obj.store(T(0)); 92 assert(obj == T(0)); 93 obj.store(T(1), std::memory_order_release); 94 assert(obj == T(1)); 95 assert(obj.load() == T(1)); 96 assert(obj.load(std::memory_order_acquire) == T(1)); 97 assert(obj.exchange(T(2)) == T(1)); 98 assert(obj == T(2)); 99 assert(obj.exchange(T(3), std::memory_order_relaxed) == T(2)); 100 assert(obj == T(3)); 101 T x = obj; 102 assert(cmpxchg_weak_loop(obj, x, T(2)) == true); 103 assert(obj == T(2)); 104 assert(x == T(3)); 105 assert(obj.compare_exchange_weak(x, T(1)) == false); 106 assert(obj == T(2)); 107 assert(x == T(2)); 108 x = T(2); 109 assert(obj.compare_exchange_strong(x, T(1)) == true); 110 assert(obj == T(1)); 111 assert(x == T(2)); 112 assert(obj.compare_exchange_strong(x, T(0)) == false); 113 assert(obj == T(1)); 114 assert(x == T(1)); 115 assert((obj = T(0)) == T(0)); 116 assert(obj == T(0)); 117 obj = T(2*sizeof(X)); 118 assert((obj += std::ptrdiff_t(3)) == T(5*sizeof(X))); 119 assert(obj == T(5*sizeof(X))); 120 assert((obj -= std::ptrdiff_t(3)) == T(2*sizeof(X))); 121 assert(obj == T(2*sizeof(X))); 122 123 { 124 _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23}; 125 A& zero = *new (storage) A(); 126 assert(zero == 0); 127 zero.~A(); 128 } 129 } 130 131 template <class A, class T> 132 void test() 133 { 134 do_test<A, T>(); 135 do_test<volatile A, T>(); 136 } 137 138 int main() 139 { 140 test<std::atomic<int*>, int*>(); 141 } 142