summaryrefslogtreecommitdiff
path: root/libcxx/test
diff options
context:
space:
mode:
authorLouis Dionne <ldionne.2@gmail.com>2023-04-26 17:08:18 -0400
committerLouis Dionne <ldionne.2@gmail.com>2023-05-03 12:27:06 -0400
commit13f5579caeee2c75baf1249b9f64de54f7c361e2 (patch)
treefa8aadf30b17b5ae905b68d3c346c4607af25860 /libcxx/test
parent3e44aa659b98674a1220da235bc2cbafcb311a78 (diff)
downloadllvm-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.cpp36
-rw-r--r--libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_lvalue.pass.cpp65
-rw-r--r--libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_rvalue.pass.cpp53
-rw-r--r--libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/nested.pass.cpp40
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;
}