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
24struct TestPolicy {};
25struct TestBackend {};
26
27_LIBCPP_BEGIN_NAMESPACE_STD
28
29bool pstl_any_of_called = false;
30
31template <class, class ForwardIterator, class Pred>
32optional<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
38bool pstl_all_of_called = false;
39
40template <class, class ForwardIterator, class Pred>
41optional<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
47bool pstl_copy_called = false;
48
49template <class, class ForwardIterator, class ForwardOutIterator>
50optional<ForwardOutIterator> __pstl_copy(TestBackend, ForwardIterator, ForwardIterator, ForwardOutIterator res) {
51 assert(!pstl_copy_called);
52 pstl_copy_called = true;
53 return res;
54}
55
56bool pstl_copy_n_called = false;
57
58template <class, class ForwardIterator, class Size, class ForwardOutIterator>
59optional<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
65bool pstl_count_called = false;
66
67template <class, class ForwardIterator, class T>
68optional<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
75bool pstl_count_if_called = false;
76
77template <class, class ForwardIterator, class Pred>
78optional<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
85bool pstl_generate_called = false;
86
87template <class, class ForwardIterator, class Gen>
88optional<__empty> __pstl_generate(TestBackend, ForwardIterator, ForwardIterator, Gen) {
89 assert(!pstl_generate_called);
90 pstl_generate_called = true;
91 return __empty{};
92}
93
94bool pstl_generate_n_called = false;
95
96template <class, class ForwardIterator, class Size, class Gen>
97optional<__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
103bool pstl_none_of_called = false;
104
105template <class, class ForwardIterator, class Pred>
106optional<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
112bool pstl_find_called = false;
113
114template <class, class ForwardIterator, class Pred>
115optional<ForwardIterator> __pstl_find(TestBackend, ForwardIterator first, ForwardIterator, Pred) {
116 assert(!pstl_find_called);
117 pstl_find_called = true;
118 return first;
119}
120
121bool pstl_find_if_called = false;
122
123template <class, class ForwardIterator, class Pred>
124optional<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
130bool pstl_find_if_not_called = false;
131
132template <class, class ForwardIterator, class Pred>
133optional<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
139bool pstl_for_each_called = false;
140
141template <class, class ForwardIterator, class Size, class Func>
142optional<__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
148bool pstl_for_each_n_called = false;
149
150template <class, class ForwardIterator, class Size, class Func>
151optional<__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
157bool pstl_fill_called = false;
158
159template <class, class ForwardIterator, class Size, class Func>
160optional<__empty> __pstl_fill(TestBackend, ForwardIterator, Size, Func) {
161 assert(!pstl_fill_called);
162 pstl_fill_called = true;
163 return __empty{};
164}
165
166bool pstl_fill_n_called = false;
167
168template <class, class ForwardIterator, class Size, class Func>
169optional<__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
175bool pstl_move_called = false;
176
177template <class, class ForwardIterator, class Size, class Func>
178ForwardIterator __pstl_move(TestBackend, ForwardIterator, Size, Func) {
179 assert(!pstl_move_called);
180 pstl_move_called = true;
181 return 0;
182}
183
184bool pstl_is_partitioned_called = false;
185
186template <class, class ForwardIterator, class Func>
187optional<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
193bool pstl_replace_called = false;
194
195template <class, class ForwardIterator, class T>
196optional<__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
202bool pstl_replace_if_called = false;
203
204template <class, class ForwardIterator, class T, class Func>
205optional<__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
211bool pstl_replace_copy_called = false;
212
213template <class, class ForwardIterator, class ForwardOutIterator, class T>
214optional<__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
221bool pstl_replace_copy_if_called = false;
222
223template <class, class ForwardIterator, class ForwardOutIterator, class T, class Func>
224optional<__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
231bool pstl_rotate_copy_called = false;
232
233template <class, class ForwardIterator, class ForwardOutIterator>
234optional<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
241bool pstl_unary_transform_called = false;
242
243template <class, class ForwardIterator, class ForwardOutIterator, class UnaryOperation>
244optional<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
251bool pstl_binary_transform_called = false;
252
253template <class, class ForwardIterator1, class ForwardIterator2, class ForwardOutIterator, class BinaryOperation>
254optional<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
261bool pstl_reduce_with_init_called = false;
262
263template <class, class ForwardIterator, class T, class BinaryOperation>
264optional<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
270bool pstl_reduce_without_init_called = false;
271
272template <class, class ForwardIterator>
273optional<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
280bool pstl_sort_called = false;
281
282template <class, class RandomAccessIterator, class Comp>
283optional<__empty> __pstl_sort(TestBackend, RandomAccessIterator, RandomAccessIterator, Comp) {
284 assert(!pstl_sort_called);
285 pstl_sort_called = true;
286 return __empty{};
287}
288
289bool pstl_stable_sort_called = false;
290
291template <class, class RandomAccessIterator, class Comp>
292optional<__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
298bool pstl_unary_transform_reduce_called = false;
299
300template <class, class ForwardIterator, class T, class UnaryOperation, class BinaryOperation>
301T __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
307bool pstl_binary_transform_reduce_called = false;
308
309template <class,
310 class ForwardIterator1,
311 class ForwardIterator2,
312 class T,
313 class BinaryOperation1,
314 class BinaryOperation2>
315typename 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
329template <>
330inline constexpr bool std::is_execution_policy_v<TestPolicy> = true;
331
332template <>
333struct std::__select_backend<TestPolicy> {
334 using type = TestBackend;
335};
336
337int 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

source code of libcxx/test/libcxx/algorithms/pstl.robust_against_customization_points_not_working.pass.cpp