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