48 changes: 48 additions & 0 deletions libcxx/include/__type_traits/is_execution_policy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___TYPE_TRAITS_IS_EXECUTION_POLICY_H
#define _LIBCPP___TYPE_TRAITS_IS_EXECUTION_POLICY_H

#include <__config>
#include <__type_traits/remove_cvref.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

#if _LIBCPP_STD_VER >= 17

_LIBCPP_BEGIN_NAMESPACE_STD

template <class>
inline constexpr bool is_execution_policy_v = false;

template <class>
inline constexpr bool __is_unsequenced_execution_policy_impl = false;

template <class _Tp>
inline constexpr bool __is_unsequenced_execution_policy_v =
__is_unsequenced_execution_policy_impl<__remove_cvref_t<_Tp>>;

template <class>
inline constexpr bool __is_parallel_execution_policy_impl = false;

template <class _Tp>
inline constexpr bool __is_parallel_execution_policy_v = __is_parallel_execution_policy_impl<__remove_cvref_t<_Tp>>;

// Removes the "parallel" part of an execution policy.
// For example, turns par_unseq into unseq, and par into seq.
template <class _ExecutionPolicy>
const auto& __remove_parallel_policy(_ExecutionPolicy&&);

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP_STD_VER >= 17

#endif // _LIBCPP___TYPE_TRAITS_IS_EXECUTION_POLICY_H
47 changes: 47 additions & 0 deletions libcxx/include/__utility/terminate_on_exception.h
Original file line number Diff line number Diff line change
@@ -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
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___UTILITY_TERMINATE_ON_EXCEPTION_H
#define _LIBCPP___UTILITY_TERMINATE_ON_EXCEPTION_H

#include <__config>
#include <exception>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

#if _LIBCPP_STD_VER >= 17

_LIBCPP_BEGIN_NAMESPACE_STD

# ifndef _LIBCPP_HAS_NO_EXCEPTIONS

template <class _Func>
_LIBCPP_HIDE_FROM_ABI auto __terminate_on_exception(_Func __func) {
try {
return __func();
} catch (...) {
std::terminate();
}
}

# else // _LIBCPP_HAS_NO_EXCEPTIONS

template <class _Func>
_LIBCPP_HIDE_FROM_ABI auto __terminate_on_exception(_Func __func) {
return __func();
}

# endif // _LIBCPP_HAS_NO_EXCEPTIONS

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP_STD_VER >= 17

#endif // _LIBCPP___UTILITY_TERMINATE_ON_EXCEPTION_H
4 changes: 4 additions & 0 deletions libcxx/include/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -1908,6 +1908,10 @@ template <class BidirectionalIterator, class Compare>
#include <__algorithm/unwrap_iter.h>
#include <__algorithm/upper_bound.h>

#ifdef _LIBCPP_HAS_PARALLEL_ALGORITHMS
# include <__algorithm/pstl_any_all_none_of.h>
#endif

// standard-mandated includes

// [algorithm.syn]
Expand Down
130 changes: 130 additions & 0 deletions libcxx/include/execution
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,142 @@
#ifndef _LIBCPP_EXECUTION
#define _LIBCPP_EXECUTION

/*
namespace std::execution {
struct sequenced_policy;
struct parallel_policy;
struct parallel_unsequenced_policy;
struct unsequenced_policy; // since C++20
inline constexpr sequenced_policy seq = implementation-defined;
inline constexpr parallel_policy par = implementation-defined;
inline constexpr parallel_unsequenced_policy par_unseq = implementation-defined;
inline constexpr unsequenced_policy unseq = implementation-defined; // since C++20
}
namespace std {
template <class T>
struct is_execution_policy;
template <class T>
inline constexpr bool is_execution_policy_v;
}
*/

#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
#include <__type_traits/is_execution_policy.h>
#include <__type_traits/is_same.h>
#include <__type_traits/remove_cvref.h>
#include <version>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

#if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17

_LIBCPP_BEGIN_NAMESPACE_STD

