From f52c88f0150dcbd1b8de361ee3227221ad7a9b75 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Wed, 16 Jul 2014 15:51:50 +0000 Subject: [PATCH] Correctly implement LWG 2049; std::is_destructible. llvm-svn: 213163 --- libcxx/include/type_traits | 60 +++++++++++++--------- .../meta.unary.prop/is_constructible.pass.cpp | 12 +++++ .../meta.unary.prop/is_destructible.pass.cpp | 56 ++++++++++++++++---- .../is_nothrow_destructible.pass.cpp | 10 +++- .../is_trivially_destructible.pass.cpp | 10 +++- 5 files changed, 112 insertions(+), 36 deletions(-) diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index 4179cd1..e9f6c01 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -1537,42 +1537,56 @@ template struct _LIBCPP_TYPE_VIS_ONLY is_move_assignable // is_destructible +// if it's a reference, return true +// if it's a function, return false +// if it's void, return false +// if it's an array of unknown bound, return false +// Otherwise, return "std::declval<_Up&>().~_Up()" is well-formed +// where _Up is remove_all_extents<_Tp>::type + +template +struct __is_destructor_wellformed { + template ().~_Tp1())> + static char __test (int); + + template + static __two __test (...); + + static const bool value = sizeof(__test<_Tp>(12)) == sizeof(char); + }; + +template +struct __destructible_imp; + template -struct __destructible_test -{ - _Tp __t; -}; +struct __destructible_imp<_Tp, false> + : public _VSTD::integral_constant::type>::value> {}; template -decltype((_VSTD::declval<__destructible_test<_Tp> >().~__destructible_test<_Tp>(), true_type())) -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES -__is_destructible_test(_Tp&&); -#else -__is_destructible_test(_Tp&); -#endif +struct __destructible_imp<_Tp, true> + : public _VSTD::true_type {}; -false_type -__is_destructible_test(__any); +template +struct __destructible_false; -template ::value || is_abstract<_Tp>::value - || is_function<_Tp>::value> -struct __destructible_imp - : public common_type - < - decltype(__is_destructible_test(declval<_Tp>())) - >::type {}; +template +struct __destructible_false<_Tp, false> : public __destructible_imp<_Tp, _VSTD::is_reference<_Tp>::value> {}; template -struct __destructible_imp<_Tp, true> - : public false_type {}; +struct __destructible_false<_Tp, true> : public _VSTD::false_type {}; template struct is_destructible - : public __destructible_imp<_Tp> {}; + : public __destructible_false<_Tp, _VSTD::is_function<_Tp>::value> {}; template struct is_destructible<_Tp[]> - : public false_type {}; + : public _VSTD::false_type {}; + +template <> +struct is_destructible + : public _VSTD::false_type {}; // move diff --git a/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp b/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp index 0753ab7..2b8f7ef 100644 --- a/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp +++ b/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp @@ -24,6 +24,16 @@ private: A(char); }; +class Abstract +{ + virtual void foo() = 0; +}; + +class AbstractDestructor +{ + virtual ~AbstractDestructor() = 0; +}; + template void test_is_constructible() { @@ -71,4 +81,6 @@ int main() test_is_not_constructible (); test_is_not_constructible (); test_is_not_constructible (); + test_is_not_constructible (); + test_is_not_constructible (); } diff --git a/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_destructible.pass.cpp b/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_destructible.pass.cpp index 5cabb38..807745e 100644 --- a/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_destructible.pass.cpp +++ b/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_destructible.pass.cpp @@ -31,9 +31,7 @@ void test_is_not_destructible() static_assert(!std::is_destructible::value, ""); } -class Empty -{ -}; +class Empty {}; class NotEmpty { @@ -47,11 +45,6 @@ struct bit_zero int : 0; }; -class Abstract -{ - virtual ~Abstract() = 0; -}; - struct A { ~A(); @@ -59,6 +52,31 @@ struct A typedef void (Function) (); +struct PublicAbstract { public: virtual void foo() = 0; }; +struct ProtectedAbstract { protected: virtual void foo() = 0; }; +struct PrivateAbstract { private: virtual void foo() = 0; }; + +struct PublicDestructor { public: ~PublicDestructor() {}}; +struct ProtectedDestructor { protected: ~ProtectedDestructor() {}}; +struct PrivateDestructor { private: ~PrivateDestructor() {}}; + +struct VirtualPublicDestructor { public: virtual ~VirtualPublicDestructor() {}}; +struct VirtualProtectedDestructor { protected: virtual ~VirtualProtectedDestructor() {}}; +struct VirtualPrivateDestructor { private: virtual ~VirtualPrivateDestructor() {}}; + +struct PurePublicDestructor { public: virtual ~PurePublicDestructor() = 0; }; +struct PureProtectedDestructor { protected: virtual ~PureProtectedDestructor() = 0; }; +struct PurePrivateDestructor { private: virtual ~PurePrivateDestructor() = 0; }; + +struct DeletedPublicDestructor { public: ~DeletedPublicDestructor() = delete; }; +struct DeletedProtectedDestructor { protected: ~DeletedProtectedDestructor() = delete; }; +struct DeletedPrivateDestructor { private: ~DeletedPrivateDestructor() = delete; }; + +struct DeletedVirtualPublicDestructor { public: virtual ~DeletedVirtualPublicDestructor() = delete; }; +struct DeletedVirtualProtectedDestructor { protected: virtual ~DeletedVirtualProtectedDestructor() = delete; }; +struct DeletedVirtualPrivateDestructor { private: virtual ~DeletedVirtualPrivateDestructor() = delete; }; + + int main() { test_is_destructible(); @@ -72,10 +90,30 @@ int main() test_is_destructible(); test_is_destructible(); test_is_destructible(); + test_is_destructible(); + test_is_destructible(); + test_is_destructible(); + test_is_destructible(); + test_is_destructible(); + test_is_destructible(); test_is_not_destructible(); test_is_not_destructible(); - test_is_not_destructible(); + + test_is_not_destructible(); + test_is_not_destructible(); + test_is_not_destructible(); + test_is_not_destructible(); + test_is_not_destructible(); + test_is_not_destructible(); + test_is_not_destructible(); + test_is_not_destructible(); + test_is_not_destructible(); + +// test_is_not_destructible(); // currently fails due to clang bug #20268 + test_is_not_destructible(); + test_is_not_destructible(); + #if __has_feature(cxx_access_control_sfinae) test_is_not_destructible(); #endif diff --git a/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_destructible.pass.cpp b/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_destructible.pass.cpp index a513d52..7871732 100644 --- a/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_destructible.pass.cpp +++ b/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_destructible.pass.cpp @@ -49,7 +49,12 @@ struct bit_zero class Abstract { - virtual ~Abstract() = 0; + virtual void foo() = 0; +}; + +class AbstractDestructor +{ + virtual ~AbstractDestructor() = 0; }; struct A @@ -60,7 +65,7 @@ struct A int main() { test_has_not_nothrow_destructor(); - test_has_not_nothrow_destructor(); + test_has_not_nothrow_destructor(); test_has_not_nothrow_destructor(); #if __has_feature(cxx_noexcept) @@ -79,6 +84,7 @@ int main() test_is_nothrow_destructible(); test_is_nothrow_destructible(); test_is_nothrow_destructible(); + test_is_nothrow_destructible(); #if __has_feature(cxx_noexcept) test_is_nothrow_destructible(); #endif diff --git a/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_trivially_destructible.pass.cpp b/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_trivially_destructible.pass.cpp index ebe10e3..1b34885 100644 --- a/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_trivially_destructible.pass.cpp +++ b/libcxx/test/utilities/meta/meta.unary/meta.unary.prop/is_trivially_destructible.pass.cpp @@ -49,7 +49,12 @@ struct bit_zero class Abstract { - virtual ~Abstract() = 0; + virtual void foo() = 0; +}; + +class AbstractDestructor +{ + virtual ~AbstractDestructor() = 0; }; struct A @@ -61,9 +66,10 @@ int main() { test_has_not_trivial_destructor(); test_has_not_trivial_destructor(); - test_has_not_trivial_destructor(); + test_has_not_trivial_destructor(); test_has_not_trivial_destructor(); + test_is_trivially_destructible(); test_is_trivially_destructible(); test_is_trivially_destructible(); test_is_trivially_destructible(); -- 2.7.4