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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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 | |
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(arr&: a), std::end(arr&: a), pred); |
342 | assert(std::pstl_any_of_called); |
343 | (void)std::all_of(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), pred); |
344 | assert(std::pstl_all_of_called); |
345 | (void)std::none_of(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), pred); |
346 | assert(std::pstl_none_of_called); |
347 | std::copy(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), std::begin(arr&: a)); |
348 | assert(std::pstl_copy_called); |
349 | std::copy_n(TestPolicy{}, std::begin(arr&: a), 1, std::begin(arr&: a)); |
350 | assert(std::pstl_copy_n_called); |
351 | (void)std::count(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), 0); |
352 | assert(std::pstl_count_called); |
353 | (void)std::count_if(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), pred); |
354 | assert(std::pstl_count_if_called); |
355 | (void)std::fill(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), 0); |
356 | assert(std::pstl_fill_called); |
357 | (void)std::fill_n(TestPolicy{}, std::begin(arr&: a), std::size(a), 0); |
358 | assert(std::pstl_fill_n_called); |
359 | (void)std::find(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), 0); |
360 | assert(std::pstl_find_called); |
361 | (void)std::find_if(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), pred); |
362 | assert(std::pstl_find_if_called); |
363 | (void)std::find_if_not(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), pred); |
364 | assert(std::pstl_find_if_not_called); |
365 | (void)std::for_each(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), pred); |
366 | assert(std::pstl_for_each_called); |
367 | (void)std::for_each_n(TestPolicy{}, std::begin(arr&: a), std::size(a), pred); |
368 | assert(std::pstl_for_each_n_called); |
369 | (void)std::generate(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), pred); |
370 | assert(std::pstl_generate_called); |
371 | (void)std::generate_n(TestPolicy{}, std::begin(arr&: a), std::size(a), pred); |
372 | assert(std::pstl_generate_n_called); |
373 | (void)std::is_partitioned(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), pred); |
374 | assert(std::pstl_is_partitioned_called); |
375 | (void)std::move(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), std::begin(arr&: a)); |
376 | assert(std::pstl_move_called); |
377 | (void)std::replace(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), 0, 0); |
378 | assert(std::pstl_replace_called); |
379 | (void)std::replace_if(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), pred, 0); |
380 | assert(std::pstl_replace_if_called); |
381 | (void)std::replace_copy(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), std::begin(arr&: a), 0, 0); |
382 | assert(std::pstl_replace_copy_called); |
383 | (void)std::replace_copy_if(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), std::begin(arr&: a), pred, 0); |
384 | assert(std::pstl_replace_copy_if_called); |
385 | (void)std::transform(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), std::begin(arr&: a), pred); |
386 | assert(std::pstl_unary_transform_called); |
387 | (void)std::transform(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), std::begin(arr&: a), std::begin(arr&: a), pred); |
388 | assert(std::pstl_unary_transform_called); |
389 | (void)std::reduce(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), 0, pred); |
390 | assert(std::pstl_reduce_with_init_called); |
391 | (void)std::reduce(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a)); |
392 | assert(std::pstl_reduce_without_init_called); |
393 | (void)std::rotate_copy(TestPolicy{}, std::begin(arr&: a), std::begin(arr&: a), std::end(arr&: a), std::begin(arr&: a)); |
394 | assert(std::pstl_rotate_copy_called); |
395 | (void)std::sort(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a)); |
396 | assert(std::pstl_sort_called); |
397 | (void)std::stable_sort(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a)); |
398 | assert(std::pstl_stable_sort_called); |
399 | (void)std::transform_reduce(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), 0, pred, pred); |
400 | assert(std::pstl_unary_transform_reduce_called); |
401 | (void)std::transform_reduce(TestPolicy{}, std::begin(arr&: a), std::end(arr&: a), std::begin(arr&: a), 0, pred, pred); |
402 | assert(std::pstl_binary_transform_reduce_called); |
403 | |
404 | return 0; |
405 | } |
406 | |