namespace execution {
struct __disable_user_instantiations_tag {
explicit __disable_user_instantiations_tag() = default;
};

struct sequenced_policy {
constexpr explicit sequenced_policy(__disable_user_instantiations_tag) {}
sequenced_policy(const sequenced_policy&) = delete;
sequenced_policy& operator=(const sequenced_policy&) = delete;
};

inline constexpr sequenced_policy seq{__disable_user_instantiations_tag{}};

struct parallel_policy {
constexpr explicit parallel_policy(__disable_user_instantiations_tag) {}
parallel_policy(const parallel_policy&) = delete;
parallel_policy& operator=(const parallel_policy&) = delete;
};

inline constexpr parallel_policy par{__disable_user_instantiations_tag{}};

struct parallel_unsequenced_policy {
constexpr explicit parallel_unsequenced_policy(__disable_user_instantiations_tag) {}
parallel_unsequenced_policy(const parallel_unsequenced_policy&) = delete;
parallel_unsequenced_policy& operator=(const parallel_unsequenced_policy&) = delete;
};

inline constexpr parallel_unsequenced_policy par_unseq{__disable_user_instantiations_tag{}};

struct __unsequenced_policy {
constexpr explicit __unsequenced_policy(__disable_user_instantiations_tag) {}
__unsequenced_policy(const __unsequenced_policy&) = delete;
__unsequenced_policy& operator=(const __unsequenced_policy&) = delete;
};

constexpr __unsequenced_policy __unseq{__disable_user_instantiations_tag{}};

# if _LIBCPP_STD_VER >= 20

struct unsequenced_policy {
constexpr explicit unsequenced_policy(__disable_user_instantiations_tag) {}
unsequenced_policy(const unsequenced_policy&) = delete;
unsequenced_policy& operator=(const unsequenced_policy&) = delete;
};

inline constexpr unsequenced_policy unseq{__disable_user_instantiations_tag{}};

# endif // _LIBCPP_STD_VER >= 20

} // namespace execution

template <>
inline constexpr bool is_execution_policy_v<execution::sequenced_policy> = true;

template <>
inline constexpr bool is_execution_policy_v<execution::parallel_policy> = true;

template <>
inline constexpr bool is_execution_policy_v<execution::parallel_unsequenced_policy> = true;

template <>
inline constexpr bool is_execution_policy_v<execution::__unsequenced_policy> = true;

template <>
inline constexpr bool __is_parallel_execution_policy_impl<execution::parallel_policy> = true;

template <>
inline constexpr bool __is_parallel_execution_policy_impl<execution::parallel_unsequenced_policy> = true;

template <>
inline constexpr bool __is_unsequenced_execution_policy_impl<execution::__unsequenced_policy> = true;

template <>
inline constexpr bool __is_unsequenced_execution_policy_impl<execution::parallel_unsequenced_policy> = true;

# if _LIBCPP_STD_VER >= 20
template <>
inline constexpr bool is_execution_policy_v<execution::unsequenced_policy> = true;

template <>
inline constexpr bool __is_unsequenced_execution_policy_impl<execution::unsequenced_policy> = true;

# endif

template <class _Tp>
struct is_execution_policy : bool_constant<is_execution_policy_v<_Tp>> {};

template <class _ExecutionPolicy>
const auto& __remove_parallel_policy(_ExecutionPolicy&&) {
using _ExecPol = __remove_cvref_t<_ExecutionPolicy>;
if constexpr (is_same_v<_ExecPol, execution::parallel_policy>) {
return execution::seq;
} else if constexpr (is_same_v<_ExecPol, execution::parallel_unsequenced_policy>) {
return execution::__unseq;
}
}

_LIBCPP_END_NAMESPACE_STD

#endif // defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17

