diff options
author | Louis Dionne <ldionne.2@gmail.com> | 2023-04-26 17:08:18 -0400 |
---|---|---|
committer | Louis Dionne <ldionne.2@gmail.com> | 2023-05-03 12:27:06 -0400 |
commit | 13f5579caeee2c75baf1249b9f64de54f7c361e2 (patch) | |
tree | fa8aadf30b17b5ae905b68d3c346c4607af25860 /libcxx/test | |
parent | 3e44aa659b98674a1220da235bc2cbafcb311a78 (diff) | |
download | llvm-13f5579caeee2c75baf1249b9f64de54f7c361e2.tar.gz |
[libc++] Make std::bind constexpr-friendly
std::bind is supposed to be constexpr-friendly since C++20 and it was
marked as such in our synopsis. However, the tests were not actually
testing any of it and as it happens, std::bind was not really constexpr
friendly. This fixes the issue and makes sure that at least some of the
tests are running in constexpr mode.
Some tests for std::bind check functions that return void, and those
use global variables. These tests haven't been made constexpr-friendly,
however the coverage added by this patch should be sufficient to get
decent confidence.
Differential Revision: https://reviews.llvm.org/D149295
Diffstat (limited to 'libcxx/test')
-rw-r--r-- | libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/PR23141.pass.cpp (renamed from libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/PR23141_invoke_not_constexpr.pass.cpp) | 23 | ||||
-rw-r--r-- | libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_int_0.pass.cpp | 36 | ||||
-rw-r--r-- | libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_lvalue.pass.cpp | 65 | ||||
-rw-r--r-- | libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_rvalue.pass.cpp | 53 | ||||
-rw-r--r-- | libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/nested.pass.cpp | 40 |
5 files changed, 122 insertions, 95 deletions
diff --git a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/PR23141_invoke_not_constexpr.pass.cpp b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/PR23141.pass.cpp index eeb87e0db0a8..f1c5b07aa51b 100644 --- a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/PR23141_invoke_not_constexpr.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/PR23141.pass.cpp @@ -11,9 +11,9 @@ // <functional> // template<CopyConstructible Fn, CopyConstructible... Types> -// unspecified bind(Fn, Types...); +// unspecified bind(Fn, Types...); // constexpr since C++20 // template<Returnable R, CopyConstructible Fn, CopyConstructible... Types> -// unspecified bind(Fn, Types...); +// unspecified bind(Fn, Types...); // constexpr since C++20 // https://llvm.org/PR23141 #include <functional> @@ -21,18 +21,23 @@ #include "test_macros.h" -struct Fun -{ +struct Fun { template<typename T, typename U> - void operator()(T &&, U &&) const - { + TEST_CONSTEXPR_CXX20 void operator()(T &&, U &&) const { static_assert(std::is_same<U, int &>::value, ""); } }; -int main(int, char**) -{ - std::bind(Fun{}, std::placeholders::_1, 42)("hello"); +TEST_CONSTEXPR_CXX20 bool test() { + std::bind(Fun{}, std::placeholders::_1, 42)("hello"); + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER >= 20 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_int_0.pass.cpp b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_int_0.pass.cpp index 4d3f679893d1..37c914467df1 100644 --- a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_int_0.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_int_0.pass.cpp @@ -11,9 +11,9 @@ // <functional> // template<CopyConstructible Fn, CopyConstructible... Types> -// unspecified bind(Fn, Types...); +// unspecified bind(Fn, Types...); // constexpr since C++20 // template<Returnable R, CopyConstructible Fn, CopyConstructible... Types> -// unspecified bind(Fn, Types...); +// unspecified bind(Fn, Types...); // constexpr since C++20 #include <functional> #include <cassert> @@ -21,29 +21,25 @@ #include "test_macros.h" template <class R, class F> -void -test(F f, R expected) -{ +TEST_CONSTEXPR_CXX20 +void test(F f, R expected) { assert(f() == expected); } template <class R, class F> -void -test_const(const F& f, R expected) -{ +TEST_CONSTEXPR_CXX20 +void test_const(const F& f, R expected) { assert(f() == expected); } -int f() {return 1;} +TEST_CONSTEXPR_CXX20 int f() {return 1;} -struct A_int_0 -{ - int operator()() {return 4;} - int operator()() const {return 5;} +struct A_int_0 { + TEST_CONSTEXPR_CXX20 int operator()() {return 4;} + TEST_CONSTEXPR_CXX20 int operator()() const {return 5;} }; -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool test_all() { test(std::bind(f), 1); test(std::bind(&f), 1); test(std::bind(A_int_0()), 4); @@ -53,6 +49,14 @@ int main(int, char**) test(std::bind<int>(&f), 1); test(std::bind<int>(A_int_0()), 4); test_const(std::bind<int>(A_int_0()), 5); + return true; +} + +int main(int, char**) { + test_all(); +#if TEST_STD_VER >= 20 + static_assert(test_all()); +#endif - return 0; + return 0; } diff --git a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_lvalue.pass.cpp b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_lvalue.pass.cpp index 49547a22b39a..82431bb67377 100644 --- a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_lvalue.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_lvalue.pass.cpp @@ -11,9 +11,9 @@ // <functional> // template<CopyConstructible Fn, CopyConstructible... Types> -// unspecified bind(Fn, Types...); +// unspecified bind(Fn, Types...); // constexpr since C++20 // template<Returnable R, CopyConstructible Fn, CopyConstructible... Types> -// unspecified bind(Fn, Types...); +// unspecified bind(Fn, Types...); // constexpr since C++20 #include <stdio.h> @@ -140,27 +140,22 @@ test_void_1() // 1 arg, return int -int f_int_1(int i) -{ +TEST_CONSTEXPR_CXX20 int f_int_1(int i) { return i + 1; } -struct A_int_1 -{ - A_int_1() : data_(5) {} - int operator()(int i) - { +struct A_int_1 { + TEST_CONSTEXPR_CXX20 A_int_1() : data_(5) {} + TEST_CONSTEXPR_CXX20 int operator()(int i) { return i - 1; } - int mem1() {return 3;} - int mem2() const {return 4;} + TEST_CONSTEXPR_CXX20 int mem1() { return 3; } + TEST_CONSTEXPR_CXX20 int mem2() const { return 4; } int data_; }; -void -test_int_1() -{ +TEST_CONSTEXPR_CXX20 bool test_int_1() { using namespace std::placeholders; // function { @@ -212,6 +207,8 @@ test_int_1() std::bind(&A_int_1::data_, _1)(ap) = 7; assert(std::bind(&A_int_1::data_, _1)(ap) == 7); } + + return true; } // 2 arg, return void @@ -263,31 +260,45 @@ test_void_2() } } -struct TFENode -{ - bool foo(unsigned long long) const - { +struct ConstQualifiedMemberFunction { + TEST_CONSTEXPR_CXX20 bool foo(unsigned long long) const { return true; } }; -void -test3() -{ +TEST_CONSTEXPR_CXX20 bool test_const_qualified_member() { using namespace std; using namespace std::placeholders; - const auto f = bind(&TFENode::foo, _1, 0UL); - const TFENode n = TFENode{}; + const auto f = bind(&ConstQualifiedMemberFunction::foo, _1, 0UL); + const ConstQualifiedMemberFunction n = ConstQualifiedMemberFunction{}; bool b = f(n); assert(b); + return true; } -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool test_many_args() { + using namespace std::placeholders; + auto f = [](int& a, char&, float&, long&) -> int& { return a; }; + auto bound = std::bind(f, _4, _3, _2, _1); + int a = 3; char b = '2'; float c = 1.0f; long d = 0l; + int& result = bound(d, c, b, a); + assert(&result == &a); + return true; +} + +int main(int, char**) { test_void_1(); test_int_1(); test_void_2(); - test3(); + test_const_qualified_member(); + test_many_args(); + + // The other tests are not constexpr-friendly since they need to use a global variable +#if TEST_STD_VER >= 20 + static_assert(test_int_1()); + static_assert(test_const_qualified_member()); + static_assert(test_many_args()); +#endif - return 0; + return 0; } diff --git a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_rvalue.pass.cpp b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_rvalue.pass.cpp index cd15727da90d..91ccbcf9eec9 100644 --- a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_rvalue.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_rvalue.pass.cpp @@ -11,9 +11,9 @@ // <functional> // template<CopyConstructible Fn, CopyConstructible... Types> -// unspecified bind(Fn, Types...); +// unspecified bind(Fn, Types...); // constexpr since C++20 // template<Returnable R, CopyConstructible Fn, CopyConstructible... Types> -// unspecified bind(Fn, Types...); +// unspecified bind(Fn, Types...); // constexpr since C++20 #include <stdio.h> @@ -130,27 +130,22 @@ test_void_1() // 1 arg, return int -int f_int_1(int i) -{ +TEST_CONSTEXPR_CXX20 int f_int_1(int i) { return i + 1; } -struct A_int_1 -{ - A_int_1() : data_(5) {} - int operator()(int i) - { +struct A_int_1 { + TEST_CONSTEXPR_CXX20 A_int_1() : data_(5) {} + TEST_CONSTEXPR_CXX20 int operator()(int i) { return i - 1; } - int mem1() {return 3;} - int mem2() const {return 4;} + TEST_CONSTEXPR_CXX20 int mem1() { return 3; } + TEST_CONSTEXPR_CXX20 int mem2() const { return 4; } int data_; }; -void -test_int_1() -{ +TEST_CONSTEXPR_CXX20 bool test_int_1() { using namespace std::placeholders; // function { @@ -196,6 +191,7 @@ test_int_1() std::bind(&A_int_1::data_, _1)(&a) = 7; assert(std::bind(&A_int_1::data_, _1)(&a) == 7); } + return true; } // 2 arg, return void @@ -244,28 +240,39 @@ test_void_2() } } -int f_nested(int i) -{ +TEST_CONSTEXPR_CXX20 int f_nested(int i) { return i+1; } -int g_nested(int i) -{ +TEST_CONSTEXPR_CXX20 int g_nested(int i) { return i*10; } -void test_nested() -{ +TEST_CONSTEXPR_CXX20 bool test_nested() { using namespace std::placeholders; assert(std::bind(f_nested, std::bind(g_nested, _1))(3) == 31); + return true; } -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool test_many_args() { + using namespace std::placeholders; + auto f = [](int a, char, float, long) { return a; }; + auto bound = std::bind(f, _4, _3, _2, _1); + assert(bound(0l, 1.0f, '2', 3) == 3); + return true; +} + +int main(int, char**) { test_void_1(); test_int_1(); test_void_2(); test_nested(); - return 0; + // The other tests are not constexpr-friendly since they need to use a global variable +#if TEST_STD_VER >= 20 + static_assert(test_int_1()); + static_assert(test_nested()); +#endif + + return 0; } diff --git a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/nested.pass.cpp b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/nested.pass.cpp index 76e9d84b63fd..0fe72220efa4 100644 --- a/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/nested.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/nested.pass.cpp @@ -11,45 +11,45 @@ // <functional> // template<CopyConstructible Fn, CopyConstructible... Types> -// unspecified bind(Fn, Types...); +// unspecified bind(Fn, Types...); // constexpr since C++20 // template<Returnable R, CopyConstructible Fn, CopyConstructible... Types> -// unspecified bind(Fn, Types...); +// unspecified bind(Fn, Types...); // constexpr since C++20 // https://llvm.org/PR16343 -#include <cmath> #include <functional> #include <cassert> #include "test_macros.h" -struct power -{ +struct multiply { template <typename T> - T - operator()(T a, T b) - { - return static_cast<T>(std::pow(a, b)); + TEST_CONSTEXPR_CXX20 T operator()(T a, T b) { + return a * b; } }; -struct plus_one -{ +struct plus_one { template <typename T> - T - operator()(T a) - { + TEST_CONSTEXPR_CXX20 T operator()(T a) { return a + 1; } }; -int main(int, char**) -{ - using std::placeholders::_1; +TEST_CONSTEXPR_CXX20 bool test() { + using std::placeholders::_1; + auto g = std::bind(multiply(), 2, _1); + assert(g(5) == 10); + assert(std::bind(plus_one(), g)(5) == 11); - auto g = std::bind(power(), 2, _1); - assert(g(5) == 32); - assert(std::bind(plus_one(), g)(5) == 33); + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER >= 20 + static_assert(test()); +#endif return 0; } |