summaryrefslogtreecommitdiffstats
path: root/libcxx/test
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2016-04-20 00:14:32 +0000
committerEric Fiselier <eric@efcs.ca>2016-04-20 00:14:32 +0000
commit840fa745ca493123c44d7e9b62676f3a0cd23c0d (patch)
tree48f0ece836408898936fa627512b5422a3e562b2 /libcxx/test
parent3eef9d180dbc9458f96f3e0f6a79fdee56bb8aae (diff)
downloadbcm5719-llvm-840fa745ca493123c44d7e9b62676f3a0cd23c0d.tar.gz
bcm5719-llvm-840fa745ca493123c44d7e9b62676f3a0cd23c0d.zip
Add 'is_callable' and 'is_nothrow_callable' traits and cleanup INVOKE.
The primary purpose of this patch is to add the 'is_callable' traits. Since 'is_nothrow_callable' required making 'INVOKE' conditionally noexcept I also took this oppertunity to implement a constexpr version of INVOKE. This fixes 'std::experimental::apply' which required constexpr 'INVOKE support'. This patch will be followed up with some cleanup. Primarly removing most of "__member_function_traits" since it's no longer used by INVOKE (in C++11 at least). llvm-svn: 266836
Diffstat (limited to 'libcxx/test')
-rw-r--r--libcxx/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp5
-rw-r--r--libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/PR23141_invoke_not_constexpr.pass.cpp35
-rw-r--r--libcxx/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp3
-rw-r--r--libcxx/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp21
-rw-r--r--libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h196
-rw-r--r--libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp4
-rw-r--r--libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_cxx03.pass.cpp (renamed from libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_no_variadics.pass.cpp)2
-rw-r--r--libcxx/test/std/utilities/meta/meta.rel/is_callable.pass.cpp159
-rw-r--r--libcxx/test/std/utilities/meta/meta.rel/is_nothrow_callable.pass.cpp115
-rw-r--r--libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp7
-rw-r--r--libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp4
11 files changed, 488 insertions, 63 deletions
diff --git a/libcxx/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp
index 2d700486f26..5b8a8f09d1e 100644
--- a/libcxx/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp
+++ b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp
@@ -9,11 +9,6 @@
// UNSUPPORTED: c++98, c++03, c++11
-// TODO(ericwf)
-// constexpr support temporarily reverted due to bug:
-// https://llvm.org/bugs/show_bug.cgi?id=23141
-// XFAIL: *
-
// <experimental/tuple>
// template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
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_invoke_not_constexpr.pass.cpp
new file mode 100644
index 00000000000..163b2d9afea
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/PR23141_invoke_not_constexpr.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <functional>
+
+// template<CopyConstructible Fn, CopyConstructible... Types>
+// unspecified bind(Fn, Types...);
+// template<Returnable R, CopyConstructible Fn, CopyConstructible... Types>
+// unspecified bind(Fn, Types...);
+
+// https://llvm.org/bugs/show_bug.cgi?id=23141
+#include <functional>
+#include <type_traits>
+
+struct Fun
+{
+ template<typename T, typename U>
+ void operator()(T && t, U && u) const
+ {
+ static_assert(std::is_same<U, int &>::value, "");
+ }
+};
+
+int main()
+{
+ std::bind(Fun{}, std::placeholders::_1, 42)("hello");
+}
diff --git a/libcxx/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp b/libcxx/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp
index 09e8e21137a..509c751b455 100644
--- a/libcxx/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.require/bullet_1_2_3.pass.cpp
@@ -260,8 +260,11 @@ void test_derived_from_ref_wrap() {
DerivedFromRefWrap<int> d(x);
auto get_fn = &std::reference_wrapper<int>::get;
auto& ret = std::__invoke(get_fn, r);
+ auto& cret = std::__invoke_constexpr(get_fn, r);
assert(&ret == &x);
+ assert(&cret == &x);
auto& ret2 = std::__invoke(get_fn, d);
+ auto& cret2 = std::__invoke_constexpr(get_fn, d);
assert(&ret2 == &x);
auto& ret3 = std::__invoke(get_fn, r2);
assert(&ret3 == &x);
diff --git a/libcxx/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp b/libcxx/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp
index 2007c417a62..803c501f8c9 100644
--- a/libcxx/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp
@@ -185,11 +185,22 @@ private:
#else
void runTest(Fn M, T& obj, ObjectType* expect ) {
#endif
- static_assert((std::is_same<
- decltype(std::__invoke(M, std::forward<T>(obj))), Expect
- >::value), "");
- Expect e = std::__invoke(M, std::forward<T>(obj));
- assert(&e == expect);
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke(M, std::forward<T>(obj))), Expect
+ >::value), "");
+ Expect e = std::__invoke(M, std::forward<T>(obj));
+ assert(&e == expect);
+ }
+#if TEST_STD_VER >= 11
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke_constexpr(M, std::forward<T>(obj))), Expect
+ >::value), "");
+ Expect e = std::__invoke_constexpr(M, std::forward<T>(obj));
+ assert(&e == expect);
+ }
+#endif
}
};
diff --git a/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h b/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h
index 495703d0e32..7e7a5fd24a6 100644
--- a/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h
+++ b/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h
@@ -271,89 +271,185 @@ private:
ArgType a0, a1, a2;
//==========================================================================
- // BULLET 1 AND 2 TEST METHODS
+ // BULLET 1, 2 AND 3 TEST METHODS
//==========================================================================
template <class MethodPtr, class ObjectT>
void runTestImp(Int<0>, MethodPtr ptr, ObjectT& object) {
- static_assert((std::is_same<
- decltype(std::__invoke(ptr, object_cast(object)))
- , CallRet>::value), "");
- assert(ID::unchecked_call == false);
- CallRet ret = std::__invoke(ptr, object_cast(object));
- assert(ID::checkCalled(ret));
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke(ptr, object_cast(object)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke(ptr, object_cast(object));
+ assert(ID::checkCalled(ret));
+ }
+#if TEST_STD_VER >= 11
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke_constexpr(ptr, object_cast(object)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke_constexpr(ptr, object_cast(object));
+ assert(ID::checkCalled(ret));
+ }
+#endif
}
template <class MethodPtr, class ObjectT>
void runTestImp(Int<1>, MethodPtr ptr, ObjectT& object) {
- static_assert((std::is_same<
- decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0)))
- , CallRet>::value), "");
- assert(ID::unchecked_call == false);
- CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0));
- assert(ID::checkCalled(ret));
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0));
+ assert(ID::checkCalled(ret));
+ }
+#if TEST_STD_VER >= 11
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0));
+ assert(ID::checkCalled(ret));
+ }
+#endif
}
template <class MethodPtr, class ObjectT>
void runTestImp(Int<2>, MethodPtr ptr, ObjectT& object) {
- static_assert((std::is_same<
- decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
- , CallRet>::value), "");
- assert(ID::unchecked_call == false);
- CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
- assert(ID::checkCalled(ret));
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
+ assert(ID::checkCalled(ret));
+ }
+#if TEST_STD_VER >= 11
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
+ assert(ID::checkCalled(ret));
+ }
+#endif
}
template <class MethodPtr, class ObjectT>
void runTestImp(Int<3>, MethodPtr ptr, ObjectT& object) {
- static_assert((std::is_same<
- decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
- , CallRet>::value), "");
- assert(ID::unchecked_call == false);
- CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
- assert(ID::checkCalled(ret));
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
+ assert(ID::checkCalled(ret));
+ }
+#if TEST_STD_VER >= 11
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
+ assert(ID::checkCalled(ret));
+ }
+#endif
}
//==========================================================================
- // BULLET 5 TEST METHODS
+ // BULLET 7 TEST METHODS
//==========================================================================
template <class ObjectT>
void runTestImp(Int<0>, ObjectT& object) {
- static_assert((std::is_same<
- decltype(std::__invoke(object_cast(object)))
- , CallRet>::value), "");
- assert(ID::unchecked_call == false);
- CallRet ret = std::__invoke(object_cast(object));
- assert(ID::checkCalled(ret));
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke(object_cast(object)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke(object_cast(object));
+ assert(ID::checkCalled(ret));
+ }
+#if TEST_STD_VER >= 11
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke_constexpr(object_cast(object)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke_constexpr(object_cast(object));
+ assert(ID::checkCalled(ret));
+ }
+#endif
}
template <class ObjectT>
void runTestImp(Int<1>, ObjectT& object) {
- static_assert((std::is_same<
- decltype(std::__invoke(object_cast(object), arg_cast(a0)))
- , CallRet>::value), "");
- assert(ID::unchecked_call == false);
- CallRet ret = std::__invoke(object_cast(object), arg_cast(a0));
- assert(ID::checkCalled(ret));
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke(object_cast(object), arg_cast(a0)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke(object_cast(object), arg_cast(a0));
+ assert(ID::checkCalled(ret));
+ }
+#if TEST_STD_VER >= 11
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0));
+ assert(ID::checkCalled(ret));
+ }
+#endif
}
template <class ObjectT>
void runTestImp(Int<2>, ObjectT& object) {
- static_assert((std::is_same<
- decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1)))
- , CallRet>::value), "");
- assert(ID::unchecked_call == false);
- CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1));
- assert(ID::checkCalled(ret));
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1));
+ assert(ID::checkCalled(ret));
+ }
+#if TEST_STD_VER >= 11
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1));
+ assert(ID::checkCalled(ret));
+ }
+#endif
}
template <class ObjectT>
void runTestImp(Int<3>, ObjectT& object) {
- static_assert((std::is_same<
- decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
- , CallRet>::value), "");
- assert(ID::unchecked_call == false);
- CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
- assert(ID::checkCalled(ret));
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
+ assert(ID::checkCalled(ret));
+ }
+#if TEST_STD_VER >= 11
+ {
+ static_assert((std::is_same<
+ decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
+ , CallRet>::value), "");
+ assert(ID::unchecked_call == false);
+ CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
+ assert(ID::checkCalled(ret));
+ }
+#endif
}
};
diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp
index aa77dab5151..3e4a99e981d 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03
+
// <memory>
// shared_ptr
@@ -55,7 +57,6 @@ int main()
}
assert(A::count == 0);
assert(test_allocator<A>::alloc_count == 0);
-#if __cplusplus >= 201103L
{
int i = 67;
char c = 'e';
@@ -74,5 +75,4 @@ int main()
assert(p->get_char() == 'f');
}
assert(A::count == 0);
-#endif
}
diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_no_variadics.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_cxx03.pass.cpp
index 8dcd50e4941..f6350c72bcc 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_no_variadics.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_cxx03.pass.cpp
@@ -14,7 +14,7 @@
// template<class T, class A, class... Args>
// shared_ptr<T> allocate_shared(const A& a, Args&&... args);
-#define _LIBCPP_HAS_NO_VARIADICS
+
#include <memory>
#include <new>
#include <cstdlib>
diff --git a/libcxx/test/std/utilities/meta/meta.rel/is_callable.pass.cpp b/libcxx/test/std/utilities/meta/meta.rel/is_callable.pass.cpp
new file mode 100644
index 00000000000..7de65835f73
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.rel/is_callable.pass.cpp
@@ -0,0 +1,159 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// type_traits
+
+// is_callable
+
+// Most testing of is_callable is done within the [meta.trans.other] result_of
+// tests.
+
+#include <type_traits>
+#include <functional>
+
+#include "test_macros.h"
+
+struct Tag {};
+struct DerFromTag : Tag {};
+
+struct Implicit {
+ Implicit(int) {}
+};
+
+struct Explicit {
+ explicit Explicit(int) {}
+};
+
+struct NotCallableWithInt {
+ int operator()(int) = delete;
+ int operator()(Tag) { return 42; }
+};
+
+int main()
+{
+ {
+ using Fn = int(Tag::*)(int);
+ using RFn = int(Tag::*)(int) &&;
+ // INVOKE bullet 1, 2 and 3
+ {
+ // Bullet 1
+ static_assert(std::is_callable<Fn(Tag&, int)>::value);
+ static_assert(std::is_callable<Fn(DerFromTag&, int)>::value);
+ static_assert(std::is_callable<RFn(Tag&&, int)>::value);
+ static_assert(!std::is_callable<RFn(Tag&, int)>::value);
+ static_assert(!std::is_callable<Fn(Tag&)>::value);
+ static_assert(!std::is_callable<Fn(Tag const&, int)>::value);
+ }
+ {
+ // Bullet 2
+ using T = std::reference_wrapper<Tag>;
+ using DT = std::reference_wrapper<DerFromTag>;
+ using CT = std::reference_wrapper<const Tag>;
+ static_assert(std::is_callable<Fn(T&, int)>::value);
+ static_assert(std::is_callable<Fn(DT&, int)>::value);
+ static_assert(std::is_callable<Fn(const T&, int)>::value);
+ static_assert(std::is_callable<Fn(T&&, int)>::value);
+ static_assert(!std::is_callable<Fn(CT&, int)>::value);
+ static_assert(!std::is_callable<RFn(T, int)>::value);
+ }
+ {
+ // Bullet 3
+ using T = Tag*;
+ using DT = DerFromTag*;
+ using CT = const Tag*;
+ using ST = std::unique_ptr<Tag>;
+ static_assert(std::is_callable<Fn(T&, int)>::value);
+ static_assert(std::is_callable<Fn(DT&, int)>::value);
+ static_assert(std::is_callable<Fn(const T&, int)>::value);
+ static_assert(std::is_callable<Fn(T&&, int)>::value);
+ static_assert(std::is_callable<Fn(ST, int)>::value);
+ static_assert(!std::is_callable<Fn(CT&, int)>::value);
+ static_assert(!std::is_callable<RFn(T, int)>::value);
+ }
+ }
+ {
+ // Bullets 4, 5 and 6
+ using Fn = int (Tag::*);
+ static_assert(!std::is_callable<Fn()>::value);
+ {
+ // Bullet 4
+ static_assert(std::is_callable<Fn(Tag&)>::value);
+ static_assert(std::is_callable<Fn(DerFromTag&)>::value);
+ static_assert(std::is_callable<Fn(Tag&&)>::value);
+ static_assert(std::is_callable<Fn(Tag const&)>::value);
+ }
+ {
+ // Bullet 5
+ using T = std::reference_wrapper<Tag>;
+ using DT = std::reference_wrapper<DerFromTag>;
+ using CT = std::reference_wrapper<const Tag>;
+ static_assert(std::is_callable<Fn(T&)>::value);
+ static_assert(std::is_callable<Fn(DT&)>::value);
+ static_assert(std::is_callable<Fn(const T&)>::value);
+ static_assert(std::is_callable<Fn(T&&)>::value);
+ static_assert(std::is_callable<Fn(CT&)>::value);
+ }
+ {
+ // Bullet 6
+ using T = Tag*;
+ using DT = DerFromTag*;
+ using CT = const Tag*;
+ using ST = std::unique_ptr<Tag>;
+ static_assert(std::is_callable<Fn(T&)>::value);
+ static_assert(std::is_callable<Fn(DT&)>::value);
+ static_assert(std::is_callable<Fn(const T&)>::value);
+ static_assert(std::is_callable<Fn(T&&)>::value);
+ static_assert(std::is_callable<Fn(ST)>::value);
+ static_assert(std::is_callable<Fn(CT&)>::value);
+ }
+ }
+ {
+ // INVOKE bullet 7
+ {
+ // Function pointer
+ using Fp = void(*)(Tag&, int);
+ static_assert(std::is_callable<Fp(Tag&, int)>::value);
+ static_assert(std::is_callable<Fp(DerFromTag&, int)>::value);
+ static_assert(!std::is_callable<Fp(const Tag&, int)>::value);
+ static_assert(!std::is_callable<Fp()>::value);
+ static_assert(!std::is_callable<Fp(Tag&)>::value);
+ }
+ {
+ // Function reference
+ using Fp = void(&)(Tag&, int);
+ static_assert(std::is_callable<Fp(Tag&, int)>::value);
+ static_assert(std::is_callable<Fp(DerFromTag&, int)>::value);
+ static_assert(!std::is_callable<Fp(const Tag&, int)>::value);
+ static_assert(!std::is_callable<Fp()>::value);
+ static_assert(!std::is_callable<Fp(Tag&)>::value);
+ }
+ {
+ // Function object
+ using Fn = NotCallableWithInt;
+ static_assert(std::is_callable<Fn(Tag)>::value, "");
+ static_assert(!std::is_callable<Fn(int)>::value, "");
+ }
+ }
+ {
+ // Check that the conversion to the return type is properly checked
+ using Fn = int(*)();
+ static_assert(std::is_callable<Fn(), Implicit>::value);
+ static_assert(std::is_callable<Fn(), double>::value);
+ static_assert(std::is_callable<Fn(), const volatile void>::value);
+ static_assert(!std::is_callable<Fn(), Explicit>::value);
+ }
+ {
+ // Check for is_callable_v
+ using Fn = void(*)();
+ static_assert(std::is_callable_v<Fn()>);
+ static_assert(!std::is_callable_v<Fn(int)>);
+ }
+}
diff --git a/libcxx/test/std/utilities/meta/meta.rel/is_nothrow_callable.pass.cpp b/libcxx/test/std/utilities/meta/meta.rel/is_nothrow_callable.pass.cpp
new file mode 100644
index 00000000000..c36a460af34
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.rel/is_nothrow_callable.pass.cpp
@@ -0,0 +1,115 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// type_traits
+
+// is_nothrow_callable
+
+#include <type_traits>
+#include <functional>
+
+#include "test_macros.h"
+
+struct Tag {};
+
+struct Implicit {
+ Implicit(int) noexcept {}
+};
+
+struct ThrowsImplicit {
+ ThrowsImplicit(int) {}
+};
+
+struct Explicit {
+ explicit Explicit(int) noexcept {}
+};
+
+template <bool IsNoexcept, class Ret, class ...Args>
+struct CallObject {
+ Ret operator()(Args&&...) const noexcept(IsNoexcept);
+};
+
+template <class Fn>
+constexpr bool throws_callable() {
+ return std::is_callable<Fn>::value &&
+ !std::is_nothrow_callable<Fn>::value;
+}
+
+template <class Fn, class Ret>
+constexpr bool throws_callable() {
+ return std::is_callable<Fn, Ret>::value &&
+ !std::is_nothrow_callable<Fn, Ret>::value;
+}
+
+// FIXME(EricWF) Don't test the where noexcept is *not* part of the type system
+// once implementations have caught up.
+void test_noexcept_function_pointers()
+{
+ struct Dummy { void foo() noexcept; static void bar() noexcept; };
+#if !defined(__cpp_noexcept_function_type)
+ {
+ // Check that PMF's and function pointers *work*. is_nothrow_callable will always
+ // return false because 'noexcept' is not part of the function type.
+ static_assert(throws_callable<decltype(&Dummy::foo)(Dummy&)>());
+ static_assert(throws_callable<decltype(&Dummy::bar)()>());
+ }
+#else
+ {
+ // Check that PMF's and function pointers actually work and that
+ // is_nothrow_callable returns true for noexcept PMF's and function
+ // pointers.
+ static_assert(std::is_nothrow_callable<decltype(&Dummy::foo)(Dummy&)>::value);
+ static_assert(std::is_nothrow_callable<decltype(&Dummy::bar)()>::value);
+ }
+#endif
+}
+
+int main()
+{
+ {
+ // Check that the conversion to the return type is properly checked
+ using Fn = CallObject<true, int>;
+ static_assert(std::is_nothrow_callable<Fn(), Implicit>::value);
+ static_assert(std::is_nothrow_callable<Fn(), double>::value);
+ static_assert(std::is_nothrow_callable<Fn(), const volatile void>::value);
+ static_assert(throws_callable<Fn(), ThrowsImplicit>());
+ static_assert(!std::is_nothrow_callable<Fn(), Explicit>());
+ }
+ {
+ // Check that the conversion to the parameters is properly checked
+ using Fn = CallObject<true, void, const Implicit&, const ThrowsImplicit&>;
+ static_assert(std::is_nothrow_callable<Fn(Implicit&, ThrowsImplicit&)>::value);
+ static_assert(std::is_nothrow_callable<Fn(int, ThrowsImplicit&)>::value);
+ static_assert(throws_callable<Fn(int, int)>());
+ static_assert(!std::is_nothrow_callable<Fn()>::value);
+ }
+ {
+ // Check that the noexcept-ness of function objects is checked.
+ using Fn = CallObject<true, void>;
+ using Fn2 = CallObject<false, void>;
+ static_assert(std::is_nothrow_callable<Fn()>::value);
+ static_assert(throws_callable<Fn2()>());
+ }
+ {
+ // Check that PMD derefs are noexcept
+ using Fn = int (Tag::*);
+ static_assert(std::is_nothrow_callable<Fn(Tag&)>::value);
+ static_assert(std::is_nothrow_callable<Fn(Tag&), Implicit>::value);
+ static_assert(throws_callable<Fn(Tag&), ThrowsImplicit>());
+ }
+ {
+ // Check for is_nothrow_callable_v
+ using Fn = CallObject<true, int>;
+ static_assert(std::is_nothrow_callable_v<Fn()>);
+ static_assert(!std::is_nothrow_callable_v<Fn(int)>);
+ }
+ test_noexcept_function_pointers();
+}
diff --git a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp
index 3ac7d1bc9df..fc01b22c36a 100644
--- a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp
@@ -45,6 +45,10 @@ struct HasType<T, typename Voider<typename T::type>::type> : std::true_type {};
template <class T, class U>
void test_result_of()
{
+#if TEST_STD_VER > 14
+ static_assert(std::is_callable<T>::value, "");
+ static_assert(std::is_callable<T, U>::value, "");
+#endif
static_assert((std::is_same<typename std::result_of<T>::type, U>::value), "");
}
@@ -54,6 +58,9 @@ void test_no_result()
#if TEST_STD_VER >= 11
static_assert((!HasType<std::result_of<T> >::value), "");
#endif
+#if TEST_STD_VER > 14
+ static_assert(std::is_callable<T>::value == false, "");
+#endif
}
int main()
diff --git a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp
index a00887384d4..8cb5853bbc6 100644
--- a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp
@@ -35,6 +35,10 @@ void test_result_of_imp()
#if TEST_STD_VER > 11
static_assert((std::is_same<std::result_of_t<T>, U>::value), "");
#endif
+#if TEST_STD_VER > 14
+ static_assert(std::is_callable<T>::value, "");
+ static_assert(std::is_callable<T, U>::value, "");
+#endif
}
int main()
OpenPOWER on IntegriCloud