#endif // _LIBCPP_EXECUTION
42 changes: 22 additions & 20 deletions libcxx/include/module.modulemap.in
Original file line number Diff line number Diff line change
Expand Up @@ -1555,6 +1555,7 @@ module std [system] {
private header "__type_traits/is_equality_comparable.h"
export integral_constant
}
module is_execution_policy { private header "__type_traits/is_execution_policy.h" }
module is_final { private header "__type_traits/is_final.h" }
module is_floating_point { private header "__type_traits/is_floating_point.h" }
module is_function { private header "__type_traits/is_function.h" }
Expand Down Expand Up @@ -1672,29 +1673,30 @@ module std [system] {
export *

module __utility {
module as_const { private header "__utility/as_const.h" }
module auto_cast {
module as_const { private header "__utility/as_const.h" }
module auto_cast {
private header "__utility/auto_cast.h"
export type_traits.decay
}
module cmp { private header "__utility/cmp.h" }
module convert_to_integral { private header "__utility/convert_to_integral.h" }
module declval { private header "__utility/declval.h" }
module exception_guard { private header "__utility/exception_guard.h" }
module exchange { private header "__utility/exchange.h" }
module forward { private header "__utility/forward.h" }
module forward_like { private header "__utility/forward_like.h" }
module in_place { private header "__utility/in_place.h" }
module integer_sequence { private header "__utility/integer_sequence.h" }
module move { private header "__utility/move.h" }
module pair { private header "__utility/pair.h" }
module pair_fwd { private header "__fwd/pair.h" }
module piecewise_construct { private header "__utility/piecewise_construct.h" }
module priority_tag { private header "__utility/priority_tag.h" }
module rel_ops { private header "__utility/rel_ops.h" }
module swap { private header "__utility/swap.h" }
module to_underlying { private header "__utility/to_underlying.h" }
module unreachable { private header "__utility/unreachable.h" }
module cmp { private header "__utility/cmp.h" }
module convert_to_integral { private header "__utility/convert_to_integral.h" }
module declval { private header "__utility/declval.h" }
module exception_guard { private header "__utility/exception_guard.h" }
module exchange { private header "__utility/exchange.h" }
module forward { private header "__utility/forward.h" }
module forward_like { private header "__utility/forward_like.h" }
module in_place { private header "__utility/in_place.h" }
module integer_sequence { private header "__utility/integer_sequence.h" }
module move { private header "__utility/move.h" }
module pair { private header "__utility/pair.h" }
module pair_fwd { private header "__fwd/pair.h" }
module piecewise_construct { private header "__utility/piecewise_construct.h" }
module priority_tag { private header "__utility/priority_tag.h" }
module rel_ops { private header "__utility/rel_ops.h" }
module swap { private header "__utility/swap.h" }
module terminate_on_exception { private header "__utility/terminate_on_exception.h" }
module to_underlying { private header "__utility/to_underlying.h" }
module unreachable { private header "__utility/unreachable.h" }
}
}
module valarray {
Expand Down
2 changes: 1 addition & 1 deletion libcxx/test/libcxx/clang_tidy.sh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

// REQUIRES: has-clang-tidy

// FIXME: This should pass with the PSTL enables
// FIXME: This should pass with the PSTL enabled
// XFAIL: with-pstl

// The GCC compiler flags are not always compatible with clang-tidy.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// Check that PSTL algorithms aren't marked [[nodiscard]] when
// _LIBCPP_DISBALE_NODISCARD_EXT is defined

// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_NODISCARD_EXT

// REQUIRES: with-pstl

// UNSUPPORTED: c++03, c++11, c++14

#include <algorithm>
#include <execution>

void test() {
int a[] = {1};
auto pred = [](auto) { return false; };
std::all_of(std::execution::par, std::begin(a), std::end(a), pred);
std::any_of(std::execution::par, std::begin(a), std::end(a), pred);
std::none_of(std::execution::par, std::begin(a), std::end(a), pred);
}
Original file line number Diff line number Diff line change
@@ -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
//
//===----------------------------------------------------------------------===//

// Check that PSTL algorithms are marked [[nodiscard]] as a conforming extension

// REQUIRES: with-pstl

// UNSUPPORTED: c++03, c++11, c++14

#include <algorithm>
#include <execution>

void test() {
int a[] = {1};
auto pred = [](auto) { return false; };
std::all_of(std::execution::par, std::begin(a), std::end(a), pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
std::any_of(std::execution::par, std::begin(a), std::end(a), pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
std::none_of(std::execution::par, std::begin(a), std::end(a), pred); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
}
3 changes: 3 additions & 0 deletions libcxx/test/libcxx/nasty_macros.compile.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
// Test that headers are not tripped up by the surrounding code defining various
// alphabetic macros.

// FIXME: This should pass with the PSTL enabled
// XFAIL: with-pstl

// Prevent <ext/hash_map> from generating deprecated warnings for this test.
#if defined(__DEPRECATED)
# undef __DEPRECATED
Expand Down
2 changes: 2 additions & 0 deletions libcxx/test/libcxx/private_headers.verify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,7 @@ END-SCRIPT
#include <__type_traits/is_empty.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/is_empty.h'}}
#include <__type_traits/is_enum.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/is_enum.h'}}
#include <__type_traits/is_equality_comparable.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/is_equality_comparable.h'}}
#include <__type_traits/is_execution_policy.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/is_execution_policy.h'}}
#include <__type_traits/is_final.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/is_final.h'}}
#include <__type_traits/is_floating_point.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/is_floating_point.h'}}
#include <__type_traits/is_function.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/is_function.h'}}
Expand Down Expand Up @@ -782,6 +783,7 @@ END-SCRIPT
#include <__utility/priority_tag.h> // expected-error@*:* {{use of private header from outside its module: '__utility/priority_tag.h'}}
#include <__utility/rel_ops.h> // expected-error@*:* {{use of private header from outside its module: '__utility/rel_ops.h'}}
#include <__utility/swap.h> // expected-error@*:* {{use of private header from outside its module: '__utility/swap.h'}}
#include <__utility/terminate_on_exception.h> // expected-error@*:* {{use of private header from outside its module: '__utility/terminate_on_exception.h'}}
#include <__utility/to_underlying.h> // expected-error@*:* {{use of private header from outside its module: '__utility/to_underlying.h'}}
#include <__utility/unreachable.h> // expected-error@*:* {{use of private header from outside its module: '__utility/unreachable.h'}}
#include <__variant/monostate.h> // expected-error@*:* {{use of private header from outside its module: '__variant/monostate.h'}}
Expand Down
3 changes: 3 additions & 0 deletions libcxx/test/libcxx/transitive_includes.sh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
// this test instead.
// UNSUPPORTED: transitive-includes-disabled

// FIXME: This should pass with the PSTL enabled
// XFAIL: with-pstl

// Prevent <ext/hash_map> from generating deprecated warnings for this test.
#if defined(__DEPRECATED)
# undef __DEPRECATED
Expand Down
1 change: 1 addition & 0 deletions libcxx/test/libcxx/transitive_includes/cxx03.csv
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ exception cstddef
exception cstdlib
exception type_traits
exception version
execution cstddef
execution version
expected cstddef
expected initializer_list
Expand Down
1 change: 1 addition & 0 deletions libcxx/test/libcxx/transitive_includes/cxx11.csv
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ exception cstddef
exception cstdlib
exception type_traits
exception version
execution cstddef
execution version
expected cstddef
expected initializer_list
Expand Down
1 change: 1 addition & 0 deletions libcxx/test/libcxx/transitive_includes/cxx14.csv
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ exception cstddef
exception cstdlib
exception type_traits
exception version
execution cstddef
execution version
expected cstddef
expected initializer_list
Expand Down
1 change: 1 addition & 0 deletions libcxx/test/libcxx/transitive_includes/cxx17.csv
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ exception cstddef
exception cstdlib
exception type_traits
exception version
execution cstddef
execution version
expected cstddef
expected initializer_list
Expand Down
1 change: 1 addition & 0 deletions libcxx/test/libcxx/transitive_includes/cxx20.csv
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ exception cstddef
exception cstdlib
exception type_traits
exception version
execution cstddef
execution version
expected cstddef
expected initializer_list
Expand Down
1 change: 1 addition & 0 deletions libcxx/test/libcxx/transitive_includes/cxx2b.csv
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ deque version
exception cstddef
exception cstdlib
exception version
execution cstddef
execution version
expected cstddef
expected initializer_list
Expand Down
44 changes: 44 additions & 0 deletions libcxx/test/libcxx/utilities/expol/policies.compile.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// Make sure we don't allow copying the execution policies in any way to avoid users relying on it.

// UNSUPPORTED: c++03, c++11, c++14

// REQUIRES: with-pstl

#include <execution>
#include <type_traits>

#include "test_macros.h"

static_assert(!std::is_default_constructible_v<std::execution::sequenced_policy>);
static_assert(!std::is_copy_constructible_v<std::execution::sequenced_policy>);
static_assert(!std::is_move_constructible_v<std::execution::sequenced_policy>);
static_assert(!std::is_copy_assignable_v<std::execution::sequenced_policy>);
static_assert(!std::is_move_assignable_v<std::execution::sequenced_policy>);

static_assert(!std::is_default_constructible_v<std::execution::parallel_policy>);
static_assert(!std::is_copy_constructible_v<std::execution::parallel_policy>);
static_assert(!std::is_move_constructible_v<std::execution::parallel_policy>);
static_assert(!std::is_copy_assignable_v<std::execution::parallel_policy>);
static_assert(!std::is_move_assignable_v<std::execution::parallel_policy>);

static_assert(!std::is_default_constructible_v<std::execution::parallel_unsequenced_policy>);
static_assert(!std::is_copy_constructible_v<std::execution::parallel_unsequenced_policy>);
static_assert(!std::is_move_constructible_v<std::execution::parallel_unsequenced_policy>);
static_assert(!std::is_copy_assignable_v<std::execution::parallel_unsequenced_policy>);
static_assert(!std::is_move_assignable_v<std::execution::parallel_unsequenced_policy>);

#if TEST_STD_VER >= 20
static_assert(!std::is_default_constructible_v<std::execution::unsequenced_policy>);
static_assert(!std::is_copy_constructible_v<std::execution::unsequenced_policy>);
static_assert(!std::is_move_constructible_v<std::execution::unsequenced_policy>);
static_assert(!std::is_copy_assignable_v<std::execution::unsequenced_policy>);
static_assert(!std::is_move_assignable_v<std::execution::unsequenced_policy>);
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//===----------------------------------------------------------------------===//
//
// 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

// REQUIRES: with-pstl

// <algorithm>

// template<class ExecutionPolicy, class ForwardIterator, class Predicate>
// bool any_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last,
// Predicate pred);

#include <algorithm>
#include <cassert>
#include <vector>

#include "test_macros.h"
#include "test_execution_policies.h"
#include "test_iterators.h"

EXECUTION_POLICY_SFINAE_TEST(all_of);

static_assert(sfinae_test_all_of<int, int*, int*, bool (*)(int)>);
static_assert(!sfinae_test_all_of<std::execution::parallel_policy, int*, int*, bool (*)(int)>);

template <class Iter>
struct Test {
template <class Policy>
void operator()(Policy&& policy) {
int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
// simple test
assert(std::all_of(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i < 9; }));
assert(!std::all_of(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i < 8; }));

// check that an empty range works
assert(std::all_of(policy, Iter(std::begin(a)), Iter(std::begin(a)), [](int) { return true; }));

// check that a single-element range works
assert(std::all_of(policy, Iter(a), Iter(a + 1), [](int i) { return i < 2; }));

// check that a two-element range works
assert(std::all_of(policy, Iter(a), Iter(a + 2), [](int i) { return i < 3; }));

// check that false is returned if no element satisfies the condition
assert(!std::all_of(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 9; }));

// check that false is returned if only one elements satisfies the condition
assert(!std::all_of(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 1; }));

// check that a one-element range works
assert(std::all_of(policy, Iter(std::begin(a)), Iter(std::begin(a) + 1), [](int i) { return i == 1; }));

// check that a two-element range works
assert(std::all_of(policy, Iter(std::begin(a)), Iter(std::begin(a) + 2), [](int i) { return i < 3; }));

// check that a large number of elements works
std::vector<int> vec(100);
std::fill(vec.begin(), vec.end(), 3);
assert(std::all_of(Iter(vec.data()), Iter(vec.data() + vec.size()), [](int i) { return i == 3; }));
}
};

