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