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 // UNSUPPORTED: c++03, c++11, c++14
10 // UNSUPPORTED: libcpp-has-no-incomplete-pstl
11
12 // Having a customization point outside the module doesn't work, so this test is inherently module-hostile.
13 // UNSUPPORTED: clang-modules-build
14
15 // Make sure that the customization points get called properly when overloaded
16
17 #include <__config>
18 #include <__iterator/iterator_traits.h>
19 #include <__iterator/readable_traits.h>
20 #include <__utility/empty.h>
21 #include <cassert>
22 #include <optional>
23
24 struct TestPolicy {};
25 struct TestBackend {};
26
27 _LIBCPP_BEGIN_NAMESPACE_STD
28
29 bool pstl_any_of_called = false;
30
31 template <class, class ForwardIterator, class Pred>
__pstl_any_of(TestBackend,ForwardIterator,ForwardIterator,Pred)32 optional<bool> __pstl_any_of(TestBackend, ForwardIterator, ForwardIterator, Pred) {
33 assert(!pstl_any_of_called);
34 pstl_any_of_called = true;
35 return true;
36 }
37
38 bool pstl_all_of_called = false;
39
40 template <class, class ForwardIterator, class Pred>
__pstl_all_of(TestBackend,ForwardIterator,ForwardIterator,Pred)41 optional<bool> __pstl_all_of(TestBackend, ForwardIterator, ForwardIterator, Pred) {
42 assert(!pstl_all_of_called);
43 pstl_all_of_called = true;
44 return true;
45 }
46
47 bool pstl_copy_called = false;
48
49 template <class, class ForwardIterator, class ForwardOutIterator>
__pstl_copy(TestBackend,ForwardIterator,ForwardIterator,ForwardOutIterator res)50 optional<ForwardOutIterator> __pstl_copy(TestBackend, ForwardIterator, ForwardIterator, ForwardOutIterator res) {
51 assert(!pstl_copy_called);
52 pstl_copy_called = true;
53 return res;
54 }
55
56 bool pstl_copy_n_called = false;
57
58 template <class, class ForwardIterator, class Size, class ForwardOutIterator>
__pstl_copy_n(TestBackend,ForwardIterator,Size,ForwardOutIterator res)59 optional<ForwardOutIterator> __pstl_copy_n(TestBackend, ForwardIterator, Size, ForwardOutIterator res) {
60 assert(!pstl_copy_n_called);
61 pstl_copy_n_called = true;
62 return res;
63 }
64
65 bool pstl_count_called = false;
66
67 template <class, class ForwardIterator, class T>
68 optional<typename std::iterator_traits<ForwardIterator>::difference_type>
__pstl_count(TestBackend,ForwardIterator,ForwardIterator,const T &)69 __pstl_count(TestBackend, ForwardIterator, ForwardIterator, const T&) {
70 assert(!pstl_count_called);
71 pstl_count_called = true;
72 return 0;
73 }
74
75 bool pstl_count_if_called = false;
76
77 template <class, class ForwardIterator, class Pred>
78 optional<typename std::iterator_traits<ForwardIterator>::difference_type>
__pstl_count_if(TestBackend,ForwardIterator,ForwardIterator,Pred)79 __pstl_count_if(TestBackend, ForwardIterator, ForwardIterator, Pred) {
80 assert(!pstl_count_if_called);
81 pstl_count_if_called = true;
82 return 0;
83 }
84
85 bool pstl_generate_called = false;
86
87 template <class, class ForwardIterator, class Gen>
__pstl_generate(TestBackend,ForwardIterator,ForwardIterator,Gen)88 optional<__empty> __pstl_generate(TestBackend, ForwardIterator, ForwardIterator, Gen) {
89 assert(!pstl_generate_called);
90 pstl_generate_called = true;
91 return __empty{};
92 }
93
94 bool pstl_generate_n_called = false;
95
96 template <class, class ForwardIterator, class Size, class Gen>
__pstl_generate_n(TestBackend,Size,ForwardIterator,Gen)97 optional<__empty> __pstl_generate_n(TestBackend, Size, ForwardIterator, Gen) {
98 assert(!pstl_generate_n_called);
99 pstl_generate_n_called = true;
100 return __empty{};
101 }
102
103 bool pstl_none_of_called = false;
104
105 template <class, class ForwardIterator, class Pred>
__pstl_none_of(TestBackend,ForwardIterator,ForwardIterator,Pred)106 optional<bool> __pstl_none_of(TestBackend, ForwardIterator, ForwardIterator, Pred) {
107 assert(!pstl_none_of_called);
108 pstl_none_of_called = true;
109 return true;
110 }
111
112 bool pstl_find_called = false;
113
114 template <class, class ForwardIterator, class Pred>
__pstl_find(TestBackend,ForwardIterator first,ForwardIterator,Pred)115 optional<ForwardIterator> __pstl_find(TestBackend, ForwardIterator first, ForwardIterator, Pred) {
116 assert(!pstl_find_called);
117 pstl_find_called = true;
118 return first;
119 }
120
121 bool pstl_find_if_called = false;
122
123 template <class, class ForwardIterator, class Pred>
__pstl_find_if(TestBackend,ForwardIterator first,ForwardIterator,Pred)124 optional<ForwardIterator> __pstl_find_if(TestBackend, ForwardIterator first, ForwardIterator, Pred) {
125 assert(!pstl_find_if_called);
126 pstl_find_if_called = true;
127 return first;
128 }
129
130 bool pstl_find_if_not_called = false;
131
132 template <class, class ForwardIterator, class Pred>
__pstl_find_if_not(TestBackend,ForwardIterator first,ForwardIterator,Pred)133 optional<ForwardIterator> __pstl_find_if_not(TestBackend, ForwardIterator first, ForwardIterator, Pred) {
134 assert(!pstl_find_if_not_called);
135 pstl_find_if_not_called = true;
136 return first;
137 }
138
139 bool pstl_for_each_called = false;
140
141 template <class, class ForwardIterator, class Size, class Func>
__pstl_for_each(TestBackend,ForwardIterator,Size,Func)142 optional<__empty> __pstl_for_each(TestBackend, ForwardIterator, Size, Func) {
143 assert(!pstl_for_each_called);
144 pstl_for_each_called = true;
145 return __empty{};
146 }
147
148 bool pstl_for_each_n_called = false;
149
150 template <class, class ForwardIterator, class Size, class Func>
__pstl_for_each_n(TestBackend,ForwardIterator,Size,Func)151 optional<__empty> __pstl_for_each_n(TestBackend, ForwardIterator, Size, Func) {
152 assert(!pstl_for_each_n_called);
153 pstl_for_each_n_called = true;
154 return __empty{};
155 }
156
157 bool pstl_fill_called = false;
158
159 template <class, class ForwardIterator, class Size, class Func>
__pstl_fill(TestBackend,ForwardIterator,Size,Func)160 optional<__empty> __pstl_fill(TestBackend, ForwardIterator, Size, Func) {
161 assert(!pstl_fill_called);
162 pstl_fill_called = true;
163 return __empty{};
164 }
165
166 bool pstl_fill_n_called = false;
167
168 template <class, class ForwardIterator, class Size, class Func>
__pstl_fill_n(TestBackend,ForwardIterator,Size,Func)169 optional<__empty> __pstl_fill_n(TestBackend, ForwardIterator, Size, Func) {
170 assert(!pstl_fill_n_called);
171 pstl_fill_n_called = true;
172 return __empty{};
173 }
174
175 bool pstl_move_called = false;
176
177 template <class, class ForwardIterator, class Size, class Func>
__pstl_move(TestBackend,ForwardIterator,Size,Func)178 ForwardIterator __pstl_move(TestBackend, ForwardIterator, Size, Func) {
179 assert(!pstl_move_called);
180 pstl_move_called = true;
181 return 0;
182 }
183
184 bool pstl_is_partitioned_called = false;
185
186 template <class, class ForwardIterator, class Func>
__pstl_is_partitioned(TestBackend,ForwardIterator,ForwardIterator,Func)187 optional<bool> __pstl_is_partitioned(TestBackend, ForwardIterator, ForwardIterator, Func) {
188 assert(!pstl_is_partitioned_called);
189 pstl_is_partitioned_called = true;
190 return true;
191 }
192
193 bool pstl_replace_called = false;
194
195 template <class, class ForwardIterator, class T>
__pstl_replace(TestBackend,ForwardIterator,ForwardIterator,const T &,const T &)196 optional<__empty> __pstl_replace(TestBackend, ForwardIterator, ForwardIterator, const T&, const T&) {
197 assert(!pstl_replace_called);
198 pstl_replace_called = true;
199 return __empty{};
200 }
201
202 bool pstl_replace_if_called = false;
203
204 template <class, class ForwardIterator, class T, class Func>
__pstl_replace_if(TestBackend,ForwardIterator,ForwardIterator,Func,const T &)205 optional<__empty> __pstl_replace_if(TestBackend, ForwardIterator, ForwardIterator, Func, const T&) {
206 assert(!pstl_replace_if_called);
207 pstl_replace_if_called = true;
208 return __empty{};
209 }
210
211 bool pstl_replace_copy_called = false;
212
213 template <class, class ForwardIterator, class ForwardOutIterator, class T>
214 optional<__empty>
__pstl_replace_copy(TestBackend,ForwardIterator,ForwardIterator,ForwardOutIterator,const T &,const T &)215 __pstl_replace_copy(TestBackend, ForwardIterator, ForwardIterator, ForwardOutIterator, const T&, const T&) {
216 assert(!pstl_replace_copy_called);
217 pstl_replace_copy_called = true;
218 return __empty{};
219 }
220
221 bool pstl_replace_copy_if_called = false;
222
223 template <class, class ForwardIterator, class ForwardOutIterator, class T, class Func>
224 optional<__empty>
__pstl_replace_copy_if(TestBackend,ForwardIterator,ForwardIterator,ForwardOutIterator,Func,const T &)225 __pstl_replace_copy_if(TestBackend, ForwardIterator, ForwardIterator, ForwardOutIterator, Func, const T&) {
226 assert(!pstl_replace_copy_if_called);
227 pstl_replace_copy_if_called = true;
228 return __empty{};
229 }
230
231 bool pstl_rotate_copy_called = false;
232
233 template <class, class ForwardIterator, class ForwardOutIterator>
234 optional<ForwardOutIterator>
__pstl_rotate_copy(TestBackend,ForwardIterator,ForwardIterator,ForwardIterator,ForwardOutIterator res)235 __pstl_rotate_copy(TestBackend, ForwardIterator, ForwardIterator, ForwardIterator, ForwardOutIterator res) {
236 assert(!pstl_rotate_copy_called);
237 pstl_rotate_copy_called = true;
238 return res;
239 }
240
241 bool pstl_unary_transform_called = false;
242
243 template <class, class ForwardIterator, class ForwardOutIterator, class UnaryOperation>
244 optional<ForwardOutIterator>
__pstl_transform(TestBackend,ForwardIterator,ForwardIterator,ForwardOutIterator res,UnaryOperation)245 __pstl_transform(TestBackend, ForwardIterator, ForwardIterator, ForwardOutIterator res, UnaryOperation) {
246 assert(!pstl_unary_transform_called);
247 pstl_unary_transform_called = true;
248 return res;
249 }
250
251 bool pstl_binary_transform_called = false;
252
253 template <class, class ForwardIterator1, class ForwardIterator2, class ForwardOutIterator, class BinaryOperation>
__pstl_transform(TestBackend,ForwardIterator1,ForwardIterator1,ForwardIterator2,ForwardOutIterator res,BinaryOperation)254 optional<ForwardOutIterator> __pstl_transform(
255 TestBackend, ForwardIterator1, ForwardIterator1, ForwardIterator2, ForwardOutIterator res, BinaryOperation) {
256 assert(!pstl_binary_transform_called);
257 pstl_binary_transform_called = true;
258 return res;
259 }
260
261 bool pstl_reduce_with_init_called = false;
262
263 template <class, class ForwardIterator, class T, class BinaryOperation>
__pstl_reduce(TestBackend,ForwardIterator,ForwardIterator,T v,BinaryOperation)264 optional<T> __pstl_reduce(TestBackend, ForwardIterator, ForwardIterator, T v, BinaryOperation) {
265 assert(!pstl_reduce_with_init_called);
266 pstl_reduce_with_init_called = true;
267 return v;
268 }
269
270 bool pstl_reduce_without_init_called = false;
271
272 template <class, class ForwardIterator>
273 optional<typename std::iterator_traits<ForwardIterator>::value_type>
__pstl_reduce(TestBackend,ForwardIterator first,ForwardIterator)274 __pstl_reduce(TestBackend, ForwardIterator first, ForwardIterator) {
275 assert(!pstl_reduce_without_init_called);
276 pstl_reduce_without_init_called = true;
277 return *first;
278 }
279
280 bool pstl_sort_called = false;
281
282 template <class, class RandomAccessIterator, class Comp>
__pstl_sort(TestBackend,RandomAccessIterator,RandomAccessIterator,Comp)283 optional<__empty> __pstl_sort(TestBackend, RandomAccessIterator, RandomAccessIterator, Comp) {
284 assert(!pstl_sort_called);
285 pstl_sort_called = true;
286 return __empty{};
287 }
288
289 bool pstl_stable_sort_called = false;
290
291 template <class, class RandomAccessIterator, class Comp>
__pstl_stable_sort(TestBackend,RandomAccessIterator,RandomAccessIterator,Comp)292 optional<__empty> __pstl_stable_sort(TestBackend, RandomAccessIterator, RandomAccessIterator, Comp) {
293 assert(!pstl_stable_sort_called);
294 pstl_stable_sort_called = true;
295 return __empty{};
296 }
297
298 bool pstl_unary_transform_reduce_called = false;
299
300 template <class, class ForwardIterator, class T, class UnaryOperation, class BinaryOperation>
__pstl_transform_reduce(TestBackend,ForwardIterator,ForwardIterator,T v,UnaryOperation,BinaryOperation)301 T __pstl_transform_reduce(TestBackend, ForwardIterator, ForwardIterator, T v, UnaryOperation, BinaryOperation) {
302 assert(!pstl_unary_transform_reduce_called);
303 pstl_unary_transform_reduce_called = true;
304 return v;
305 }
306
307 bool pstl_binary_transform_reduce_called = false;
308
309 template <class,
310 class ForwardIterator1,
311 class ForwardIterator2,
312 class T,
313 class BinaryOperation1,
314 class BinaryOperation2>
__pstl_transform_reduce(TestBackend,ForwardIterator1,ForwardIterator1,ForwardIterator2,T v,BinaryOperation1,BinaryOperation2)315 typename std::iterator_traits<ForwardIterator1>::value_type __pstl_transform_reduce(
316 TestBackend, ForwardIterator1, ForwardIterator1, ForwardIterator2, T v, BinaryOperation1, BinaryOperation2) {
317 assert(!pstl_binary_transform_reduce_called);
318 pstl_binary_transform_reduce_called = true;
319 return v;
320 }
321
322 _LIBCPP_END_NAMESPACE_STD
323
324 #include <algorithm>
325 #include <cassert>
326 #include <iterator>
327 #include <numeric>
328
329 template <>
330 inline constexpr bool std::is_execution_policy_v<TestPolicy> = true;
331
332 template <>
333 struct std::__select_backend<TestPolicy> {
334 using type = TestBackend;
335 };
336
main(int,char **)337 int main(int, char**) {
338 int a[] = {1, 2};
339 auto pred = [](auto&&...) { return true; };
340
341 (void)std::any_of(TestPolicy{}, std::begin(a), std::end(a), pred);
342 assert(std::pstl_any_of_called);
343 (void)std::all_of(TestPolicy{}, std::begin(a), std::end(a), pred);
344 assert(std::pstl_all_of_called);
345 (void)std::none_of(TestPolicy{}, std::begin(a), std::end(a), pred);
346 assert(std::pstl_none_of_called);
347 std::copy(TestPolicy{}, std::begin(a), std::end(a), std::begin(a));
348 assert(std::pstl_copy_called);
349 std::copy_n(TestPolicy{}, std::begin(a), 1, std::begin(a));
350 assert(std::pstl_copy_n_called);
351 (void)std::count(TestPolicy{}, std::begin(a), std::end(a), 0);
352 assert(std::pstl_count_called);
353 (void)std::count_if(TestPolicy{}, std::begin(a), std::end(a), pred);
354 assert(std::pstl_count_if_called);
355 (void)std::fill(TestPolicy{}, std::begin(a), std::end(a), 0);
356 assert(std::pstl_fill_called);
357 (void)std::fill_n(TestPolicy{}, std::begin(a), std::size(a), 0);
358 assert(std::pstl_fill_n_called);
359 (void)std::find(TestPolicy{}, std::begin(a), std::end(a), 0);
360 assert(std::pstl_find_called);
361 (void)std::find_if(TestPolicy{}, std::begin(a), std::end(a), pred);
362 assert(std::pstl_find_if_called);
363 (void)std::find_if_not(TestPolicy{}, std::begin(a), std::end(a), pred);
364 assert(std::pstl_find_if_not_called);
365 (void)std::for_each(TestPolicy{}, std::begin(a), std::end(a), pred);
366 assert(std::pstl_for_each_called);
367 (void)std::for_each_n(TestPolicy{}, std::begin(a), std::size(a), pred);
368 assert(std::pstl_for_each_n_called);
369 (void)std::generate(TestPolicy{}, std::begin(a), std::end(a), pred);
370 assert(std::pstl_generate_called);
371 (void)std::generate_n(TestPolicy{}, std::begin(a), std::size(a), pred);
372 assert(std::pstl_generate_n_called);
373 (void)std::is_partitioned(TestPolicy{}, std::begin(a), std::end(a), pred);
374 assert(std::pstl_is_partitioned_called);
375 (void)std::move(TestPolicy{}, std::begin(a), std::end(a), std::begin(a));
376 assert(std::pstl_move_called);
377 (void)std::replace(TestPolicy{}, std::begin(a), std::end(a), 0, 0);
378 assert(std::pstl_replace_called);
379 (void)std::replace_if(TestPolicy{}, std::begin(a), std::end(a), pred, 0);
380 assert(std::pstl_replace_if_called);
381 (void)std::replace_copy(TestPolicy{}, std::begin(a), std::end(a), std::begin(a), 0, 0);
382 assert(std::pstl_replace_copy_called);
383 (void)std::replace_copy_if(TestPolicy{}, std::begin(a), std::end(a), std::begin(a), pred, 0);
384 assert(std::pstl_replace_copy_if_called);
385 (void)std::transform(TestPolicy{}, std::begin(a), std::end(a), std::begin(a), pred);
386 assert(std::pstl_unary_transform_called);
387 (void)std::transform(TestPolicy{}, std::begin(a), std::end(a), std::begin(a), std::begin(a), pred);
388 assert(std::pstl_unary_transform_called);
389 (void)std::reduce(TestPolicy{}, std::begin(a), std::end(a), 0, pred);
390 assert(std::pstl_reduce_with_init_called);
391 (void)std::reduce(TestPolicy{}, std::begin(a), std::end(a));
392 assert(std::pstl_reduce_without_init_called);
393 (void)std::rotate_copy(TestPolicy{}, std::begin(a), std::begin(a), std::end(a), std::begin(a));
394 assert(std::pstl_rotate_copy_called);
395 (void)std::sort(TestPolicy{}, std::begin(a), std::end(a));
396 assert(std::pstl_sort_called);
397 (void)std::stable_sort(TestPolicy{}, std::begin(a), std::end(a));
398 assert(std::pstl_stable_sort_called);
399 (void)std::transform_reduce(TestPolicy{}, std::begin(a), std::end(a), 0, pred, pred);
400 assert(std::pstl_unary_transform_reduce_called);
401 (void)std::transform_reduce(TestPolicy{}, std::begin(a), std::end(a), std::begin(a), 0, pred, pred);
402 assert(std::pstl_binary_transform_reduce_called);
403
404 return 0;
405 }
406