int main(int, char**) {
types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<Test>{});

#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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//===----------------------------------------------------------------------===//
//
// 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

// REQUIRES: with-pstl

// <algorithm>

// template<class ExecutionPolicy, class ForwardIterator, class Predicate>
// bool any_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last,
// Predicate pred);

#include <algorithm>
#include <cassert>
#include <vector>

#include "test_macros.h"
#include "test_execution_policies.h"
#include "test_iterators.h"

EXECUTION_POLICY_SFINAE_TEST(any_of);

static_assert(sfinae_test_any_of<int, int*, int*, bool (*)(int)>);
static_assert(!sfinae_test_any_of<std::execution::parallel_policy, int*, int*, bool (*)(int)>);

template <class Iter>
struct Test {
template <class Policy>
void operator()(Policy&& policy) {
int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
// simple test
assert(std::any_of(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i < 9; }));
assert(!std::any_of(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i > 8; }));

// check that an empty range works
assert(!std::any_of(policy, Iter(std::begin(a)), Iter(std::begin(a)), [](int) { return false; }));

// check that false is returned if no element satisfies the condition
assert(!std::any_of(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 9; }));

// check that true is returned if only one elements satisfies the condition
assert(std::any_of(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 1; }));

// check that a one-element range works
assert(std::any_of(policy, Iter(std::begin(a)), Iter(std::begin(a) + 1), [](int i) { return i == 1; }));

