[MLIR] Extend MPI dialect (#123255)
[llvm-project.git] / libcxx / test / std / algorithms / pstl.exception_handling.pass.cpp
blobe24ce66314197de27c30b71fef82cbfd7a291457
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 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
10 // UNSUPPORTED: no-exceptions
11 // `check_assertion.h` requires Unix headers and regex support.
12 // REQUIRES: has-unix-headers
13 // UNSUPPORTED: no-localization
15 // UNSUPPORTED: libcpp-has-no-incomplete-pstl
17 // <algorithm>
18 // <numeric>
20 // Check that PSTL algorithms terminate on user-thrown exceptions.
22 #include <algorithm>
23 #include <numeric>
25 #include "check_assertion.h"
26 #include "test_execution_policies.h"
27 #include "test_iterators.h"
29 template <class F>
30 void assert_non_throwing(F f) {
31 // We wrap this whole test in EXPECT_STD_TERMINATE because if f() terminates, we want the test to pass,
32 // since this signals proper handling of user exceptions in the PSTL.
33 EXPECT_STD_TERMINATE([&] {
34 bool threw = false;
35 try {
36 f();
37 } catch (...) {
38 threw = true;
40 // If nothing was thrown, call std::terminate() to pass the EXPECT_STD_TERMINATE assertion.
41 // Otherwise, don't call std::terminate() to fail the assertion.
42 if (!threw)
43 std::terminate();
44 });
47 struct ThrowToken {
48 void activate() { active_ = true; }
49 void deactivate() { active_ = false; }
50 bool active() const { return active_; }
52 private:
53 bool active_{false};
56 template <class Func>
57 struct on_scope_exit {
58 explicit on_scope_exit(Func func) : func_(func) {}
59 ~on_scope_exit() { func_(); }
61 private:
62 Func func_;
64 template <class Func>
65 on_scope_exit(Func) -> on_scope_exit<Func>;
67 int main(int, char**) {
68 test_execution_policies([&](auto&& policy) {
69 int a[] = {1, 2, 3, 4};
70 int b[] = {1, 2, 3};
71 int n = 2;
72 int storage[999];
73 int val = 99;
74 int init = 1;
76 // We generate a certain number of "tokens" and we activate exactly one on each iteration. We then
77 // throw in a given operation only when that token is active. That way we check that each argument
78 // of the algorithm is handled properly.
79 ThrowToken tokens[7];
80 for (ThrowToken& t : tokens) {
81 t.activate();
82 on_scope_exit _([&] { t.deactivate(); });
84 auto first1 = util::throw_on_move_iterator(std::begin(a), tokens[0].active() ? 1 : -1);
85 auto last1 = util::throw_on_move_iterator(std::end(a), tokens[1].active() ? 1 : -1);
86 auto first2 = util::throw_on_move_iterator(std::begin(b), tokens[2].active() ? 1 : -1);
87 auto last2 = util::throw_on_move_iterator(std::end(b), tokens[3].active() ? 1 : -1);
88 auto dest = util::throw_on_move_iterator(std::end(storage), tokens[4].active() ? 1 : -1);
89 auto maybe_throw = [](ThrowToken const& token, auto f) {
90 return [&token, f](auto... args) {
91 if (token.active())
92 throw 1;
93 return f(args...);
98 auto pred = maybe_throw(tokens[5], [](int x) -> bool { return x % 2 == 0; });
100 // all_of(first, last, pred)
101 assert_non_throwing([=, &policy] { (void)std::all_of(policy, std::move(first1), std::move(last1), pred); });
103 // any_of(first, last, pred)
104 assert_non_throwing([=, &policy] { (void)std::any_of(policy, std::move(first1), std::move(last1), pred); });
106 // none_of(first, last, pred)
107 assert_non_throwing([=, &policy] { (void)std::none_of(policy, std::move(first1), std::move(last1), pred); });
111 // copy(first, last, dest)
112 assert_non_throwing([=, &policy] {
113 (void)std::copy(policy, std::move(first1), std::move(last1), std::move(dest));
116 // copy_n(first, n, dest)
117 assert_non_throwing([=, &policy] { (void)std::copy_n(policy, std::move(first1), n, std::move(dest)); });
121 auto pred = maybe_throw(tokens[5], [](int x) -> bool { return x % 2 == 0; });
123 // count(first, last, val)
124 assert_non_throwing([=, &policy] { (void)std::count(policy, std::move(first1), std::move(last1), val); });
126 // count_if(first, last, pred)
127 assert_non_throwing([=, &policy] { (void)std::count_if(policy, std::move(first1), std::move(last1), pred); });
131 auto binary_pred = maybe_throw(tokens[5], [](int x, int y) -> bool { return x == y; });
133 // equal(first1, last1, first2)
134 assert_non_throwing([=, &policy] {
135 (void)std::equal(policy, std::move(first1), std::move(last1), std::move(first2));
138 // equal(first1, last1, first2, binary_pred)
139 assert_non_throwing([=, &policy] {
140 (void)std::equal(policy, std::move(first1), std::move(last1), std::move(first2), binary_pred);
143 // equal(first1, last1, first2, last2)
144 assert_non_throwing([=, &policy] {
145 (void)std::equal(policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2));
148 // equal(first1, last1, first2, last2, binary_pred)
149 assert_non_throwing([=, &policy] {
150 (void)std::equal(
151 policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2), binary_pred);
156 // fill(first, last, val)
157 assert_non_throwing([=, &policy] { (void)std::fill(policy, std::move(first1), std::move(last1), val); });
159 // fill_n(first, n, val)
160 assert_non_throwing([=, &policy] { (void)std::fill_n(policy, std::move(first1), n, val); });
164 auto pred = maybe_throw(tokens[5], [](int x) -> bool { return x % 2 == 0; });
166 // find(first, last, val)
167 assert_non_throwing([=, &policy] { (void)std::find(policy, std::move(first1), std::move(last1), val); });
169 // find_if(first, last, pred)
170 assert_non_throwing([=, &policy] { (void)std::find_if(policy, std::move(first1), std::move(last1), pred); });
172 // find_if_not(first, last, pred)
173 assert_non_throwing([=, &policy] {
174 (void)std::find_if_not(policy, std::move(first1), std::move(last1), pred);
179 auto func = maybe_throw(tokens[5], [](int) {});
181 // for_each(first, last, func)
182 assert_non_throwing([=, &policy] { (void)std::for_each(policy, std::move(first1), std::move(last1), func); });
184 // for_each_n(first, n, func)
185 assert_non_throwing([=, &policy] { (void)std::for_each_n(policy, std::move(first1), n, func); });
189 auto gen = maybe_throw(tokens[5], []() -> int { return 42; });
191 // generate(first, last, func)
192 assert_non_throwing([=, &policy] { (void)std::generate(policy, std::move(first1), std::move(last1), gen); });
194 // generate_n(first, n, func)
195 assert_non_throwing([=, &policy] { (void)std::generate_n(policy, std::move(first1), n, gen); });
199 auto pred = maybe_throw(tokens[5], [](int x) -> bool { return x % 2 == 0; });
201 // is_partitioned(first, last, pred)
202 assert_non_throwing([=, &policy] {
203 (void)std::is_partitioned(policy, std::move(first1), std::move(last1), pred);
208 auto compare = maybe_throw(tokens[5], [](int x, int y) -> bool { return x < y; });
210 // merge(first1, last1, first2, last2, dest)
211 assert_non_throwing([=, &policy] {
212 (void)std::merge(
213 policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2), std::move(dest));
216 // merge(first1, last1, first2, last2, dest, comp)
217 assert_non_throwing([=, &policy] {
218 (void)std::merge(
219 policy,
220 std::move(first1),
221 std::move(last1),
222 std::move(first2),
223 std::move(last2),
224 std::move(dest),
225 compare);
230 // move(first, last, dest)
231 assert_non_throwing([=, &policy] {
232 (void)std::move(policy, std::move(first1), std::move(last1), std::move(dest));
237 auto pred = maybe_throw(tokens[5], [](int x) -> bool { return x % 2 == 0; });
239 // replace_if(first, last, pred, val)
240 assert_non_throwing([=, &policy] {
241 (void)std::replace_if(policy, std::move(first1), std::move(last1), pred, val);
244 // replace(first, last, val1, val2)
245 assert_non_throwing([=, &policy] {
246 (void)std::replace(policy, std::move(first1), std::move(last1), val, val);
249 // replace_copy_if(first, last, dest, pred, val)
250 assert_non_throwing([=, &policy] {
251 (void)std::replace_copy_if(policy, std::move(first1), std::move(last1), std::move(dest), pred, val);
254 // replace_copy(first, last, dest, val1, val2)
255 assert_non_throwing([=, &policy] {
256 (void)std::replace_copy(policy, std::move(first1), std::move(last1), std::move(dest), val, val);
261 auto mid1 = util::throw_on_move_iterator(std::begin(a) + 2, tokens[5].active() ? 1 : -1);
263 // rotate_copy(first, mid, last, dest)
264 assert_non_throwing([=, &policy] {
265 (void)std::rotate_copy(policy, std::move(first1), std::move(mid1), std::move(last1), std::move(dest));
270 auto compare = maybe_throw(tokens[5], [](int x, int y) -> bool { return x < y; });
272 // sort(first, last)
273 assert_non_throwing([=, &policy] { (void)std::sort(policy, std::move(first1), std::move(last1)); });
275 // sort(first, last, comp)
276 assert_non_throwing([=, &policy] { (void)std::sort(policy, std::move(first1), std::move(last1), compare); });
278 // stable_sort(first, last)
279 assert_non_throwing([=, &policy] { (void)std::stable_sort(policy, std::move(first1), std::move(last1)); });
281 // stable_sort(first, last, comp)
282 assert_non_throwing([=, &policy] {
283 (void)std::stable_sort(policy, std::move(first1), std::move(last1), compare);
288 auto unary = maybe_throw(tokens[5], [](int x) -> int { return x * 2; });
289 auto binary = maybe_throw(tokens[5], [](int x, int y) -> int { return x * y; });
291 // transform(first, last, dest, func)
292 assert_non_throwing([=, &policy] {
293 (void)std::transform(policy, std::move(first1), std::move(last1), std::move(dest), unary);
296 // transform(first1, last1, first2, dest, func)
297 assert_non_throwing([=, &policy] {
298 (void)std::transform(policy, std::move(first1), std::move(last1), std::move(first2), std::move(dest), binary);
303 auto reduction = maybe_throw(tokens[5], [](int x, int y) -> int { return x + y; });
304 auto transform_unary = maybe_throw(tokens[6], [](int x) -> int { return x * 2; });
305 auto transform_binary = maybe_throw(tokens[6], [](int x, int y) -> int { return x * y; });
307 // transform_reduce(first1, last1, first2, init)
308 assert_non_throwing([=, &policy] {
309 (void)std::transform_reduce(policy, std::move(first1), std::move(last1), std::move(first2), init);
312 // transform_reduce(first1, last1, init, reduce, transform)
313 assert_non_throwing([=, &policy] {
314 (void)std::transform_reduce(policy, std::move(first1), std::move(last1), init, reduction, transform_unary);
317 // transform_reduce(first1, last1, first2, init, reduce, transform)
318 assert_non_throwing([=, &policy] {
319 (void)std::transform_reduce(
320 policy, std::move(first1), std::move(last1), std::move(first2), init, reduction, transform_binary);
325 auto reduction = maybe_throw(tokens[5], [](int x, int y) -> int { return x + y; });
327 // reduce(first, last)
328 assert_non_throwing([=, &policy] { (void)std::reduce(policy, std::move(first1), std::move(last1)); });
330 // reduce(first, last, init)
331 assert_non_throwing([=, &policy] { (void)std::reduce(policy, std::move(first1), std::move(last1), init); });
333 // reduce(first, last, init, binop)
334 assert_non_throwing([=, &policy] {
335 (void)std::reduce(policy, std::move(first1), std::move(last1), init, reduction);