diff options
5 files changed, 112 insertions, 36 deletions
diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index 4179cd1ed37..e9f6c014e2a 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -1537,42 +1537,56 @@ template <class _Tp> 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 <typename _Tp> +struct __is_destructor_wellformed { + template <typename _Tp1, typename _Tp2 = decltype(_VSTD::declval<_Tp1&>().~_Tp1())> + static char __test (int); + + template <typename _Tp1> + static __two __test (...); + + static const bool value = sizeof(__test<_Tp>(12)) == sizeof(char); + }; + +template <class _Tp, bool> +struct __destructible_imp; + template <class _Tp> -struct __destructible_test -{ - _Tp __t; -}; +struct __destructible_imp<_Tp, false> + : public _VSTD::integral_constant<bool, + __is_destructor_wellformed<typename _VSTD::remove_all_extents<_Tp>::type>::value> {}; template <class _Tp> -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 <class _Tp, bool> +struct __destructible_false; -template <class _Tp, bool = is_void<_Tp>::value || is_abstract<_Tp>::value - || is_function<_Tp>::value> -struct __destructible_imp - : public common_type - < - decltype(__is_destructible_test(declval<_Tp>())) - >::type {}; +template <class _Tp> +struct __destructible_false<_Tp, false> : public __destructible_imp<_Tp, _VSTD::is_reference<_Tp>::value> {}; template <class _Tp> -struct __destructible_imp<_Tp, true> - : public false_type {}; +struct __destructible_false<_Tp, true> : public _VSTD::false_type {}; template <class _Tp> struct is_destructible - : public __destructible_imp<_Tp> {}; + : public __destructible_false<_Tp, _VSTD::is_function<_Tp>::value> {}; template <class _Tp> struct is_destructible<_Tp[]> - : public false_type {}; + : public _VSTD::false_type {}; + +template <> +struct is_destructible<void> + : 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 0753ab7bcaa..2b8f7efec60 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 <class T> void test_is_constructible() { @@ -71,4 +81,6 @@ int main() test_is_not_constructible<A, void> (); test_is_not_constructible<void> (); test_is_not_constructible<int&> (); + test_is_not_constructible<Abstract> (); + test_is_not_constructible<AbstractDestructor> (); } 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 5cabb381db5..807745ef66c 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<const volatile T>::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<A>(); @@ -72,10 +90,30 @@ int main() test_is_destructible<char[3]>(); test_is_destructible<bit_zero>(); test_is_destructible<int[3]>(); + test_is_destructible<ProtectedAbstract>(); + test_is_destructible<PublicAbstract>(); + test_is_destructible<PrivateAbstract>(); + test_is_destructible<PublicDestructor>(); + test_is_destructible<VirtualPublicDestructor>(); + test_is_destructible<PurePublicDestructor>(); test_is_not_destructible<int[]>(); test_is_not_destructible<void>(); - test_is_not_destructible<Abstract>(); + + test_is_not_destructible<ProtectedDestructor>(); + test_is_not_destructible<PrivateDestructor>(); + test_is_not_destructible<VirtualProtectedDestructor>(); + test_is_not_destructible<VirtualPrivateDestructor>(); + test_is_not_destructible<PureProtectedDestructor>(); + test_is_not_destructible<PurePrivateDestructor>(); + test_is_not_destructible<DeletedPublicDestructor>(); + test_is_not_destructible<DeletedProtectedDestructor>(); + test_is_not_destructible<DeletedPrivateDestructor>(); + +// test_is_not_destructible<DeletedVirtualPublicDestructor>(); // currently fails due to clang bug #20268 + test_is_not_destructible<DeletedVirtualProtectedDestructor>(); + test_is_not_destructible<DeletedVirtualPrivateDestructor>(); + #if __has_feature(cxx_access_control_sfinae) test_is_not_destructible<NotEmpty>(); #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 a513d52f933..78717329af8 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<void>(); - test_has_not_nothrow_destructor<Abstract>(); + test_has_not_nothrow_destructor<AbstractDestructor>(); test_has_not_nothrow_destructor<NotEmpty>(); #if __has_feature(cxx_noexcept) @@ -79,6 +84,7 @@ int main() test_is_nothrow_destructible<const int*>(); test_is_nothrow_destructible<char[3]>(); test_is_nothrow_destructible<char[3]>(); + test_is_nothrow_destructible<Abstract>(); #if __has_feature(cxx_noexcept) test_is_nothrow_destructible<bit_zero>(); #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 ebe10e32009..1b34885ef99 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<void>(); test_has_not_trivial_destructor<A>(); - test_has_not_trivial_destructor<Abstract>(); + test_has_not_trivial_destructor<AbstractDestructor>(); test_has_not_trivial_destructor<NotEmpty>(); + test_is_trivially_destructible<Abstract>(); test_is_trivially_destructible<int&>(); test_is_trivially_destructible<Union>(); test_is_trivially_destructible<Empty>(); |