// check that a two-element range works
assert(std::any_of(policy, Iter(std::begin(a)), Iter(std::begin(a) + 2), [](int i) { return i == 2; }));

// check that a large number of elements works
std::vector<int> vec(100, 2);
vec[96] = 3;
assert(std::any_of(Iter(vec.data()), Iter(vec.data() + vec.size()), [](int i) { return i == 3; }));
}
};

int main(int, char**) {
types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<Test>{});

#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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// REQUIRES: with-pstl

// <algorithm>

// template<class ExecutionPolicy, class ForwardIterator, class Predicate>
// bool any_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last,
// Predicate pred);

#include <algorithm>
#include <cassert>
#include <vector>

#include "test_macros.h"
#include "test_execution_policies.h"
#include "test_iterators.h"

EXECUTION_POLICY_SFINAE_TEST(none_of);

static_assert(sfinae_test_none_of<int, int*, int*, bool (*)(int)>);
static_assert(!sfinae_test_none_of<std::execution::parallel_policy, int*, int*, bool (*)(int)>);

template <class Iter>
struct Test {
template <class Policy>
void operator()(Policy&& policy) {
int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
// simple test
assert(std::none_of(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i > 9; }));
assert(!std::none_of(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i >= 8; }));

// check that an empty range works
assert(std::none_of(policy, Iter(std::begin(a)), Iter(std::begin(a)), [](int) { return false; }));

