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 #include "test_macros.h" 79 80 template <class A, class T> 81 void 82 do_test() 83 { 84 typedef typename std::remove_pointer<T>::type X; 85 A obj(T(0)); 86 bool b0 = obj.is_lock_free(); 87 ((void)b0); // mark as unused 88 assert(obj == T(0)); 89 std::atomic_init(&obj, T(1)); 90 assert(obj == T(1)); 91 std::atomic_init(&obj, T(2)); 92 assert(obj == T(2)); 93 obj.store(T(0)); 94 assert(obj == T(0)); 95 obj.store(T(1), std::memory_order_release); 96 assert(obj == T(1)); 97 assert(obj.load() == T(1)); 98 assert(obj.load(std::memory_order_acquire) == T(1)); 99 assert(obj.exchange(T(2)) == T(1)); 100 assert(obj == T(2)); 101 assert(obj.exchange(T(3), std::memory_order_relaxed) == T(2)); 102 assert(obj == T(3)); 103 T x = obj; 104 assert(cmpxchg_weak_loop(obj, x, T(2)) == true); 105 assert(obj == T(2)); 106 assert(x == T(3)); 107 assert(obj.compare_exchange_weak(x, T(1)) == false); 108 assert(obj == T(2)); 109 assert(x == T(2)); 110 x = T(2); 111 assert(obj.compare_exchange_strong(x, T(1)) == true); 112 assert(obj == T(1)); 113 assert(x == T(2)); 114 assert(obj.compare_exchange_strong(x, T(0)) == false); 115 assert(obj == T(1)); 116 assert(x == T(1)); 117 assert((obj = T(0)) == T(0)); 118 assert(obj == T(0)); 119 obj = T(2*sizeof(X)); 120 assert((obj += std::ptrdiff_t(3)) == T(5*sizeof(X))); 121 assert(obj == T(5*sizeof(X))); 122 assert((obj -= std::ptrdiff_t(3)) == T(2*sizeof(X))); 123 assert(obj == T(2*sizeof(X))); 124 125 { 126 TEST_ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23}; 127 A& zero = *new (storage) A(); 128 assert(zero == T(0)); 129 zero.~A(); 130 } 131 } 132 133 template <class A, class T> 134 void test() 135 { 136 do_test<A, T>(); 137 do_test<volatile A, T>(); 138 } 139 140 int main() 141 { 142 test<std::atomic<int*>, int*>(); 143 } 144