diff options
author | ville <ville@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-05-17 13:54:23 +0000 |
---|---|---|
committer | ville <ville@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-05-17 13:54:23 +0000 |
commit | b4d90ee21694777d1558cc9d2d29ac82cb7b168c (patch) | |
tree | 5dba2cc1db7a08d1f9a5a4c2c53436d4d65bed2e /libstdc++-v3 | |
parent | a1dda1ac8b4c9de64cfd4f709f5c04d256ea74b1 (diff) | |
download | gcc-b4d90ee21694777d1558cc9d2d29ac82cb7b168c.tar.gz |
Implement new C++ intrinsics __is_assignable and __is_constructible.
c-family/
Implement new C++ intrinsics __is_assignable and __is_constructible.
* c-common.c (__is_assignable, __is_constructible): New.
* c-common.h (RID_IS_ASSIGNABLE, RID_IS_CONSTRUCTIBLE): Likewise.
cp/
PR c++/80654
PR c++/80682
Implement new C++ intrinsics __is_assignable and __is_constructible.
* cp-tree.h (CPTK_IS_ASSIGNABLE, CPTK_IS_CONSTRUCTIBLE): New.
(is_xible): New.
* cxx-pretty-print.c (pp_cxx_trait_expression): Handle
CPTK_IS_ASSIGNABLE and CPTK_IS_CONSTRUCTIBLE.
* method.c (constructible_expr): Set cp_unevaluated.
(is_xible_helper): New.
(is_trivially_xible): Adjust.
(is_xible): New.
* parser.c (cp_parser_primary_expression): Handle
RID_IS_ASSIGNABLE and RID_IS_CONSTRUCTIBLE.
(cp_parser_trait_expr): Likewise.
* semantics.c (trait_expr_value): Handle
CPTK_IS_ASSIGNABLE and CPTK_IS_CONSTRUCTIBLE.
testsuite/
* g++.dg/ext/80654.C: New.
libstdc++-v3/
Implement new C++ intrinsics __is_assignable and __is_constructible.
* include/std/type_traits (__do_is_static_castable_impl): Remove.
(__is_static_castable_impl, __is_static_castable_safe): Likewise.
(__is_static_castable, __do_is_direct_constructible_impl): Likewise.
(__is_direct_constructible_impl): Likewise.
(__is_direct_constructible_new_safe): Likewise.
(__is_base_to_derived_ref, __is_lvalue_to_rvalue_ref): Likewise.
(__is_direct_constructible_ref_cast): Likewise.
(__is_direct_constructible_new, __is_direct_constructible): Likewise.
(__do_is_nary_constructible_impl): Likewise.
(__is_nary_constructible_impl, __is_nary_constructible): Likewise.
(__is_constructible_impl): Likewise.
(is_constructible): Call the intrinsic.
(__is_assignable_helper): Remove.
(is_assignable): Call the intrinsic.
(is_trivially_constructible): Likewise.
(__is_trivially_copy_constructible_impl): New.
(is_trivially_copy_constructible): Use it.
(__is_trivially_move_constructible_impl): New.
(is_trivially_move_constructible): Use it.
(is_trivially_assignable): Call the intrinsic.
(__is_trivially_copy_assignable_impl): New.
(is_trivially_copy_assignable): Use it.
(__is_trivially_move_assignable_impl): New.
(is_trivially_move_assignable): Use it.
(testsuite/20_util/declval/requirements/1_neg.cc): Adjust.
(testsuite/20_util/is_trivially_copy_assignable/value.cc):
Add test for void.
(testsuite/20_util/is_trivially_copy_constructible/value.cc): Likewise.
(testsuite/20_util/is_trivially_move_assignable/value.cc): Likewise.
(testsuite/20_util/is_trivially_move_constructible/value.cc): Likewise.
(testsuite/20_util/make_signed/requirements/typedefs_neg.cc): Adjust.
(testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc):
Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@248153 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3')
9 files changed, 109 insertions, 234 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index c32dc62abca..98d363acc2e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,40 @@ +2017-05-17 Ville Voutilainen <ville.voutilainen@gmail.com> + + Implement new C++ intrinsics __is_assignable and __is_constructible. + * include/std/type_traits (__do_is_static_castable_impl): Remove. + (__is_static_castable_impl, __is_static_castable_safe): Likewise. + (__is_static_castable, __do_is_direct_constructible_impl): Likewise. + (__is_direct_constructible_impl): Likewise. + (__is_direct_constructible_new_safe): Likewise. + (__is_base_to_derived_ref, __is_lvalue_to_rvalue_ref): Likewise. + (__is_direct_constructible_ref_cast): Likewise. + (__is_direct_constructible_new, __is_direct_constructible): Likewise. + (__do_is_nary_constructible_impl): Likewise. + (__is_nary_constructible_impl, __is_nary_constructible): Likewise. + (__is_constructible_impl): Likewise. + (is_constructible): Call the intrinsic. + (__is_assignable_helper): Remove. + (is_assignable): Call the intrinsic. + (is_trivially_constructible): Likewise. + (__is_trivially_copy_constructible_impl): New. + (is_trivially_copy_constructible): Use it. + (__is_trivially_move_constructible_impl): New. + (is_trivially_move_constructible): Use it. + (is_trivially_assignable): Call the intrinsic. + (__is_trivially_copy_assignable_impl): New. + (is_trivially_copy_assignable): Use it. + (__is_trivially_move_assignable_impl): New. + (is_trivially_move_assignable): Use it. + (testsuite/20_util/declval/requirements/1_neg.cc): Adjust. + (testsuite/20_util/is_trivially_copy_assignable/value.cc): + Add test for void. + (testsuite/20_util/is_trivially_copy_constructible/value.cc): Likewise. + (testsuite/20_util/is_trivially_move_assignable/value.cc): Likewise. + (testsuite/20_util/is_trivially_move_constructible/value.cc): Likewise. + (testsuite/20_util/make_signed/requirements/typedefs_neg.cc): Adjust. + (testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc): + Likewise. + 2017-05-16 Jonathan Wakely <jwakely@redhat.com> * testsuite/experimental/source_location/1.cc: Change expected result diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index aac7cff6cf6..390b6f40af5 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -924,213 +924,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __is_default_constructible_safe<_Tp>::type { }; - - // Implementation of is_constructible. - - // The hardest part of this trait is the binary direct-initialization - // case, because we hit into a functional cast of the form T(arg). - // This implementation uses different strategies depending on the - // target type to reduce the test overhead as much as possible: - // - // a) For a reference target type, we use a static_cast expression - // modulo its extra cases. - // - // b) For a non-reference target type we use a ::new expression. - struct __do_is_static_castable_impl - { - template<typename _From, typename _To, typename - = decltype(static_cast<_To>(declval<_From>()))> - static true_type __test(int); - - template<typename, typename> - static false_type __test(...); - }; - - template<typename _From, typename _To> - struct __is_static_castable_impl - : public __do_is_static_castable_impl - { - typedef decltype(__test<_From, _To>(0)) type; - }; - - template<typename _From, typename _To> - struct __is_static_castable_safe - : public __is_static_castable_impl<_From, _To>::type - { }; - - // __is_static_castable - template<typename _From, typename _To> - struct __is_static_castable - : public integral_constant<bool, (__is_static_castable_safe< - _From, _To>::value)> - { }; - - // Implementation for non-reference types. To meet the proper - // variable definition semantics, we also need to test for - // is_destructible in this case. - // This form should be simplified by a single expression: - // ::delete ::new _Tp(declval<_Arg>()), see c++/51222. - struct __do_is_direct_constructible_impl - { - template<typename _Tp, typename _Arg, typename - = decltype(::new _Tp(declval<_Arg>()))> - static true_type __test(int); - - template<typename, typename> - static false_type __test(...); - }; - - template<typename _Tp, typename _Arg> - struct __is_direct_constructible_impl - : public __do_is_direct_constructible_impl - { - typedef decltype(__test<_Tp, _Arg>(0)) type; - }; - - template<typename _Tp, typename _Arg> - struct __is_direct_constructible_new_safe - : public __and_<is_destructible<_Tp>, - __is_direct_constructible_impl<_Tp, _Arg>> - { }; - - template<typename, typename> - struct is_same; - - template<typename, typename> - struct is_base_of; - - template<typename> - struct remove_reference; - - template<typename _From, typename _To, bool - = __not_<__or_<is_void<_From>, - is_function<_From>>>::value> - struct __is_base_to_derived_ref; - - template<typename _Tp, typename... _Args> - struct is_constructible; - - // Detect whether we have a downcast situation during - // reference binding. - template<typename _From, typename _To> - struct __is_base_to_derived_ref<_From, _To, true> - { - typedef typename remove_cv<typename remove_reference<_From - >::type>::type __src_t; - typedef typename remove_cv<typename remove_reference<_To - >::type>::type __dst_t; - typedef __and_<__not_<is_same<__src_t, __dst_t>>, - is_base_of<__src_t, __dst_t>, - __not_<is_constructible<__dst_t, _From>>> type; - static constexpr bool value = type::value; - }; - - template<typename _From, typename _To> - struct __is_base_to_derived_ref<_From, _To, false> - : public false_type - { }; - - template<typename _From, typename _To, bool - = __and_<is_lvalue_reference<_From>, - is_rvalue_reference<_To>>::value> - struct __is_lvalue_to_rvalue_ref; - - // Detect whether we have an lvalue of non-function type - // bound to a reference-compatible rvalue-reference. - template<typename _From, typename _To> - struct __is_lvalue_to_rvalue_ref<_From, _To, true> - { - typedef typename remove_cv<typename remove_reference< - _From>::type>::type __src_t; - typedef typename remove_cv<typename remove_reference< - _To>::type>::type __dst_t; - typedef __and_<__not_<is_function<__src_t>>, - __or_<is_same<__src_t, __dst_t>, - is_base_of<__dst_t, __src_t>>> type; - static constexpr bool value = type::value; - }; - - template<typename _From, typename _To> - struct __is_lvalue_to_rvalue_ref<_From, _To, false> - : public false_type - { }; - - // Here we handle direct-initialization to a reference type as - // equivalent to a static_cast modulo overshooting conversions. - // These are restricted to the following conversions: - // a) A base class value to a derived class reference - // b) An lvalue to an rvalue-reference of reference-compatible - // types that are not functions - template<typename _Tp, typename _Arg> - struct __is_direct_constructible_ref_cast - : public __and_<__is_static_castable<_Arg, _Tp>, - __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>, - __is_lvalue_to_rvalue_ref<_Arg, _Tp> - >>> - { }; - - template<typename _Tp, typename _Arg> - struct __is_direct_constructible_new - : public conditional<is_reference<_Tp>::value, - __is_direct_constructible_ref_cast<_Tp, _Arg>, - __is_direct_constructible_new_safe<_Tp, _Arg> - >::type - { }; - - template<typename _Tp, typename _Arg> - struct __is_direct_constructible - : public __is_direct_constructible_new<_Tp, _Arg>::type - { }; - - // Since default-construction and binary direct-initialization have - // been handled separately, the implementation of the remaining - // n-ary construction cases is rather straightforward. We can use - // here a functional cast, because array types are excluded anyway - // and this form is never interpreted as a C cast. - struct __do_is_nary_constructible_impl - { - template<typename _Tp, typename... _Args, typename - = decltype(_Tp(declval<_Args>()...))> - static true_type __test(int); - - template<typename, typename...> - static false_type __test(...); - }; - - template<typename _Tp, typename... _Args> - struct __is_nary_constructible_impl - : public __do_is_nary_constructible_impl - { - typedef decltype(__test<_Tp, _Args...>(0)) type; - }; - - template<typename _Tp, typename... _Args> - struct __is_nary_constructible - : public __is_nary_constructible_impl<_Tp, _Args...>::type - { - static_assert(sizeof...(_Args) > 1, - "Only useful for > 1 arguments"); - }; - - template<typename _Tp, typename... _Args> - struct __is_constructible_impl - : public __is_nary_constructible<_Tp, _Args...> - { }; - - template<typename _Tp, typename _Arg> - struct __is_constructible_impl<_Tp, _Arg> - : public __is_direct_constructible<_Tp, _Arg> - { }; - - template<typename _Tp> - struct __is_constructible_impl<_Tp> - : public is_default_constructible<_Tp> - { }; - /// is_constructible template<typename _Tp, typename... _Args> struct is_constructible - : public __is_constructible_impl<_Tp, _Args...>::type + : public __bool_constant<__is_constructible(_Tp, _Args...)> { }; template<typename _Tp, bool = __is_referenceable<_Tp>::value> @@ -1255,26 +1052,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __is_nothrow_move_constructible_impl<_Tp> { }; - template<typename _Tp, typename _Up> - class __is_assignable_helper - { - template<typename _Tp1, typename _Up1, - typename = decltype(declval<_Tp1>() = declval<_Up1>())> - static true_type - __test(int); - - template<typename, typename> - static false_type - __test(...); - - public: - typedef decltype(__test<_Tp, _Up>(0)) type; - }; - /// is_assignable template<typename _Tp, typename _Up> struct is_assignable - : public __is_assignable_helper<_Tp, _Up>::type + : public __bool_constant<__is_assignable(_Tp, _Up)> { }; template<typename _Tp, bool = __is_referenceable<_Tp>::value> @@ -1364,8 +1145,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_trivially_constructible template<typename _Tp, typename... _Args> struct is_trivially_constructible - : public __and_<is_constructible<_Tp, _Args...>, integral_constant<bool, - __is_trivially_constructible(_Tp, _Args...)>> + : public __bool_constant<__is_trivially_constructible(_Tp, _Args...)> { }; /// is_trivially_default_constructible @@ -1405,45 +1185,95 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { }; /// is_trivially_copy_constructible + + template<typename _Tp, bool = __is_referenceable<_Tp>::value> + struct __is_trivially_copy_constructible_impl; + template<typename _Tp> - struct is_trivially_copy_constructible + struct __is_trivially_copy_constructible_impl<_Tp, false> + : public false_type { }; + + template<typename _Tp> + struct __is_trivially_copy_constructible_impl<_Tp, true> : public __and_<is_copy_constructible<_Tp>, integral_constant<bool, __is_trivially_constructible(_Tp, const _Tp&)>> { }; + template<typename _Tp> + struct is_trivially_copy_constructible + : public __is_trivially_copy_constructible_impl<_Tp> + { }; + /// is_trivially_move_constructible + + template<typename _Tp, bool = __is_referenceable<_Tp>::value> + struct __is_trivially_move_constructible_impl; + template<typename _Tp> - struct is_trivially_move_constructible + struct __is_trivially_move_constructible_impl<_Tp, false> + : public false_type { }; + + template<typename _Tp> + struct __is_trivially_move_constructible_impl<_Tp, true> : public __and_<is_move_constructible<_Tp>, integral_constant<bool, __is_trivially_constructible(_Tp, _Tp&&)>> { }; + template<typename _Tp> + struct is_trivially_move_constructible + : public __is_trivially_move_constructible_impl<_Tp> + { }; + /// is_trivially_assignable template<typename _Tp, typename _Up> struct is_trivially_assignable - : public __and_<is_assignable<_Tp, _Up>, - integral_constant<bool, - __is_trivially_assignable(_Tp, _Up)>> + : public __bool_constant<__is_trivially_assignable(_Tp, _Up)> { }; /// is_trivially_copy_assignable + + template<typename _Tp, bool = __is_referenceable<_Tp>::value> + struct __is_trivially_copy_assignable_impl; + template<typename _Tp> - struct is_trivially_copy_assignable + struct __is_trivially_copy_assignable_impl<_Tp, false> + : public false_type { }; + + template<typename _Tp> + struct __is_trivially_copy_assignable_impl<_Tp, true> : public __and_<is_copy_assignable<_Tp>, integral_constant<bool, __is_trivially_assignable(_Tp&, const _Tp&)>> { }; + template<typename _Tp> + struct is_trivially_copy_assignable + : public __is_trivially_copy_assignable_impl<_Tp> + { }; + /// is_trivially_move_assignable + + template<typename _Tp, bool = __is_referenceable<_Tp>::value> + struct __is_trivially_move_assignable_impl; + template<typename _Tp> - struct is_trivially_move_assignable + struct __is_trivially_move_assignable_impl<_Tp, false> + : public false_type { }; + + template<typename _Tp> + struct __is_trivially_move_assignable_impl<_Tp, true> : public __and_<is_move_assignable<_Tp>, integral_constant<bool, __is_trivially_assignable(_Tp&, _Tp&&)>> { }; + template<typename _Tp> + struct is_trivially_move_assignable + : public __is_trivially_move_assignable_impl<_Tp> + { }; + /// is_trivially_destructible template<typename _Tp> struct is_trivially_destructible diff --git a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc index dc9daeb42ce..4e254e89191 100644 --- a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc +++ b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc @@ -18,7 +18,7 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// { dg-error "static assertion failed" "" { target *-*-* } 2259 } +// { dg-error "static assertion failed" "" { target *-*-* } 2089 } #include <utility> diff --git a/libstdc++-v3/testsuite/20_util/is_trivially_copy_assignable/value.cc b/libstdc++-v3/testsuite/20_util/is_trivially_copy_assignable/value.cc index b002246dfd5..902aa5e5932 100644 --- a/libstdc++-v3/testsuite/20_util/is_trivially_copy_assignable/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_trivially_copy_assignable/value.cc @@ -88,4 +88,6 @@ void test01() MoveOnly>(false), ""); static_assert(test_property<is_trivially_copy_assignable, MoveOnly2>(false), ""); + static_assert(test_property<is_trivially_copy_assignable, + void>(false), ""); } diff --git a/libstdc++-v3/testsuite/20_util/is_trivially_copy_constructible/value.cc b/libstdc++-v3/testsuite/20_util/is_trivially_copy_constructible/value.cc index 845e0586151..627410bdc30 100644 --- a/libstdc++-v3/testsuite/20_util/is_trivially_copy_constructible/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_trivially_copy_constructible/value.cc @@ -82,4 +82,6 @@ void test01() MoveOnly>(false), ""); static_assert(test_property<is_trivially_copy_constructible, MoveOnly2>(false), ""); + static_assert(test_property<is_trivially_copy_constructible, + void>(false), ""); } diff --git a/libstdc++-v3/testsuite/20_util/is_trivially_move_assignable/value.cc b/libstdc++-v3/testsuite/20_util/is_trivially_move_assignable/value.cc index 68833b67f12..221048347a2 100644 --- a/libstdc++-v3/testsuite/20_util/is_trivially_move_assignable/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_trivially_move_assignable/value.cc @@ -88,4 +88,6 @@ void test01() MoveOnly>(true), ""); static_assert(test_property<is_trivially_move_assignable, MoveOnly2>(false), ""); + static_assert(test_property<is_trivially_move_assignable, + void>(false), ""); } diff --git a/libstdc++-v3/testsuite/20_util/is_trivially_move_constructible/value.cc b/libstdc++-v3/testsuite/20_util/is_trivially_move_constructible/value.cc index ad6045bda81..9a21b6e2133 100644 --- a/libstdc++-v3/testsuite/20_util/is_trivially_move_constructible/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_trivially_move_constructible/value.cc @@ -82,4 +82,6 @@ void test01() MoveOnly>(true), ""); static_assert(test_property<is_trivially_move_constructible, MoveOnly2>(false), ""); + static_assert(test_property<is_trivially_move_constructible, + void>(false), ""); } diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc index 664fb70fb4b..e3e80f91979 100644 --- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc +++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc @@ -47,4 +47,4 @@ void test01() // { dg-error "required from here" "" { target *-*-* } 39 } // { dg-error "required from here" "" { target *-*-* } 41 } -// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1924 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1754 } diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc index 6d6471755f7..86b0c2d6da7 100644 --- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc +++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc @@ -47,5 +47,5 @@ void test01() // { dg-error "required from here" "" { target *-*-* } 39 } // { dg-error "required from here" "" { target *-*-* } 41 } -// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1820 } -// { dg-error "declaration of" "" { target *-*-* } 1777 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1650 } + |