// check that true is returned if no element satisfies the condition
assert(std::none_of(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 9; }));

// check that false is returned if only one elements satisfies the condition
assert(!std::none_of(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 1; }));

// check that a one-element range works
assert(std::none_of(policy, Iter(std::begin(a)), Iter(std::begin(a) + 1), [](int i) { return i != 1; }));

// check that a two-element range works
assert(std::none_of(policy, Iter(std::begin(a)), Iter(std::begin(a) + 2), [](int i) { return i > 2; }));

// check that a large number of elements works
std::vector<int> vec(100);
std::fill(vec.begin(), vec.end(), 3);
assert(std::none_of(Iter(vec.data()), Iter(vec.data() + vec.size()), [](int i) { return i != 3; }));
}
};

int main(int, char**) {
types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<Test>{});

#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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// template<class T> struct is_execution_policy;
// template<class T> constexpr bool is_execution_policy_v = is_execution_policy<T>::value;

// UNSUPPORTED: c++03, c++11, c++14

// REQUIRES: with-pstl

#include <execution>

#include "test_macros.h"

static_assert(std::is_execution_policy<std::execution::sequenced_policy>::value);
static_assert(std::is_execution_policy_v<std::execution::sequenced_policy>);
static_assert(std::is_execution_policy<std::execution::parallel_policy>::value);
static_assert(std::is_execution_policy_v<std::execution::parallel_policy>);
static_assert(std::is_execution_policy<std::execution::parallel_unsequenced_policy>::value);
static_assert(std::is_execution_policy_v<std::execution::parallel_unsequenced_policy>);

