diff --git a/libcxx/include/__algorithm/pstl_backend.h b/libcxx/include/__algorithm/pstl_backend.h --- a/libcxx/include/__algorithm/pstl_backend.h +++ b/libcxx/include/__algorithm/pstl_backend.h @@ -152,6 +152,12 @@ // TODO: Complete this list +Exception handling +================== + +The backend is expected to terminate on any user-thrown exceptions. This includes exceptions which are thrown by a +parallel algorithm which is invoked inside another algorithm. If any allocation fails, the backend shall throw +std::bad_alloc. */ template diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backend.h b/libcxx/include/__algorithm/pstl_backends/cpu_backend.h --- a/libcxx/include/__algorithm/pstl_backends/cpu_backend.h +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backend.h @@ -44,6 +44,13 @@ _LeafSort __leaf_sort); TODO: Document the parallel backend + +Exception handling +================== + +The backend is expected to terminate on any user-thrown exceptions. This includes exceptions which are thrown by a +parallel algorithm which is invoked inside another algorithm. If any allocation fails, the backend shall throw +std::bad_alloc. */ #include <__algorithm/pstl_backends/cpu_backends/any_of.h> diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/any_of.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/any_of.h --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/any_of.h +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/any_of.h @@ -68,18 +68,16 @@ __pstl_any_of(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && __has_random_access_iterator_category<_ForwardIterator>::value) { - return std::__terminate_on_exception([&] { - return std::__parallel_or( - __first, __last, [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { - return std::__pstl_any_of<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, __brick_first, __brick_last, __pred); - }); - }); + return std::__parallel_or( + __first, __last, [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + return std::__pstl_any_of<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __pred); + }); } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && __has_random_access_iterator_category<_ForwardIterator>::value) { - return std::__simd_or(__first, __last - __first, __pred); + return std::__terminate_on_exception([&] { return std::__simd_or(__first, __last - __first, __pred); }); } else { - return std::any_of(__first, __last, __pred); + return std::__terminate_on_exception([&] { return std::any_of(__first, __last, __pred); }); } } diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/fill.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/fill.h --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/fill.h +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/fill.h @@ -38,18 +38,16 @@ __pstl_fill(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && __has_random_access_iterator_category<_ForwardIterator>::value) { - std::__terminate_on_exception([&] { - __par_backend::__parallel_for( - __first, __last, [&__value](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { - std::__pstl_fill<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, __brick_first, __brick_last, __value); - }); - }); + __par_backend::__parallel_for( + __first, __last, [&__value](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + std::__pstl_fill<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __value); + }); } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && __has_random_access_iterator_category<_ForwardIterator>::value) { - std::__simd_fill_n(__first, __last - __first, __value); + return std::__terminate_on_exception([&] { std::__simd_fill_n(__first, __last - __first, __value); }); } else { - std::fill(__first, __last, __value); + return std::__terminate_on_exception([&] { std::fill(__first, __last, __value); }); } } diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/find_if.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/find_if.h --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/find_if.h +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/find_if.h @@ -94,25 +94,26 @@ __pstl_find_if(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && __has_random_access_iterator_category<_ForwardIterator>::value) { - return std::__terminate_on_exception([&] { - return std::__parallel_find( - __first, - __last, - [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { - return std::__pstl_find_if<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, __brick_first, __brick_last, __pred); - }, - less<>{}, - true); - }); + return std::__parallel_find( + __first, + __last, + [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + return std::__pstl_find_if<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __pred); + }, + less<>{}, + true); } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && __has_random_access_iterator_category<_ForwardIterator>::value) { using __diff_t = __iter_diff_t<_ForwardIterator>; - return std::__simd_first(__first, __diff_t(0), __last - __first, [&__pred](_ForwardIterator __iter, __diff_t __i) { - return __pred(__iter[__i]); + return std::__terminate_on_exception([&] { + return std::__simd_first( + __first, __diff_t(0), __last - __first, [&__pred](_ForwardIterator __iter, __diff_t __i) { + return __pred(__iter[__i]); + }); }); } else { - return std::find_if(__first, __last, __pred); + return std::__terminate_on_exception([&] { return std::find_if(__first, __last, __pred); }); } } diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/for_each.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/for_each.h --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/for_each.h +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/for_each.h @@ -38,18 +38,16 @@ __pstl_for_each(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Functor __func) { if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && __has_random_access_iterator_category<_ForwardIterator>::value) { - std::__terminate_on_exception([&] { - std::__par_backend::__parallel_for( - __first, __last, [__func](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { - std::__pstl_for_each<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, __brick_first, __brick_last, __func); - }); - }); + std::__par_backend::__parallel_for( + __first, __last, [__func](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + std::__pstl_for_each<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __func); + }); } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && __has_random_access_iterator_category<_ForwardIterator>::value) { - std::__simd_walk_1(__first, __last - __first, __func); + return std::__terminate_on_exception([&] { return std::__simd_walk_1(__first, __last - __first, __func); }); } else { - std::for_each(__first, __last, __func); + return std::__terminate_on_exception([&] { return std::for_each(__first, __last, __func); }); } } diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/merge.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/merge.h --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/merge.h +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/merge.h @@ -42,33 +42,31 @@ __has_random_access_iterator_category<_ForwardIterator1>::value && __has_random_access_iterator_category<_ForwardIterator2>::value && __has_random_access_iterator_category<_ForwardOutIterator>::value) { - return std::__terminate_on_exception([&] { - __par_backend::__parallel_merge( - __first1, - __last1, - __first2, - __last2, - __result, - __comp, - [](_ForwardIterator1 __g_first1, - _ForwardIterator1 __g_last1, - _ForwardIterator2 __g_first2, - _ForwardIterator2 __g_last2, - _ForwardOutIterator __g_result, - _Comp __g_comp) { - return std::__pstl_merge<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, - std::move(__g_first1), - std::move(__g_last1), - std::move(__g_first2), - std::move(__g_last2), - std::move(__g_result), - std::move(__g_comp)); - }); - return __result + (__last1 - __first1) + (__last2 - __first2); - }); + __par_backend::__parallel_merge( + __first1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_ForwardIterator1 __g_first1, + _ForwardIterator1 __g_last1, + _ForwardIterator2 __g_first2, + _ForwardIterator2 __g_last2, + _ForwardOutIterator __g_result, + _Comp __g_comp) { + return std::__pstl_merge<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, + std::move(__g_first1), + std::move(__g_last1), + std::move(__g_first2), + std::move(__g_last2), + std::move(__g_result), + std::move(__g_comp)); + }); + return __result + (__last1 - __first1) + (__last2 - __first2); } else { - return std::merge(__first1, __last1, __first2, __last2, __result, __comp); + return std::__terminate_on_exception([&] { return std::merge(__first1, __last1, __first2, __last2, __result, __comp); }); } } diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/serial.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/serial.h --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/serial.h +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/serial.h @@ -26,23 +26,24 @@ inline namespace __serial_cpu_backend { template -_LIBCPP_HIDE_FROM_ABI void __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) { +_LIBCPP_HIDE_FROM_ABI void +__parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) noexcept { __f(__first, __last); } template _LIBCPP_HIDE_FROM_ABI _Tp -__parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) { +__parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) noexcept { return __reduce(std::move(__first), std::move(__last), std::move(__init)); } template _LIBCPP_HIDE_FROM_ABI void __parallel_stable_sort( - _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) { + _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) noexcept { __leaf_sort(__first, __last, __comp); } -_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {} +_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() noexcept {} template ) { - std::__terminate_on_exception([&] { - __par_backend::__parallel_stable_sort( - __first, __last, __comp, [](_RandomAccessIterator __g_first, _RandomAccessIterator __g_last, _Comp __g_comp) { - std::stable_sort(__g_first, __g_last, __g_comp); - }); - }); + __par_backend::__parallel_stable_sort( + __first, __last, __comp, [](_RandomAccessIterator __g_first, _RandomAccessIterator __g_last, _Comp __g_comp) { + std::stable_sort(__g_first, __g_last, __g_comp); + }); } else { - std::stable_sort(__first, __last, __comp); + std::__terminate_on_exception([&] { std::stable_sort(__first, __last, __comp); }); } } diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/thread.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/thread.h --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/thread.h +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/thread.h @@ -29,19 +29,20 @@ inline namespace __thread_cpu_backend { template -_LIBCPP_HIDE_FROM_ABI void __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) { +_LIBCPP_HIDE_FROM_ABI void +__parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) noexcept { __f(__first, __last); } template _LIBCPP_HIDE_FROM_ABI _Tp -__parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) { +__parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) noexcept { return __reduce(std::move(__first), std::move(__last), std::move(__init)); } template _LIBCPP_HIDE_FROM_ABI void __parallel_stable_sort( - _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) { + _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) noexcept { __leaf_sort(__first, __last, __comp); } @@ -59,7 +60,7 @@ _RandomAccessIterator2 __last2, _RandomAccessIterator3 __outit, _Compare __comp, - _LeafMerge __leaf_merge) { + _LeafMerge __leaf_merge) noexcept { __leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp); } diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform.h --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform.h +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform.h @@ -45,26 +45,26 @@ if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && __has_random_access_iterator_category<_ForwardIterator>::value && __has_random_access_iterator_category<_ForwardOutIterator>::value) { - std::__terminate_on_exception([&] { - std::__par_backend::__parallel_for( - __first, __last, [__op, __first, __result](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { - return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, __brick_first, __brick_last, __result + (__brick_first - __first), __op); - }); - }); + std::__par_backend::__parallel_for( + __first, __last, [__op, __first, __result](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __result + (__brick_first - __first), __op); + }); return __result + (__last - __first); } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && __has_random_access_iterator_category<_ForwardIterator>::value && __has_random_access_iterator_category<_ForwardOutIterator>::value) { - return std::__simd_walk_2( - __first, - __last - __first, - __result, - [&](__iter_reference<_ForwardIterator> __in_value, __iter_reference<_ForwardOutIterator> __out_value) { - __out_value = __op(__in_value); - }); + return std::__terminate_on_exception([&] { + return std::__simd_walk_2( + __first, + __last - __first, + __result, + [&](__iter_reference<_ForwardIterator> __in_value, __iter_reference<_ForwardOutIterator> __out_value) { + __out_value = __op(__in_value); + }); + }); } else { - return std::transform(__first, __last, __result, __op); + return std::__terminate_on_exception([&] { return std::transform(__first, __last, __result, __op); }); } } @@ -93,35 +93,35 @@ __has_random_access_iterator_category<_ForwardIterator1>::value && __has_random_access_iterator_category<_ForwardIterator2>::value && __has_random_access_iterator_category<_ForwardOutIterator>::value) { - std::__terminate_on_exception([&] { - std::__par_backend::__parallel_for( - __first1, - __last1, - [__op, __first1, __first2, __result](_ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last) { - return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, - __brick_first, - __brick_last, - __first2 + (__brick_first - __first1), - __result + (__brick_first - __first1), - __op); - }); - }); + std::__par_backend::__parallel_for( + __first1, + __last1, + [__op, __first1, __first2, __result](_ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last) { + return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, + __brick_first, + __brick_last, + __first2 + (__brick_first - __first1), + __result + (__brick_first - __first1), + __op); + }); return __result + (__last1 - __first1); } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && __has_random_access_iterator_category<_ForwardIterator1>::value && __has_random_access_iterator_category<_ForwardIterator2>::value && __has_random_access_iterator_category<_ForwardOutIterator>::value) { - return std::__simd_walk_3( - __first1, - __last1 - __first1, - __first2, - __result, - [&](__iter_reference<_ForwardIterator1> __in1, - __iter_reference<_ForwardIterator2> __in2, - __iter_reference<_ForwardOutIterator> __out_value) { __out_value = __op(__in1, __in2); }); + return std::__terminate_on_exception([&] { + return std::__simd_walk_3( + __first1, + __last1 - __first1, + __first2, + __result, + [&](__iter_reference<_ForwardIterator1> __in1, + __iter_reference<_ForwardIterator2> __in2, + __iter_reference<_ForwardOutIterator> __out_value) { __out_value = __op(__in1, __in2); }); + }); } else { - return std::transform(__first1, __last1, __first2, __result, __op); + return std::__terminate_on_exception([&] { return std::transform(__first1, __last1, __first2, __result, __op); }); } } diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h --- a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h @@ -108,42 +108,44 @@ if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && __has_random_access_iterator_category<_ForwardIterator1>::value && __has_random_access_iterator_category<_ForwardIterator2>::value) { + return __par_backend::__parallel_transform_reduce( + __first1, + std::move(__last1), + [__first1, __first2, __transform](_ForwardIterator1 __iter) { + return __transform(*__iter, *(__first2 + (__iter - __first1))); + }, + std::move(__init), + std::move(__reduce), + [__first1, __first2, __reduce, __transform]( + _ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last, _Tp __brick_init) { + return std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, + __brick_first, + std::move(__brick_last), + __first2 + (__brick_first - __first1), + std::move(__brick_init), + std::move(__reduce), + std::move(__transform)); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator1>::value && + __has_random_access_iterator_category<_ForwardIterator2>::value) { + return std::__terminate_on_exception([&]() { + return std::__simd_transform_reduce( + __last1 - __first1, std::move(__init), std::move(__reduce), [&](__iter_diff_t<_ForwardIterator1> __i) { + return __transform(__first1[__i], __first2[__i]); + }); + }); + } else { return std::__terminate_on_exception([&] { - return __par_backend::__parallel_transform_reduce( - __first1, + return std::transform_reduce( + std::move(__first1), std::move(__last1), - [__first1, __first2, __transform](_ForwardIterator1 __iter) { - return __transform(*__iter, *(__first2 + (__iter - __first1))); - }, + std::move(__first2), std::move(__init), std::move(__reduce), - [__first1, __first2, __reduce, __transform]( - _ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last, _Tp __brick_init) { - return std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, - __brick_first, - std::move(__brick_last), - __first2 + (__brick_first - __first1), - std::move(__brick_init), - std::move(__reduce), - std::move(__transform)); - }); + std::move(__transform)); }); - } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category<_ForwardIterator1>::value && - __has_random_access_iterator_category<_ForwardIterator2>::value) { - return std::__simd_transform_reduce( - __last1 - __first1, std::move(__init), std::move(__reduce), [&](__iter_diff_t<_ForwardIterator1> __i) { - return __transform(__first1[__i], __first2[__i]); - }); - } else { - return std::transform_reduce( - std::move(__first1), - std::move(__last1), - std::move(__first2), - std::move(__init), - std::move(__reduce), - std::move(__transform)); } } @@ -157,33 +159,35 @@ _UnaryOperation __transform) { if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && __has_random_access_iterator_category<_ForwardIterator>::value) { + return __par_backend::__parallel_transform_reduce( + std::move(__first), + std::move(__last), + [__transform](_ForwardIterator __iter) { return __transform(*__iter); }, + std::move(__init), + std::move(__reduce), + [=](_ForwardIterator __brick_first, _ForwardIterator __brick_last, _Tp __brick_init) { + return std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, + std::move(__brick_first), + std::move(__brick_last), + std::move(__brick_init), + std::move(__reduce), + std::move(__transform)); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { return std::__terminate_on_exception([&] { - return __par_backend::__parallel_transform_reduce( - std::move(__first), - std::move(__last), - [__transform](_ForwardIterator __iter) { return __transform(*__iter); }, + return std::__simd_transform_reduce( + __last - __first, std::move(__init), std::move(__reduce), - [=](_ForwardIterator __brick_first, _ForwardIterator __brick_last, _Tp __brick_init) { - return std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, - std::move(__brick_first), - std::move(__brick_last), - std::move(__brick_init), - std::move(__reduce), - std::move(__transform)); - }); + [=, &__transform](__iter_diff_t<_ForwardIterator> __i) { return __transform(__first[__i]); }); }); - } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category<_ForwardIterator>::value) { - return std::__simd_transform_reduce( - __last - __first, - std::move(__init), - std::move(__reduce), - [=, &__transform](__iter_diff_t<_ForwardIterator> __i) { return __transform(__first[__i]); }); } else { - return std::transform_reduce( - std::move(__first), std::move(__last), std::move(__init), std::move(__reduce), std::move(__transform)); + return std::__terminate_on_exception([&] { + return std::transform_reduce( + std::move(__first), std::move(__last), std::move(__init), std::move(__reduce), std::move(__transform)); + }); } } diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill.pass.cpp --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill.pass.cpp @@ -24,6 +24,8 @@ #include "test_execution_policies.h" #include "test_iterators.h" +#include "check_assertion.h" + EXECUTION_POLICY_SFINAE_TEST(fill); static_assert(sfinae_test_fill); @@ -61,24 +63,8 @@ } }; -#ifndef TEST_HAS_NO_EXCEPTIONS -struct ThrowOnCopy { - ThrowOnCopy& operator=(const ThrowOnCopy&) { throw int{}; } -}; -#endif - int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - ThrowOnCopy a[2]; - try { - (void)std::fill(std::execution::par, std::begin(a), std::end(a), ThrowOnCopy{}); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill.terminate.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill.terminate.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill.terminate.pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// UNSUPPORTED: libcpp-has-no-incomplete-pstl + +// check that std::fill(ExecutionPolicy) terminates properly + +#include "terminating_test_helper.h" +#include "test_execution_policies.h" + +#include + +#ifndef TEST_HAS_NO_EXCEPTIONS +struct ThrowOnCopy { + ThrowOnCopy& operator=(const ThrowOnCopy&) { throw int{}; } +}; +#endif + +TEST_TERMINATIONS([] { + ThrowOnCopy a[2]{}; + + test_execution_policies([&](auto&& policy) { + EXPECT_STD_TERMINATE([&] { (void)std::fill(policy, std::begin(a), std::end(a), ThrowOnCopy{}); }); + EXPECT_STD_TERMINATE([&] { (void)std::fill_n(policy, std::begin(a), std::size(a), ThrowOnCopy{}); }); + }); +}); diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill_n.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill_n.pass.cpp --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill_n.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill_n.pass.cpp @@ -61,24 +61,8 @@ } }; -#ifndef TEST_HAS_NO_EXCEPTIONS -struct ThrowOnCopy { - ThrowOnCopy& operator=(const ThrowOnCopy&) { throw int{}; } -}; -#endif - int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - ThrowOnCopy a[2]; - try { - (void)std::fill_n(std::execution::par, std::begin(a), std::size(a), ThrowOnCopy{}); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace.pass.cpp --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace.pass.cpp @@ -73,24 +73,8 @@ } }; -struct ThrowOnCompare {}; - -#ifndef TEST_HAS_NO_EXCEPTIONS -bool operator==(ThrowOnCompare, ThrowOnCompare) { throw int{}; } -#endif - int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - ThrowOnCompare a[2]; - try { - (void)std::replace(std::execution::par, std::begin(a), std::end(a), ThrowOnCompare{}, ThrowOnCompare{}); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace.terminate.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace.terminate.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace.terminate.pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 +// UNSUPPORTED: libcpp-has-no-incomplete-pstl + +#include "terminating_test_helper.h" +#include "test_execution_policies.h" + +#include + +struct ThrowOnCompare {}; + +#ifndef TEST_HAS_NO_EXCEPTIONS +bool operator==(ThrowOnCompare, ThrowOnCompare) { throw int{}; } +#endif + +TEST_TERMINATIONS([] { + ThrowOnCompare a[2]{}; + + test_execution_policies([&](auto&& policy) { + EXPECT_STD_TERMINATE([&] { + (void)std::replace(policy, std::begin(a), std::end(a), ThrowOnCompare{}, ThrowOnCompare{}); + }); + EXPECT_STD_TERMINATE([&] { + (void)std::replace_if( + policy, std::begin(a), std::end(a), [](ThrowOnCompare&) -> bool { throw int{}; }, ThrowOnCompare{}); + }); + EXPECT_STD_TERMINATE([&] { + (void)std::replace_copy(policy, std::begin(a), std::end(a), std::begin(a), ThrowOnCompare{}, ThrowOnCompare{}); + }); + EXPECT_STD_TERMINATE([&] { + (void)std::replace_copy_if( + policy, + std::begin(a), + std::end(a), + std::begin(a), + [](ThrowOnCompare& i) { return i == i; }, + ThrowOnCompare{}); + }); + }); +}); diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy.pass.cpp --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy.pass.cpp @@ -82,25 +82,8 @@ } }; -struct ThrowOnCompare {}; - -#ifndef TEST_HAS_NO_EXCEPTIONS -bool operator==(ThrowOnCompare, ThrowOnCompare) { throw int{}; } -#endif - int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - ThrowOnCompare a[2]; - try { - (void)std::replace_copy( - std::execution::par, std::begin(a), std::end(a), std::begin(a), ThrowOnCompare{}, ThrowOnCompare{}); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy_if.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy_if.pass.cpp --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy_if.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy_if.pass.cpp @@ -95,30 +95,8 @@ } }; -struct ThrowOnCompare {}; - -#ifndef TEST_HAS_NO_EXCEPTIONS -bool operator==(ThrowOnCompare, ThrowOnCompare) { throw int{}; } -#endif - int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - ThrowOnCompare a[2]; - try { - (void)std::replace_copy_if( - std::execution::par, - std::begin(a), - std::end(a), - std::begin(a), - [](ThrowOnCompare& i) { return i == i; }, - ThrowOnCompare{}); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_if.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_if.pass.cpp --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_if.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_if.pass.cpp @@ -78,25 +78,8 @@ } }; -struct ThrowOnCompare {}; - -#ifndef TEST_HAS_NO_EXCEPTIONS -bool operator==(ThrowOnCompare, ThrowOnCompare) { throw int{}; } -#endif - int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - ThrowOnCompare a[2]; - try { - (void)std::replace_if( - std::execution::par, std::begin(a), std::end(a), [](ThrowOnCompare&) { return false; }, ThrowOnCompare{}); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/pstl.transform.terminate.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/pstl.transform.terminate.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/pstl.transform.terminate.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 +// UNSUPPORTED: libcpp-has-no-incomplete-pstl + +#include "terminating_test_helper.h" +#include "test_execution_policies.h" + +#include + +TEST_TERMINATIONS([] { + int a[2]{}; + int b[2]{}; + int c[2]{}; + + test_execution_policies([&](auto&& policy) { + EXPECT_STD_TERMINATE([&] { + (void)std::transform( + policy, std::begin(a), std::end(a), std::begin(b), std::begin(c), [](auto v, auto) -> decltype(v) { + throw int{}; + }); + }); + EXPECT_STD_TERMINATE([&] { + (void)std::transform(policy, std::begin(a), std::end(a), std::begin(b), [](auto v) -> decltype(v) { + throw int{}; + }); + }); + }); +}); diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.all_of/pstl.all_of.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.all_of/pstl.all_of.pass.cpp --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.all_of/pstl.all_of.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.all_of/pstl.all_of.pass.cpp @@ -69,15 +69,5 @@ int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - int a[] = {1, 2}; - try { - (void)std::all_of(std::execution::par, std::begin(a), std::end(a), [](int i) -> bool { throw i; }); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.all_of/pstl.all_of.terminate.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.all_of/pstl.all_of.terminate.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.all_of/pstl.all_of.terminate.pass.cpp @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// UNSUPPORTED: libcpp-has-no-incomplete-pstl + +#include "terminating_test_helper.h" + +#include + +TEST_TERMINATIONS([] { + int a[] = {1, 2}; + + EXPECT_STD_TERMINATE([&] { + (void)std::all_of(std::execution::par, std::begin(a), std::end(a), [](int i) -> bool { throw i; }); + }); +}); diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.any_of/pstl.any_of.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.any_of/pstl.any_of.pass.cpp --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.any_of/pstl.any_of.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.any_of/pstl.any_of.pass.cpp @@ -63,15 +63,5 @@ int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - int a[] = {1, 2}; - try { - (void)std::any_of(std::execution::par, std::begin(a), std::end(a), [](int i) -> bool { throw i; }); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.any_of/pstl.any_of.terminate.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.any_of/pstl.any_of.terminate.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.any_of/pstl.any_of.terminate.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// UNSUPPORTED: libcpp-has-no-incomplete-pstl + +#include + +#include "terminating_test_helper.h" +#include "test_execution_policies.h" + +TEST_TERMINATIONS([] { + test_execution_policies([](auto&& policy) { + EXPECT_STD_TERMINATE([&] { + int a[] = {1, 2}; + (void)std::any_of(policy, std::begin(a), std::end(a), [](int i) -> bool { throw i; }); + }); + }); +}); diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find.pass.cpp --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find.pass.cpp @@ -61,24 +61,8 @@ } }; -struct ThrowOnCompare {}; - -#ifndef TEST_HAS_NO_EXCEPTIONS -bool operator==(ThrowOnCompare, ThrowOnCompare) { throw int{}; } -#endif - int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - ThrowOnCompare a[2]; - try { - (void)std::find(std::execution::par, std::begin(a), std::end(a), ThrowOnCompare{}); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find.terminate.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find.terminate.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find.terminate.pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// UNSUPPORTED: libcpp-has-no-incomplete-pstl + +#include + +#include "test_execution_policies.h" +#include "terminating_test_helper.h" + +struct ThrowOnCompare {}; + +#ifndef TEST_HAS_NO_EXCEPTIONS +bool operator==(ThrowOnCompare, ThrowOnCompare) { throw int{}; } +#endif + +TEST_TERMINATIONS([] { + test_execution_policies([](auto&& policy) { + EXPECT_STD_TERMINATE([&] { + int a[] = {1, 2}; + (void)std::find_if(policy, std::begin(a), std::end(a), [](int) -> bool { throw int{}; }); + }); + + EXPECT_STD_TERMINATE([&] { + ThrowOnCompare a[2] = {}; + (void)std::find(policy, std::begin(a), std::end(a), ThrowOnCompare{}); + }); + + EXPECT_STD_TERMINATE([&] { + int a[] = {1, 2}; + (void)std::find_if_not(policy, std::begin(a), std::end(a), [](int) -> bool { throw int{}; }); + }); + }); +}); diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find_if.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find_if.pass.cpp --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find_if.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find_if.pass.cpp @@ -70,15 +70,5 @@ int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - int a[] = {1, 2}; - try { - (void)std::find_if(std::execution::par, std::begin(a), std::end(a), [](int) -> bool { throw int{}; }); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find_if_not.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find_if_not.pass.cpp --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find_if_not.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/pstl.find_if_not.pass.cpp @@ -71,15 +71,5 @@ int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - int a[] = {1, 2}; - try { - (void)std::find_if_not(std::execution::par, std::begin(a), std::end(a), [](int) -> bool { throw int{}; }); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each.pass.cpp --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each.pass.cpp @@ -51,15 +51,5 @@ int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - int a[] = {1, 2}; - try { - std::for_each(std::execution::par, std::begin(a), std::end(a), [](int) { throw int{}; }); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each.terminate.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each.terminate.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each.terminate.pass.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// UNSUPPORTED: libcpp-has-no-incomplete-pstl + +#include + +#include "test_execution_policies.h" +#include "terminating_test_helper.h" + +TEST_TERMINATIONS([] { + test_execution_policies([](auto&& policy) { + int a[] = {1, 2}; + EXPECT_STD_TERMINATE([&] { std::for_each(policy, std::begin(a), std::end(a), [](int) { throw int{}; }); }); + EXPECT_STD_TERMINATE([&] { std::for_each_n(policy, std::data(a), std::size(a), [](int) { throw int{}; }); }); + }); +}); diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each_n.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each_n.pass.cpp --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each_n.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/pstl.for_each_n.pass.cpp @@ -50,15 +50,5 @@ int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - int a[] = {1, 2}; - try { - std::for_each_n(std::execution::par, std::data(a), std::size(a), [](int) { throw int{}; }); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.none_of/pstl.none_of.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.none_of/pstl.none_of.pass.cpp --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.none_of/pstl.none_of.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.none_of/pstl.none_of.pass.cpp @@ -63,15 +63,5 @@ int main(int, char**) { types::for_each(types::forward_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - int a[] = {1, 2}; - try { - (void)std::none_of(std::execution::par, std::begin(a), std::end(a), [](int i) -> bool { throw i; }); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.none_of/pstl.none_of.terminate.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.none_of/pstl.none_of.terminate.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.none_of/pstl.none_of.terminate.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// UNSUPPORTED: libcpp-has-no-incomplete-pstl + +#include + +#include "terminating_test_helper.h" +#include "test_execution_policies.h" + +TEST_TERMINATIONS([] { + test_execution_policies([](auto&& policy) { + EXPECT_STD_TERMINATE([&] { + int a[] = {1, 2}; + (void)std::none_of(policy, std::begin(a), std::end(a), [](int i) -> bool { throw i; }); + }); + }); +}); diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/pstl.stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/pstl.stable_sort.pass.cpp --- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/pstl.stable_sort.pass.cpp +++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/pstl.stable_sort.pass.cpp @@ -129,15 +129,5 @@ int main(int, char**) { types::for_each(types::random_access_iterator_list{}, TestIteratorWithPolicies{}); -#ifndef TEST_HAS_NO_EXCEPTIONS - std::set_terminate(terminate_successful); - int a[] = {1, 2}; - try { - std::stable_sort(std::execution::par, std::begin(a), std::end(a), [](int, int) -> bool { throw int{}; }); - } catch (int) { - assert(false); - } -#endif - return 0; } diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/pstl.stable_sort.terminate.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/pstl.stable_sort.terminate.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/pstl.stable_sort.terminate.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// UNSUPPORTED: libcpp-has-no-incomplete-pstl + +#include + +#include "terminating_test_helper.h" +#include "test_execution_policies.h" + +TEST_TERMINATIONS([] { + test_execution_policies([](auto&& policy) { + EXPECT_STD_TERMINATE([&] { + int a[] = {1, 2}; + std::stable_sort(policy, std::begin(a), std::end(a), [](int, int) -> bool { throw int{}; }); + }); + }); +}); diff --git a/libcxx/test/support/terminating_test_helper.h b/libcxx/test/support/terminating_test_helper.h --- a/libcxx/test/support/terminating_test_helper.h +++ b/libcxx/test/support/terminating_test_helper.h @@ -9,6 +9,7 @@ #ifndef TEST_TERMINATING_TEST_HELPER_H #define TEST_TERMINATING_TEST_HELPER_H +#include #include #include #include @@ -34,6 +35,7 @@ enum class result : int { success = 0, std_terminate, + exception, nondetermenistic_test_count, #ifdef _LIBCPP_VERSION libcpp_assert, @@ -46,6 +48,8 @@ return "unexpected success"; case result::std_terminate: return "std::terminate"; + case result::exception: + return "exception"; case result::nondetermenistic_test_count: return "nondeterministic test count"; #ifdef _LIBCPP_VERSION @@ -213,11 +217,24 @@ return 0; \ } +#ifdef TEST_HAS_NO_EXCEPTIONS +# define TERMINATING_TEST_HELPER_CATCH_EXCEPTION(...) __VA_ARGS__ +#else +# define TERMINATING_TEST_HELPER_CATCH_EXCEPTION(...) \ + do { \ + try { \ + __VA_ARGS__; \ + } catch (...) { \ + ::terminate::exit(::terminate::result::exception); \ + } \ + } while (false) +#endif + #define EXPECT_RESULT(result_check_function, ...) \ do { \ ::terminate::test_infos.push_back({TEST_STRINGIZE(__VA_ARGS__), result_check_function}); \ if (::terminate::current_test++ == ::terminate::test_to_run) { \ - __VA_ARGS__(); \ + TERMINATING_TEST_HELPER_CATCH_EXCEPTION(__VA_ARGS__()); \ ::terminate::exit(::terminate::result::success); \ } \ } while (false) diff --git a/libcxx/test/support/test_execution_policies.h b/libcxx/test/support/test_execution_policies.h --- a/libcxx/test/support/test_execution_policies.h +++ b/libcxx/test/support/test_execution_policies.h @@ -58,8 +58,4 @@ } }; -#ifndef TEST_HAS_NO_EXCEPTIONS -[[noreturn]] inline void terminate_successful() { std::exit(0); } -#endif - #endif // TEST_SUPPORT_TEST_EXECUTION_POLICIES