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 // <atomic>
11 
12 // template <class Integral>
13 //     Integral
14 //     atomic_fetch_add_explicit(volatile atomic<Integral>* obj, Integral op,
15 //                               memory_order m);
16 // template <class Integral>
17 //     Integral
18 //     atomic_fetch_add_explicit(atomic<Integral>* obj, Integral op,
19 //                               memory_order m);
20 // template <class T>
21 //     T*
22 //     atomic_fetch_add_explicit(volatile atomic<T*>* obj, ptrdiff_t op,
23 //                               memory_order m);
24 // template <class T>
25 //     T*
26 //     atomic_fetch_add_explicit(atomic<T*>* obj, ptrdiff_t op, memory_order m);
27 
28 #include <atomic>
29 #include <type_traits>
30 #include <cassert>
31 
32 template <class T>
33 void
test()34 test()
35 {
36     {
37         typedef std::atomic<T> A;
38         A t;
39         std::atomic_init(&t, T(1));
40         assert(std::atomic_fetch_add_explicit(&t, T(2),
41                                             std::memory_order_seq_cst) == T(1));
42         assert(t == T(3));
43     }
44     {
45         typedef std::atomic<T> A;
46         volatile A t;
47         std::atomic_init(&t, T(1));
48         assert(std::atomic_fetch_add_explicit(&t, T(2),
49                                             std::memory_order_seq_cst) == T(1));
50         assert(t == T(3));
51     }
52 }
53 
54 template <class T>
55 void
testp()56 testp()
57 {
58     {
59         typedef std::atomic<T> A;
60         typedef typename std::remove_pointer<T>::type X;
61         A t;
62         std::atomic_init(&t, T(1*sizeof(X)));
63         assert(std::atomic_fetch_add_explicit(&t, 2,
64                                   std::memory_order_seq_cst) == T(1*sizeof(X)));
65         assert(t == T(3*sizeof(X)));
66     }
67     {
68         typedef std::atomic<T> A;
69         typedef typename std::remove_pointer<T>::type X;
70         volatile A t;
71         std::atomic_init(&t, T(1*sizeof(X)));
72         assert(std::atomic_fetch_add_explicit(&t, 2,
73                                   std::memory_order_seq_cst) == T(1*sizeof(X)));
74         assert(t == T(3*sizeof(X)));
75     }
76 }
77 
78 struct A
79 {
80     int i;
81 
AA82     explicit A(int d = 0) : i(d) {}
AA83     A(const A& a) : i(a.i) {}
AA84     A(const volatile A& a) : i(a.i) {}
85 
operator =A86     void operator=(const volatile A& a) volatile {i = a.i;}
87 
operator ==(const A & x,const A & y)88     friend bool operator==(const A& x, const A& y)
89         {return x.i == y.i;}
90 };
91 
main()92 int main()
93 {
94     test<char>();
95     test<signed char>();
96     test<unsigned char>();
97     test<short>();
98     test<unsigned short>();
99     test<int>();
100     test<unsigned int>();
101     test<long>();
102     test<unsigned long>();
103     test<long long>();
104     test<unsigned long long>();
105     test<wchar_t>();
106 #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
107     test<char16_t>();
108     test<char32_t>();
109 #endif  // _LIBCPP_HAS_NO_UNICODE_CHARS
110     testp<int*>();
111     testp<const int*>();
112 }
113