#if TEST_STD_VER >= 20
static_assert(std::is_execution_policy<std::execution::unsequenced_policy>::value);
static_assert(std::is_execution_policy_v<std::execution::unsequenced_policy>);
#endif
50 changes: 50 additions & 0 deletions libcxx/test/std/utilities/expol/policies.compile.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// class sequenced_policy;
// class parallel_policy;
// class parallel_unsequenced_policy;
// class unsequenced_policy; // since C++20
//
// inline constexpr sequenced_policy seq = implementation-defined;
// inline constexpr parallel_policy par = implementation-defined;
// inline constexpr parallel_unsequenced_policy par_unseq = implementation-defined;
// inline constexpr unsequenced_policy unseq = implementation-defined; // since C++20

// UNSUPPORTED: c++03, c++11, c++14

// REQUIRES: with-pstl

#include <execution>
#include <type_traits>

#include "test_macros.h"

template <class T>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;

template <class T>
TEST_NOINLINE void use(T&) {}

static_assert(std::is_same_v<remove_cvref_t<decltype(std::execution::seq)>, std::execution::sequenced_policy>);
static_assert(std::is_same_v<remove_cvref_t<decltype(std::execution::par)>, std::execution::parallel_policy>);
static_assert(
std::is_same_v<remove_cvref_t<decltype(std::execution::par_unseq)>, std::execution::parallel_unsequenced_policy>);

#if TEST_STD_VER >= 20
static_assert(std::is_same_v<remove_cvref_t<decltype(std::execution::unseq)>, std::execution::unsequenced_policy>);
#endif

int main(int, char**) {
use(std::execution::seq);
use(std::execution::par);
use(std::execution::par_unseq);
#if TEST_STD_VER >= 20
use(std::execution::unseq);
#endif
}
52 changes: 52 additions & 0 deletions libcxx/test/support/test_execution_policies.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef TEST_SUPPORT_TEST_EXECUTION_POLICIES
#define TEST_SUPPORT_TEST_EXECUTION_POLICIES

#include <cstdlib>
#include <execution>
#include <type_traits>
#include <utility>

#include "test_macros.h"

#define EXECUTION_POLICY_SFINAE_TEST(function) \
template <class, class...> \
struct sfinae_test_##function##_impl : std::true_type {}; \
\
template <class... Args> \
struct sfinae_test_##function##_impl<std::void_t<decltype(std::function(std::declval<Args>()...))>, Args...> \
: std::false_type {}; \
\
template <class... Args> \
constexpr bool sfinae_test_##function = sfinae_test_##function##_impl<void, Args...>::value;

template <class Functor>
bool test_execution_policies(Functor func) {
func(std::execution::seq);
#if TEST_STD_VER >= 20
func(std::execution::unseq);
#endif
func(std::execution::par);
func(std::execution::par_unseq);

return true;
}

template <template <class Iter> class TestClass>
struct TestIteratorWithPolicies {
template <class Iter>
void operator()() {
test_execution_policies(TestClass<Iter>{});
}
};

[[noreturn]] inline void terminate_successful() { std::exit(0); }

#endif // TEST_SUPPORT_TEST_EXECUTION_POLICIES
2 changes: 1 addition & 1 deletion libcxx/utils/generate_header_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def main():
experimental_headers = sorted(str(p.relative_to(include)) for p in include.glob('experimental/[a-z]*') if is_header(p))
extended_headers = sorted(str(p.relative_to(include)) for p in include.glob('ext/[a-z]*') if is_header(p))
public_headers = toplevel_headers + experimental_headers + extended_headers
private_headers = sorted(str(p.relative_to(include)) for p in include.rglob('*') if is_header(p) and str(p.relative_to(include)).startswith('__'))
private_headers = sorted(str(p.relative_to(include)) for p in include.rglob('*') if is_header(p) and str(p.relative_to(include)).startswith('__') and not p.name.startswith('pstl'))
variables = {
'toplevel_headers': toplevel_headers,
'experimental_headers': experimental_headers,
Expand Down