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