157257567SEric Fiselier //===----------------------------------------------------------------------===//
257257567SEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
657257567SEric Fiselier //
757257567SEric Fiselier //===----------------------------------------------------------------------===//
857257567SEric Fiselier
931cbe0f2SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14
1057257567SEric Fiselier
1157257567SEric Fiselier // template <class F> unspecified not_fn(F&& f);
1257257567SEric Fiselier
1357257567SEric Fiselier #include <functional>
1457257567SEric Fiselier #include <type_traits>
1557257567SEric Fiselier #include <string>
1657257567SEric Fiselier #include <cassert>
1757257567SEric Fiselier
1857257567SEric Fiselier #include "test_macros.h"
1957257567SEric Fiselier #include "type_id.h"
2084a50f59Szoecarver #include "callable_types.h"
2157257567SEric Fiselier
2257257567SEric Fiselier ///////////////////////////////////////////////////////////////////////////////
2357257567SEric Fiselier // BOOL TEST TYPES
2457257567SEric Fiselier ///////////////////////////////////////////////////////////////////////////////
2557257567SEric Fiselier
2657257567SEric Fiselier struct EvilBool {
2757257567SEric Fiselier static int bang_called;
2857257567SEric Fiselier
2957257567SEric Fiselier EvilBool(EvilBool const&) = default;
3057257567SEric Fiselier EvilBool(EvilBool&&) = default;
3157257567SEric Fiselier
operator !(EvilBool const & other)3257257567SEric Fiselier friend EvilBool operator!(EvilBool const& other) {
3357257567SEric Fiselier ++bang_called;
3457257567SEric Fiselier return EvilBool{!other.value};
3557257567SEric Fiselier }
3657257567SEric Fiselier
3757257567SEric Fiselier private:
3857257567SEric Fiselier friend struct MoveOnlyCallable<EvilBool>;
3957257567SEric Fiselier friend struct CopyCallable<EvilBool>;
4057257567SEric Fiselier friend struct NoExceptCallable<EvilBool>;
4157257567SEric Fiselier
EvilBoolEvilBool427b00e9faSArthur O'Dwyer constexpr explicit EvilBool(bool x) : value(x) {}
4357257567SEric Fiselier EvilBool& operator=(EvilBool const& other) = default;
4457257567SEric Fiselier
4557257567SEric Fiselier public:
4657257567SEric Fiselier bool value;
4757257567SEric Fiselier };
4857257567SEric Fiselier
4957257567SEric Fiselier int EvilBool::bang_called = 0;
5057257567SEric Fiselier
5157257567SEric Fiselier struct ExplicitBool {
5257257567SEric Fiselier ExplicitBool(ExplicitBool const&) = default;
5357257567SEric Fiselier ExplicitBool(ExplicitBool&&) = default;
5457257567SEric Fiselier
operator boolExplicitBool557b00e9faSArthur O'Dwyer constexpr explicit operator bool() const { return value; }
5657257567SEric Fiselier
5757257567SEric Fiselier private:
5857257567SEric Fiselier friend struct MoveOnlyCallable<ExplicitBool>;
5957257567SEric Fiselier friend struct CopyCallable<ExplicitBool>;
6057257567SEric Fiselier
ExplicitBoolExplicitBool617b00e9faSArthur O'Dwyer constexpr explicit ExplicitBool(bool x) : value(x) {}
operator =ExplicitBool627b00e9faSArthur O'Dwyer constexpr ExplicitBool& operator=(bool x) {
6357257567SEric Fiselier value = x;
6457257567SEric Fiselier return *this;
6557257567SEric Fiselier }
6657257567SEric Fiselier
6757257567SEric Fiselier bool value;
6857257567SEric Fiselier };
6957257567SEric Fiselier
7057257567SEric Fiselier
7157257567SEric Fiselier struct NoExceptEvilBool {
7257257567SEric Fiselier NoExceptEvilBool(NoExceptEvilBool const&) = default;
7357257567SEric Fiselier NoExceptEvilBool(NoExceptEvilBool&&) = default;
7457257567SEric Fiselier NoExceptEvilBool& operator=(NoExceptEvilBool const& other) = default;
7557257567SEric Fiselier
NoExceptEvilBoolNoExceptEvilBool767b00e9faSArthur O'Dwyer constexpr explicit NoExceptEvilBool(bool x) : value(x) {}
7757257567SEric Fiselier
operator !(NoExceptEvilBool const & other)7857257567SEric Fiselier friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept {
7957257567SEric Fiselier return NoExceptEvilBool{!other.value};
8057257567SEric Fiselier }
8157257567SEric Fiselier
8257257567SEric Fiselier bool value;
8357257567SEric Fiselier };
8457257567SEric Fiselier
8557257567SEric Fiselier
8657257567SEric Fiselier
877b00e9faSArthur O'Dwyer TEST_CONSTEXPR_CXX20
constructor_tests()887b00e9faSArthur O'Dwyer bool constructor_tests()
8957257567SEric Fiselier {
9057257567SEric Fiselier {
9157257567SEric Fiselier using T = MoveOnlyCallable<bool>;
9257257567SEric Fiselier T value(true);
9357257567SEric Fiselier using RetT = decltype(std::not_fn(std::move(value)));
947a580d0aSEric Fiselier static_assert(std::is_move_constructible<RetT>::value, "");
957a580d0aSEric Fiselier static_assert(!std::is_copy_constructible<RetT>::value, "");
967a580d0aSEric Fiselier static_assert(!std::is_move_assignable<RetT>::value, "");
977a580d0aSEric Fiselier static_assert(!std::is_copy_assignable<RetT>::value, "");
9857257567SEric Fiselier auto ret = std::not_fn(std::move(value));
9957257567SEric Fiselier // test it was moved from
10057257567SEric Fiselier assert(value.value == false);
10157257567SEric Fiselier // test that ret() negates the original value 'true'
10257257567SEric Fiselier assert(ret() == false);
10357257567SEric Fiselier assert(ret(0, 0.0, "blah") == false);
10457257567SEric Fiselier // Move ret and test that it was moved from and that ret2 got the
10557257567SEric Fiselier // original value.
10657257567SEric Fiselier auto ret2 = std::move(ret);
10757257567SEric Fiselier assert(ret() == true);
10857257567SEric Fiselier assert(ret2() == false);
10957257567SEric Fiselier assert(ret2(42) == false);
11057257567SEric Fiselier }
11157257567SEric Fiselier {
11257257567SEric Fiselier using T = CopyCallable<bool>;
11357257567SEric Fiselier T value(false);
11457257567SEric Fiselier using RetT = decltype(std::not_fn(value));
1157a580d0aSEric Fiselier static_assert(std::is_move_constructible<RetT>::value, "");
1167a580d0aSEric Fiselier static_assert(std::is_copy_constructible<RetT>::value, "");
1177a580d0aSEric Fiselier static_assert(!std::is_move_assignable<RetT>::value, "");
1187a580d0aSEric Fiselier static_assert(!std::is_copy_assignable<RetT>::value, "");
11957257567SEric Fiselier auto ret = std::not_fn(value);
12057257567SEric Fiselier // test that value is unchanged (copied not moved)
12157257567SEric Fiselier assert(value.value == false);
12257257567SEric Fiselier // test 'ret' has the original value
12357257567SEric Fiselier assert(ret() == true);
12457257567SEric Fiselier assert(ret(42, 100) == true);
12557257567SEric Fiselier // move from 'ret' and check that 'ret2' has the original value.
12657257567SEric Fiselier auto ret2 = std::move(ret);
12757257567SEric Fiselier assert(ret() == false);
12857257567SEric Fiselier assert(ret2() == true);
12957257567SEric Fiselier assert(ret2("abc") == true);
13084a50f59Szoecarver // initialize not_fn with rvalue
13184a50f59Szoecarver auto ret3 = std::not_fn(std::move(value));
13284a50f59Szoecarver assert(ret(0) == false);
13384a50f59Szoecarver assert(ret3(0) == true);
13457257567SEric Fiselier }
13557257567SEric Fiselier {
13657257567SEric Fiselier using T = CopyAssignableWrapper;
13757257567SEric Fiselier T value(true);
13857257567SEric Fiselier T value2(false);
13957257567SEric Fiselier using RetT = decltype(std::not_fn(value));
1407a580d0aSEric Fiselier static_assert(std::is_move_constructible<RetT>::value, "");
1417a580d0aSEric Fiselier static_assert(std::is_copy_constructible<RetT>::value, "");
14257257567SEric Fiselier auto ret = std::not_fn(value);
14357257567SEric Fiselier assert(ret() == false);
14457257567SEric Fiselier auto ret2 = std::not_fn(value2);
14557257567SEric Fiselier assert(ret2() == true);
14657257567SEric Fiselier }
14757257567SEric Fiselier {
14857257567SEric Fiselier using T = MoveAssignableWrapper;
14957257567SEric Fiselier T value(true);
15057257567SEric Fiselier T value2(false);
15157257567SEric Fiselier using RetT = decltype(std::not_fn(std::move(value)));
1527a580d0aSEric Fiselier static_assert(std::is_move_constructible<RetT>::value, "");
1537a580d0aSEric Fiselier static_assert(!std::is_copy_constructible<RetT>::value, "");
1547a580d0aSEric Fiselier static_assert(!std::is_copy_assignable<RetT>::value, "");
15557257567SEric Fiselier auto ret = std::not_fn(std::move(value));
15657257567SEric Fiselier assert(ret() == false);
15757257567SEric Fiselier auto ret2 = std::not_fn(std::move(value2));
15857257567SEric Fiselier assert(ret2() == true);
15957257567SEric Fiselier }
1607b00e9faSArthur O'Dwyer return true;
16157257567SEric Fiselier }
16257257567SEric Fiselier
return_type_tests()16357257567SEric Fiselier void return_type_tests()
16457257567SEric Fiselier {
16557257567SEric Fiselier using std::is_same;
16657257567SEric Fiselier {
16757257567SEric Fiselier using T = CopyCallable<bool>;
16857257567SEric Fiselier auto ret = std::not_fn(T{false});
1697a580d0aSEric Fiselier static_assert(is_same<decltype(ret()), bool>::value, "");
1707a580d0aSEric Fiselier static_assert(is_same<decltype(ret("abc")), bool>::value, "");
17157257567SEric Fiselier assert(ret() == true);
17257257567SEric Fiselier }
17357257567SEric Fiselier {
17457257567SEric Fiselier using T = CopyCallable<ExplicitBool>;
17557257567SEric Fiselier auto ret = std::not_fn(T{true});
1767a580d0aSEric Fiselier static_assert(is_same<decltype(ret()), bool>::value, "");
1777a580d0aSEric Fiselier static_assert(is_same<decltype(ret(std::string("abc"))), bool>::value, "");
17857257567SEric Fiselier assert(ret() == false);
17957257567SEric Fiselier }
18057257567SEric Fiselier {
18157257567SEric Fiselier using T = CopyCallable<EvilBool>;
18257257567SEric Fiselier auto ret = std::not_fn(T{false});
1837a580d0aSEric Fiselier static_assert(is_same<decltype(ret()), EvilBool>::value, "");
18457257567SEric Fiselier EvilBool::bang_called = 0;
18557257567SEric Fiselier auto value_ret = ret();
18657257567SEric Fiselier assert(EvilBool::bang_called == 1);
18757257567SEric Fiselier assert(value_ret.value == true);
18857257567SEric Fiselier ret();
18957257567SEric Fiselier assert(EvilBool::bang_called == 2);
19057257567SEric Fiselier }
19157257567SEric Fiselier }
19257257567SEric Fiselier
19357257567SEric Fiselier // Other tests only test using objects with call operators. Test various
19457257567SEric Fiselier // other callable types here.
1957b00e9faSArthur O'Dwyer TEST_CONSTEXPR_CXX20
other_callable_types_test()1967b00e9faSArthur O'Dwyer bool other_callable_types_test()
19757257567SEric Fiselier {
19857257567SEric Fiselier { // test with function pointer
19957257567SEric Fiselier auto ret = std::not_fn(returns_true);
20057257567SEric Fiselier assert(ret() == false);
20157257567SEric Fiselier }
20257257567SEric Fiselier { // test with lambda
20357257567SEric Fiselier auto returns_value = [](bool value) { return value; };
20457257567SEric Fiselier auto ret = std::not_fn(returns_value);
20557257567SEric Fiselier assert(ret(true) == false);
20657257567SEric Fiselier assert(ret(false) == true);
20757257567SEric Fiselier }
20857257567SEric Fiselier { // test with pointer to member function
20957257567SEric Fiselier MemFunCallable mt(true);
21057257567SEric Fiselier const MemFunCallable mf(false);
21157257567SEric Fiselier auto ret = std::not_fn(&MemFunCallable::return_value);
21257257567SEric Fiselier assert(ret(mt) == false);
21357257567SEric Fiselier assert(ret(mf) == true);
21457257567SEric Fiselier assert(ret(&mt) == false);
21557257567SEric Fiselier assert(ret(&mf) == true);
21657257567SEric Fiselier }
21757257567SEric Fiselier { // test with pointer to member function
21857257567SEric Fiselier MemFunCallable mt(true);
21957257567SEric Fiselier MemFunCallable mf(false);
22057257567SEric Fiselier auto ret = std::not_fn(&MemFunCallable::return_value_nc);
22157257567SEric Fiselier assert(ret(mt) == false);
22257257567SEric Fiselier assert(ret(mf) == true);
22357257567SEric Fiselier assert(ret(&mt) == false);
22457257567SEric Fiselier assert(ret(&mf) == true);
22557257567SEric Fiselier }
22657257567SEric Fiselier { // test with pointer to member data
22757257567SEric Fiselier MemFunCallable mt(true);
22857257567SEric Fiselier const MemFunCallable mf(false);
22957257567SEric Fiselier auto ret = std::not_fn(&MemFunCallable::value);
23057257567SEric Fiselier assert(ret(mt) == false);
23157257567SEric Fiselier assert(ret(mf) == true);
23257257567SEric Fiselier assert(ret(&mt) == false);
23357257567SEric Fiselier assert(ret(&mf) == true);
23457257567SEric Fiselier }
2357b00e9faSArthur O'Dwyer return true;
23657257567SEric Fiselier }
23757257567SEric Fiselier
throws_in_constructor_test()23857257567SEric Fiselier void throws_in_constructor_test()
23957257567SEric Fiselier {
24057257567SEric Fiselier #ifndef TEST_HAS_NO_EXCEPTIONS
24157257567SEric Fiselier struct ThrowsOnCopy {
24257257567SEric Fiselier ThrowsOnCopy(ThrowsOnCopy const&) {
24357257567SEric Fiselier throw 42;
24457257567SEric Fiselier }
24557257567SEric Fiselier ThrowsOnCopy() = default;
2460d467ff5SSaleem Abdulrasool bool operator()() const {
2470d467ff5SSaleem Abdulrasool assert(false);
2484e00a192SCasey Carter #ifdef TEST_COMPILER_MSVC
2490d467ff5SSaleem Abdulrasool __assume(0);
2500d467ff5SSaleem Abdulrasool #else
2510d467ff5SSaleem Abdulrasool __builtin_unreachable();
2520d467ff5SSaleem Abdulrasool #endif
2530d467ff5SSaleem Abdulrasool }
25457257567SEric Fiselier };
25557257567SEric Fiselier {
25657257567SEric Fiselier ThrowsOnCopy cp;
25757257567SEric Fiselier try {
25804576cc0SStephan T. Lavavej (void)std::not_fn(cp);
25957257567SEric Fiselier assert(false);
26057257567SEric Fiselier } catch (int const& value) {
26157257567SEric Fiselier assert(value == 42);
26257257567SEric Fiselier }
26357257567SEric Fiselier }
26457257567SEric Fiselier #endif
26557257567SEric Fiselier }
26657257567SEric Fiselier
2677b00e9faSArthur O'Dwyer TEST_CONSTEXPR_CXX20
call_operator_sfinae_test()2687b00e9faSArthur O'Dwyer bool call_operator_sfinae_test() {
26957257567SEric Fiselier { // wrong number of arguments
27057257567SEric Fiselier using T = decltype(std::not_fn(returns_true));
271bcde6e71SZhihao Yuan static_assert(std::is_invocable<T>::value, ""); // callable only with no args
272bcde6e71SZhihao Yuan static_assert(!std::is_invocable<T, bool>::value, "");
27357257567SEric Fiselier }
27457257567SEric Fiselier { // violates const correctness (member function pointer)
27557257567SEric Fiselier using T = decltype(std::not_fn(&MemFunCallable::return_value_nc));
276bcde6e71SZhihao Yuan static_assert(std::is_invocable<T, MemFunCallable&>::value, "");
277bcde6e71SZhihao Yuan static_assert(!std::is_invocable<T, const MemFunCallable&>::value, "");
27857257567SEric Fiselier }
27957257567SEric Fiselier { // violates const correctness (call object)
28057257567SEric Fiselier using Obj = CopyCallable<bool>;
28157257567SEric Fiselier using NCT = decltype(std::not_fn(Obj{true}));
28257257567SEric Fiselier using CT = const NCT;
283bcde6e71SZhihao Yuan static_assert(std::is_invocable<NCT>::value, "");
284bcde6e71SZhihao Yuan static_assert(!std::is_invocable<CT>::value, "");
28557257567SEric Fiselier }
28657257567SEric Fiselier { // returns bad type with no operator!
28757257567SEric Fiselier auto fn = [](auto x) { return x; };
28857257567SEric Fiselier using T = decltype(std::not_fn(fn));
289bcde6e71SZhihao Yuan static_assert(std::is_invocable<T, bool>::value, "");
290bcde6e71SZhihao Yuan static_assert(!std::is_invocable<T, std::string>::value, "");
29157257567SEric Fiselier }
2927b00e9faSArthur O'Dwyer return true;
29357257567SEric Fiselier }
29457257567SEric Fiselier
2957b00e9faSArthur O'Dwyer TEST_CONSTEXPR_CXX20
call_operator_forwarding_test()2967b00e9faSArthur O'Dwyer bool call_operator_forwarding_test()
29757257567SEric Fiselier {
29857257567SEric Fiselier using Fn = ForwardingCallObject;
29930f589c9SArthur O'Dwyer Fn::State st;
30030f589c9SArthur O'Dwyer auto obj = std::not_fn(Fn{st});
30157257567SEric Fiselier const auto& c_obj = obj;
30257257567SEric Fiselier { // test zero args
30357257567SEric Fiselier obj();
30430f589c9SArthur O'Dwyer assert(st.check_call<>(CT_NonConst | CT_LValue));
3059372d8bcSEric Fiselier std::move(obj)();
30630f589c9SArthur O'Dwyer assert(st.check_call<>(CT_NonConst | CT_RValue));
30757257567SEric Fiselier c_obj();
30830f589c9SArthur O'Dwyer assert(st.check_call<>(CT_Const | CT_LValue));
3099372d8bcSEric Fiselier std::move(c_obj)();
31030f589c9SArthur O'Dwyer assert(st.check_call<>(CT_Const | CT_RValue));
31157257567SEric Fiselier }
31257257567SEric Fiselier { // test value categories
31357257567SEric Fiselier int x = 42;
31457257567SEric Fiselier const int cx = 42;
31557257567SEric Fiselier obj(x);
31630f589c9SArthur O'Dwyer assert(st.check_call<int&>(CT_NonConst | CT_LValue));
31757257567SEric Fiselier obj(cx);
31830f589c9SArthur O'Dwyer assert(st.check_call<const int&>(CT_NonConst | CT_LValue));
31957257567SEric Fiselier obj(std::move(x));
32030f589c9SArthur O'Dwyer assert(st.check_call<int&&>(CT_NonConst | CT_LValue));
32157257567SEric Fiselier obj(std::move(cx));
32230f589c9SArthur O'Dwyer assert(st.check_call<const int&&>(CT_NonConst | CT_LValue));
32357257567SEric Fiselier obj(42);
32430f589c9SArthur O'Dwyer assert(st.check_call<int&&>(CT_NonConst | CT_LValue));
3259372d8bcSEric Fiselier }
3269372d8bcSEric Fiselier { // test value categories - rvalue
3279372d8bcSEric Fiselier int x = 42;
3289372d8bcSEric Fiselier const int cx = 42;
3299372d8bcSEric Fiselier std::move(obj)(x);
33030f589c9SArthur O'Dwyer assert(st.check_call<int&>(CT_NonConst | CT_RValue));
3319372d8bcSEric Fiselier std::move(obj)(cx);
33230f589c9SArthur O'Dwyer assert(st.check_call<const int&>(CT_NonConst | CT_RValue));
3339372d8bcSEric Fiselier std::move(obj)(std::move(x));
33430f589c9SArthur O'Dwyer assert(st.check_call<int&&>(CT_NonConst | CT_RValue));
3359372d8bcSEric Fiselier std::move(obj)(std::move(cx));
33630f589c9SArthur O'Dwyer assert(st.check_call<const int&&>(CT_NonConst | CT_RValue));
3379372d8bcSEric Fiselier std::move(obj)(42);
33830f589c9SArthur O'Dwyer assert(st.check_call<int&&>(CT_NonConst | CT_RValue));
33957257567SEric Fiselier }
34057257567SEric Fiselier { // test value categories - const call
34157257567SEric Fiselier int x = 42;
34257257567SEric Fiselier const int cx = 42;
34357257567SEric Fiselier c_obj(x);
34430f589c9SArthur O'Dwyer assert(st.check_call<int&>(CT_Const | CT_LValue));
34557257567SEric Fiselier c_obj(cx);
34630f589c9SArthur O'Dwyer assert(st.check_call<const int&>(CT_Const | CT_LValue));
34757257567SEric Fiselier c_obj(std::move(x));
34830f589c9SArthur O'Dwyer assert(st.check_call<int&&>(CT_Const | CT_LValue));
34957257567SEric Fiselier c_obj(std::move(cx));
35030f589c9SArthur O'Dwyer assert(st.check_call<const int&&>(CT_Const | CT_LValue));
35157257567SEric Fiselier c_obj(42);
35230f589c9SArthur O'Dwyer assert(st.check_call<int&&>(CT_Const | CT_LValue));
3539372d8bcSEric Fiselier }
3549372d8bcSEric Fiselier { // test value categories - const call rvalue
3559372d8bcSEric Fiselier int x = 42;
3569372d8bcSEric Fiselier const int cx = 42;
3579372d8bcSEric Fiselier std::move(c_obj)(x);
35830f589c9SArthur O'Dwyer assert(st.check_call<int&>(CT_Const | CT_RValue));
3599372d8bcSEric Fiselier std::move(c_obj)(cx);
36030f589c9SArthur O'Dwyer assert(st.check_call<const int&>(CT_Const | CT_RValue));
3619372d8bcSEric Fiselier std::move(c_obj)(std::move(x));
36230f589c9SArthur O'Dwyer assert(st.check_call<int&&>(CT_Const | CT_RValue));
3639372d8bcSEric Fiselier std::move(c_obj)(std::move(cx));
36430f589c9SArthur O'Dwyer assert(st.check_call<const int&&>(CT_Const | CT_RValue));
3659372d8bcSEric Fiselier std::move(c_obj)(42);
36630f589c9SArthur O'Dwyer assert(st.check_call<int&&>(CT_Const | CT_RValue));
36757257567SEric Fiselier }
36857257567SEric Fiselier { // test multi arg
3697b00e9faSArthur O'Dwyer using String = const char *;
37057257567SEric Fiselier const double y = 3.14;
3717b00e9faSArthur O'Dwyer String s = "abc";
3727b00e9faSArthur O'Dwyer obj(42, std::move(y), s, String{"foo"});
3737b00e9faSArthur O'Dwyer assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_LValue)));
3747b00e9faSArthur O'Dwyer std::move(obj)(42, std::move(y), s, String{"foo"});
3757b00e9faSArthur O'Dwyer assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_RValue)));
3767b00e9faSArthur O'Dwyer c_obj(42, std::move(y), s, String{"foo"});
3777b00e9faSArthur O'Dwyer assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const | CT_LValue)));
3787b00e9faSArthur O'Dwyer std::move(c_obj)(42, std::move(y), s, String{"foo"});
3797b00e9faSArthur O'Dwyer assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const | CT_RValue)));
38057257567SEric Fiselier }
3817b00e9faSArthur O'Dwyer return true;
38257257567SEric Fiselier }
38357257567SEric Fiselier
3847b00e9faSArthur O'Dwyer TEST_CONSTEXPR_CXX20
call_operator_noexcept_test()3857b00e9faSArthur O'Dwyer bool call_operator_noexcept_test()
38657257567SEric Fiselier {
38757257567SEric Fiselier {
38857257567SEric Fiselier using T = ConstCallable<bool>;
38957257567SEric Fiselier T value(true);
39057257567SEric Fiselier auto ret = std::not_fn(value);
39157257567SEric Fiselier static_assert(!noexcept(ret()), "call should not be noexcept");
39257257567SEric Fiselier auto const& cret = ret;
39357257567SEric Fiselier static_assert(!noexcept(cret()), "call should not be noexcept");
39457257567SEric Fiselier }
39557257567SEric Fiselier {
39657257567SEric Fiselier using T = NoExceptCallable<bool>;
39757257567SEric Fiselier T value(true);
39857257567SEric Fiselier auto ret = std::not_fn(value);
399*275ff33aSCasey Carter LIBCPP_STATIC_ASSERT(noexcept(!std::__invoke(value)), "");
4005e931dd2SEric Fiselier #if TEST_STD_VER > 14
4015e931dd2SEric Fiselier static_assert(noexcept(!std::invoke(value)), "");
4025e931dd2SEric Fiselier #endif
40357257567SEric Fiselier static_assert(noexcept(ret()), "call should be noexcept");
40457257567SEric Fiselier auto const& cret = ret;
40557257567SEric Fiselier static_assert(noexcept(cret()), "call should be noexcept");
40657257567SEric Fiselier }
40757257567SEric Fiselier {
408881334e7SEric Fiselier using T = NoExceptCallable<NoExceptEvilBool>;
409881334e7SEric Fiselier T value(true);
410881334e7SEric Fiselier auto ret = std::not_fn(value);
411881334e7SEric Fiselier static_assert(noexcept(ret()), "call should not be noexcept");
412881334e7SEric Fiselier auto const& cret = ret;
413881334e7SEric Fiselier static_assert(noexcept(cret()), "call should not be noexcept");
414881334e7SEric Fiselier }
415881334e7SEric Fiselier {
41657257567SEric Fiselier using T = NoExceptCallable<EvilBool>;
41757257567SEric Fiselier T value(true);
41857257567SEric Fiselier auto ret = std::not_fn(value);
41957257567SEric Fiselier static_assert(!noexcept(ret()), "call should not be noexcept");
42057257567SEric Fiselier auto const& cret = ret;
42157257567SEric Fiselier static_assert(!noexcept(cret()), "call should not be noexcept");
42257257567SEric Fiselier }
4237b00e9faSArthur O'Dwyer return true;
42457257567SEric Fiselier }
42557257567SEric Fiselier
4267b00e9faSArthur O'Dwyer TEST_CONSTEXPR_CXX20
test_lwg2767()4277b00e9faSArthur O'Dwyer bool test_lwg2767() {
428ade32237SStephan T. Lavavej // See https://cplusplus.github.io/LWG/lwg-defects.html#2767
429f72aaff9SEric Fiselier struct Abstract { virtual void f() const = 0; };
430f72aaff9SEric Fiselier struct Derived : public Abstract { void f() const {} };
4317b00e9faSArthur O'Dwyer struct F { constexpr bool operator()(Abstract&&) { return false; } };
432f72aaff9SEric Fiselier {
433f72aaff9SEric Fiselier Derived d;
434f72aaff9SEric Fiselier Abstract &a = d;
435f72aaff9SEric Fiselier bool b = std::not_fn(F{})(std::move(a));
436f72aaff9SEric Fiselier assert(b);
437f72aaff9SEric Fiselier }
4387b00e9faSArthur O'Dwyer return true;
439f72aaff9SEric Fiselier }
440f72aaff9SEric Fiselier
main(int,char **)4412df59c50SJF Bastien int main(int, char**)
44257257567SEric Fiselier {
44357257567SEric Fiselier constructor_tests();
44457257567SEric Fiselier return_type_tests();
44557257567SEric Fiselier other_callable_types_test();
44657257567SEric Fiselier throws_in_constructor_test();
44757257567SEric Fiselier call_operator_sfinae_test(); // somewhat of an extension
44857257567SEric Fiselier call_operator_forwarding_test();
44957257567SEric Fiselier call_operator_noexcept_test();
450f72aaff9SEric Fiselier test_lwg2767();
4512df59c50SJF Bastien
4527b00e9faSArthur O'Dwyer #if TEST_STD_VER >= 20
4537b00e9faSArthur O'Dwyer static_assert(constructor_tests());
4547b00e9faSArthur O'Dwyer static_assert(other_callable_types_test());
4557b00e9faSArthur O'Dwyer static_assert(call_operator_sfinae_test()); // somewhat of an extension
4567b00e9faSArthur O'Dwyer static_assert(call_operator_forwarding_test());
4577b00e9faSArthur O'Dwyer static_assert(call_operator_noexcept_test());
4587b00e9faSArthur O'Dwyer static_assert(test_lwg2767());
4597b00e9faSArthur O'Dwyer #endif
4607b00e9faSArthur O'Dwyer
4612df59c50SJF Bastien return 0;
46257257567SEric Fiselier }
463