blob: e6c92eada6df98dfe4dcb0862b6d57f7e74da41a [file] [log] [blame]
Howard Hinnant91e2f262010-12-07 20:46:14 +00001//===----------------------------------------------------------------------===//
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//===----------------------------------------------------------------------===//
Jonathan Roelofs8d86b2e2014-09-05 19:45:05 +00009//
10// UNSUPPORTED: libcpp-has-no-threads
11// ... test crashes clang
Howard Hinnant91e2f262010-12-07 20:46:14 +000012
13// <atomic>
14
15// template <class Integral>
16// Integral
17// atomic_fetch_sub_explicit(volatile atomic<Integral>* obj, Integral op,
18// memory_order m);
19// template <class Integral>
20// Integral
21// atomic_fetch_sub_explicit(atomic<Integral>* obj, Integral op,
22// memory_order m);
23//
24// template <class T>
25// T*
26// atomic_fetch_sub_explicit(volatile atomic<T*>* obj, ptrdiff_t op,
27// memory_order m);
28// template <class T>
29// T*
30// atomic_fetch_sub_explicit(atomic<T*>* obj, ptrdiff_t op, memory_order m);
31
32#include <atomic>
Richard Smith9efdc0b2012-04-19 00:50:47 +000033#include <type_traits>
Howard Hinnant91e2f262010-12-07 20:46:14 +000034#include <cassert>
35
36template <class T>
Dan Albert1d4a1ed2016-05-25 22:36:09 -070037void
38test()
39{
Howard Hinnant91e2f262010-12-07 20:46:14 +000040 {
41 typedef std::atomic<T> A;
42 A t;
43 std::atomic_init(&t, T(3));
44 assert(std::atomic_fetch_sub_explicit(&t, T(2),
45 std::memory_order_seq_cst) == T(3));
46 assert(t == T(1));
47 }
48 {
49 typedef std::atomic<T> A;
50 volatile A t;
51 std::atomic_init(&t, T(3));
52 assert(std::atomic_fetch_sub_explicit(&t, T(2),
53 std::memory_order_seq_cst) == T(3));
54 assert(t == T(1));
55 }
Dan Albert1d4a1ed2016-05-25 22:36:09 -070056}
Howard Hinnant91e2f262010-12-07 20:46:14 +000057
Eric Fiselier00f4a492015-08-19 17:21:46 +000058template <class T>
Dan Albert1d4a1ed2016-05-25 22:36:09 -070059void
60testp()
Eric Fiselier00f4a492015-08-19 17:21:46 +000061{
62 {
63 typedef std::atomic<T> A;
64 typedef typename std::remove_pointer<T>::type X;
65 A t;
66 std::atomic_init(&t, T(3*sizeof(X)));
67 assert(std::atomic_fetch_sub_explicit(&t, 2,
68 std::memory_order_seq_cst) == T(3*sizeof(X)));
69 assert(t == T(1*sizeof(X)));
70 }
71 {
72 typedef std::atomic<T> A;
73 typedef typename std::remove_pointer<T>::type X;
74 volatile A t;
75 std::atomic_init(&t, T(3*sizeof(X)));
76 assert(std::atomic_fetch_sub_explicit(&t, 2,
77 std::memory_order_seq_cst) == T(3*sizeof(X)));
78 assert(t == T(1*sizeof(X)));
79 }
80}
81
Dan Albert1d4a1ed2016-05-25 22:36:09 -070082struct A
83{
84 int i;
85
86 explicit A(int d = 0) noexcept {i=d;}
87 A(const A& a) : i(a.i) {}
88 A(const volatile A& a) : i(a.i) {}
89
90 void operator=(const volatile A& a) volatile {i = a.i;}
91
92 friend bool operator==(const A& x, const A& y)
93 {return x.i == y.i;}
94};
95
Howard Hinnant91e2f262010-12-07 20:46:14 +000096int main()
97{
Dan Albert1d4a1ed2016-05-25 22:36:09 -070098 test<char>();
99 test<signed char>();
100 test<unsigned char>();
101 test<short>();
102 test<unsigned short>();
103 test<int>();
104 test<unsigned int>();
105 test<long>();
106 test<unsigned long>();
107 test<long long>();
108 test<unsigned long long>();
109 test<wchar_t>();
110#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
111 test<char16_t>();
112 test<char32_t>();
113#endif // _LIBCPP_HAS_NO_UNICODE_CHARS
Howard Hinnant91e2f262010-12-07 20:46:14 +0000114 testp<int*>();
115 testp<const int*>();
116}