1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // XFAIL: !has-64-bit-atomics
10
11 // <atomic>
12
13 // template <>
14 // struct atomic<integral>
15 // {
16 // bool is_lock_free() const volatile;
17 // bool is_lock_free() const;
18 // void store(integral desr, memory_order m = memory_order_seq_cst) volatile;
19 // void store(integral desr, memory_order m = memory_order_seq_cst);
20 // integral load(memory_order m = memory_order_seq_cst) const volatile;
21 // integral load(memory_order m = memory_order_seq_cst) const;
22 // operator integral() const volatile;
23 // operator integral() const;
24 // integral exchange(integral desr,
25 // memory_order m = memory_order_seq_cst) volatile;
26 // integral exchange(integral desr, memory_order m = memory_order_seq_cst);
27 // bool compare_exchange_weak(integral& expc, integral desr,
28 // memory_order s, memory_order f) volatile;
29 // bool compare_exchange_weak(integral& expc, integral desr,
30 // memory_order s, memory_order f);
31 // bool compare_exchange_strong(integral& expc, integral desr,
32 // memory_order s, memory_order f) volatile;
33 // bool compare_exchange_strong(integral& expc, integral desr,
34 // memory_order s, memory_order f);
35 // bool compare_exchange_weak(integral& expc, integral desr,
36 // memory_order m = memory_order_seq_cst) volatile;
37 // bool compare_exchange_weak(integral& expc, integral desr,
38 // memory_order m = memory_order_seq_cst);
39 // bool compare_exchange_strong(integral& expc, integral desr,
40 // memory_order m = memory_order_seq_cst) volatile;
41 // bool compare_exchange_strong(integral& expc, integral desr,
42 // memory_order m = memory_order_seq_cst);
43 //
44 // integral
45 // fetch_add(integral op, memory_order m = memory_order_seq_cst) volatile;
46 // integral fetch_add(integral op, memory_order m = memory_order_seq_cst);
47 // integral
48 // fetch_sub(integral op, memory_order m = memory_order_seq_cst) volatile;
49 // integral fetch_sub(integral op, memory_order m = memory_order_seq_cst);
50 // integral
51 // fetch_and(integral op, memory_order m = memory_order_seq_cst) volatile;
52 // integral fetch_and(integral op, memory_order m = memory_order_seq_cst);
53 // integral
54 // fetch_or(integral op, memory_order m = memory_order_seq_cst) volatile;
55 // integral fetch_or(integral op, memory_order m = memory_order_seq_cst);
56 // integral
57 // fetch_xor(integral op, memory_order m = memory_order_seq_cst) volatile;
58 // integral fetch_xor(integral op, memory_order m = memory_order_seq_cst);
59 //
60 // atomic() = default;
61 // constexpr atomic(integral desr);
62 // atomic(const atomic&) = delete;
63 // atomic& operator=(const atomic&) = delete;
64 // atomic& operator=(const atomic&) volatile = delete;
65 // integral operator=(integral desr) volatile;
66 // integral operator=(integral desr);
67 //
68 // integral operator++(int) volatile;
69 // integral operator++(int);
70 // integral operator--(int) volatile;
71 // integral operator--(int);
72 // integral operator++() volatile;
73 // integral operator++();
74 // integral operator--() volatile;
75 // integral operator--();
76 // integral operator+=(integral op) volatile;
77 // integral operator+=(integral op);
78 // integral operator-=(integral op) volatile;
79 // integral operator-=(integral op);
80 // integral operator&=(integral op) volatile;
81 // integral operator&=(integral op);
82 // integral operator|=(integral op) volatile;
83 // integral operator|=(integral op);
84 // integral operator^=(integral op) volatile;
85 // integral operator^=(integral op);
86 // };
87
88 #include <atomic>
89 #include <cassert>
90 #include <cstdint>
91 #include <new>
92
93 #include <cmpxchg_loop.h>
94
95 #include "test_macros.h"
96
97 template <class A, class T>
98 void
do_test()99 do_test()
100 {
101 A obj(T(0));
102 assert(obj == T(0));
103 {
104 bool lockfree = obj.is_lock_free();
105 (void)lockfree;
106 #if TEST_STD_VER >= 17
107 if (A::is_always_lock_free)
108 assert(lockfree);
109 #endif
110 }
111 obj.store(T(0));
112 assert(obj == T(0));
113 obj.store(T(1), std::memory_order_release);
114 assert(obj == T(1));
115 assert(obj.load() == T(1));
116 assert(obj.load(std::memory_order_acquire) == T(1));
117 assert(obj.exchange(T(2)) == T(1));
118 assert(obj == T(2));
119 assert(obj.exchange(T(3), std::memory_order_relaxed) == T(2));
120 assert(obj == T(3));
121 T x = obj;
122 assert(cmpxchg_weak_loop(obj, x, T(2)) == true);
123 assert(obj == T(2));
124 assert(x == T(3));
125 assert(obj.compare_exchange_weak(x, T(1)) == false);
126 assert(obj == T(2));
127 assert(x == T(2));
128 x = T(2);
129 assert(obj.compare_exchange_strong(x, T(1)) == true);
130 assert(obj == T(1));
131 assert(x == T(2));
132 assert(obj.compare_exchange_strong(x, T(0)) == false);
133 assert(obj == T(1));
134 assert(x == T(1));
135 assert((obj = T(0)) == T(0));
136 assert(obj == T(0));
137 assert(obj++ == T(0));
138 assert(obj == T(1));
139 assert(++obj == T(2));
140 assert(obj == T(2));
141 assert(--obj == T(1));
142 assert(obj == T(1));
143 assert(obj-- == T(1));
144 assert(obj == T(0));
145 obj = T(2);
146 assert((obj += T(3)) == T(5));
147 assert(obj == T(5));
148 assert((obj -= T(3)) == T(2));
149 assert(obj == T(2));
150 assert((obj |= T(5)) == T(7));
151 assert(obj == T(7));
152 assert((obj &= T(0xF)) == T(7));
153 assert(obj == T(7));
154 assert((obj ^= T(0xF)) == T(8));
155 assert(obj == T(8));
156
157 {
158 TEST_ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23};
159 A& zero = *new (storage) A();
160 assert(zero == 0);
161 zero.~A();
162 }
163 }
164
165 template <class A, class T>
test()166 void test()
167 {
168 do_test<A, T>();
169 do_test<volatile A, T>();
170 }
171
172
main(int,char **)173 int main(int, char**)
174 {
175 test<std::atomic_char, char>();
176 test<std::atomic_schar, signed char>();
177 test<std::atomic_uchar, unsigned char>();
178 test<std::atomic_short, short>();
179 test<std::atomic_ushort, unsigned short>();
180 test<std::atomic_int, int>();
181 test<std::atomic_uint, unsigned int>();
182 test<std::atomic_long, long>();
183 test<std::atomic_ulong, unsigned long>();
184 test<std::atomic_llong, long long>();
185 test<std::atomic_ullong, unsigned long long>();
186 #if TEST_STD_VER > 17 && defined(__cpp_char8_t)
187 test<std::atomic_char8_t, char8_t>();
188 #endif
189 test<std::atomic_char16_t, char16_t>();
190 test<std::atomic_char32_t, char32_t>();
191 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
192 test<std::atomic_wchar_t, wchar_t>();
193 #endif
194
195 test<std::atomic_int8_t, int8_t>();
196 test<std::atomic_uint8_t, uint8_t>();
197 test<std::atomic_int16_t, int16_t>();
198 test<std::atomic_uint16_t, uint16_t>();
199 test<std::atomic_int32_t, int32_t>();
200 test<std::atomic_uint32_t, uint32_t>();
201 test<std::atomic_int64_t, int64_t>();
202 test<std::atomic_uint64_t, uint64_t>();
203
204 test<volatile std::atomic_char, char>();
205 test<volatile std::atomic_schar, signed char>();
206 test<volatile std::atomic_uchar, unsigned char>();
207 test<volatile std::atomic_short, short>();
208 test<volatile std::atomic_ushort, unsigned short>();
209 test<volatile std::atomic_int, int>();
210 test<volatile std::atomic_uint, unsigned int>();
211 test<volatile std::atomic_long, long>();
212 test<volatile std::atomic_ulong, unsigned long>();
213 test<volatile std::atomic_llong, long long>();
214 test<volatile std::atomic_ullong, unsigned long long>();
215 test<volatile std::atomic_char16_t, char16_t>();
216 test<volatile std::atomic_char32_t, char32_t>();
217 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
218 test<volatile std::atomic_wchar_t, wchar_t>();
219 #endif
220
221 test<volatile std::atomic_int8_t, int8_t>();
222 test<volatile std::atomic_uint8_t, uint8_t>();
223 test<volatile std::atomic_int16_t, int16_t>();
224 test<volatile std::atomic_uint16_t, uint16_t>();
225 test<volatile std::atomic_int32_t, int32_t>();
226 test<volatile std::atomic_uint32_t, uint32_t>();
227 test<volatile std::atomic_int64_t, int64_t>();
228 test<volatile std::atomic_uint64_t, uint64_t>();
229
230 return 0;
231 }
232