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 80template <class A, class T> 81void 82do_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 133template <class A, class T> 134void test() 135{ 136 do_test<A, T>(); 137 do_test<volatile A, T>(); 138} 139 140int main() 141{ 142 test<std::atomic<int*>, int*>(); 143} 144