From 22f1f4c790759674d47b704e0faa140343e542d5 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 31 May 2018 13:18:19 +0100 Subject: [PATCH] PR libstdc++/85951 for make_signed/make_unsigned for character types Because the wide character types are neither signed integer types nor unsigned integer types they need to be transformed to an integral type of the correct size and the lowest rank (which is not necessarily the underlying type). Reuse the helpers for enumeration types to select the correct integer. The refactoring of __make_unsigned_selector and __make_signed_selector slightly reduces the number of template instantiations and so reduces memory usage. PR libstdc++/85951 * include/std/type_traits [_GLIBCXX_USE_C99_STDINT_TR1]: Do not define uint_least16_t and uint_least32_t. (__make_unsigned): Define unconditionally. (__make_unsigned_selector<_Tp, true, false>): Remove intermediate typedefs. (__make_unsigned_selector_base): New type to provide helper templates. (__make_unsigned_selector<_Tp, false, true>): Reimplement using __make_unsigned_selector_base helpers. (__make_unsigned, __make_unsigned): Define. (__make_signed_selector<_Tp, true, false>): Remove intermediate typedefs. (__make_signed, __make_signed) (__make_signed)): Define unconditionally. * testsuite/20_util/make_signed/requirements/typedefs-3.cc: Check wchar_t, char16_t and char32_t are transformed correctly. * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Adjust dg-error lineno. * testsuite/20_util/make_unsigned/requirements/typedefs-3.cc: Check wchar_t, char16_t and char32_t are transformed correctly. * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc: Adjust dg-error lineno. From-SVN: r261023 --- libstdc++-v3/ChangeLog | 25 ++++ libstdc++-v3/include/std/type_traits | 150 +++++++++++++-------- .../20_util/make_signed/requirements/typedefs-3.cc | 15 ++- .../make_signed/requirements/typedefs_neg.cc | 4 +- .../make_unsigned/requirements/typedefs-3.cc | 15 ++- .../make_unsigned/requirements/typedefs_neg.cc | 4 +- 6 files changed, 150 insertions(+), 63 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 762de9a..8735cac 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,28 @@ +2018-05-31 Jonathan Wakely + + PR libstdc++/85951 + * include/std/type_traits [_GLIBCXX_USE_C99_STDINT_TR1]: Do not define + uint_least16_t and uint_least32_t. + (__make_unsigned): Define unconditionally. + (__make_unsigned_selector<_Tp, true, false>): Remove intermediate + typedefs. + (__make_unsigned_selector_base): New type to provide helper templates. + (__make_unsigned_selector<_Tp, false, true>): Reimplement using + __make_unsigned_selector_base helpers. + (__make_unsigned, __make_unsigned): Define. + (__make_signed_selector<_Tp, true, false>): Remove intermediate + typedefs. + (__make_signed, __make_signed) + (__make_signed)): Define unconditionally. + * testsuite/20_util/make_signed/requirements/typedefs-3.cc: Check + wchar_t, char16_t and char32_t are transformed correctly. + * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Adjust + dg-error lineno. + * testsuite/20_util/make_unsigned/requirements/typedefs-3.cc: Check + wchar_t, char16_t and char32_t are transformed correctly. + * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc: Adjust + dg-error lineno. + 2018-05-29 Jonathan Wakely * include/std/variant (__erased_dtor): Qualify call to __get. diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 7c0ba72..4397c48 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -37,18 +37,6 @@ #include -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 -# if defined (__UINT_LEAST16_TYPE__) && defined(__UINT_LEAST32_TYPE__) -namespace std -{ - typedef __UINT_LEAST16_TYPE__ uint_least16_t; - typedef __UINT_LEAST32_TYPE__ uint_least32_t; -} -# else -# include -# endif -#endif - namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -1576,12 +1564,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __make_unsigned { typedef unsigned long long __type; }; -#if defined(_GLIBCXX_USE_WCHAR_T) && !defined(__WCHAR_UNSIGNED__) - template<> - struct __make_unsigned : __make_unsigned<__WCHAR_TYPE__> - { }; -#endif - #if defined(__GLIBCXX_TYPE_INT_N_0) template<> struct __make_unsigned<__GLIBCXX_TYPE_INT_N_0> @@ -1612,36 +1594,77 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template class __make_unsigned_selector<_Tp, true, false> { - typedef __make_unsigned::type> __unsignedt; - typedef typename __unsignedt::__type __unsigned_type; - typedef __match_cv_qualifiers<_Tp, __unsigned_type> __cv_unsigned; + using __unsigned_type + = typename __make_unsigned::type>::__type; public: - typedef typename __cv_unsigned::__type __type; + using __type + = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type; }; + class __make_unsigned_selector_base + { + protected: + template struct _List { }; + + template + struct _List<_Tp, _Up...> : _List<_Up...> + { static constexpr size_t __size = sizeof(_Tp); }; + + template + struct __select; + + template + struct __select<_Sz, _List<_Uint, _UInts...>, true> + { using __type = _Uint; }; + + template + struct __select<_Sz, _List<_Uint, _UInts...>, false> + : __select<_Sz, _List<_UInts...>> + { }; + }; + + // Choose unsigned integer type with the smallest rank and same size as _Tp template class __make_unsigned_selector<_Tp, false, true> + : __make_unsigned_selector_base { // With -fshort-enums, an enum may be as small as a char. - typedef unsigned char __smallest; - static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest); - static const bool __b1 = sizeof(_Tp) <= sizeof(unsigned short); - static const bool __b2 = sizeof(_Tp) <= sizeof(unsigned int); - static const bool __b3 = sizeof(_Tp) <= sizeof(unsigned long); - typedef conditional<__b3, unsigned long, unsigned long long> __cond3; - typedef typename __cond3::type __cond3_type; - typedef conditional<__b2, unsigned int, __cond3_type> __cond2; - typedef typename __cond2::type __cond2_type; - typedef conditional<__b1, unsigned short, __cond2_type> __cond1; - typedef typename __cond1::type __cond1_type; - - typedef typename conditional<__b0, __smallest, __cond1_type>::type - __unsigned_type; - typedef __match_cv_qualifiers<_Tp, __unsigned_type> __cv_unsigned; + using _UInts = _List; + + using __unsigned_type = typename __select::__type; public: - typedef typename __cv_unsigned::__type __type; + using __type + = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type; + }; + + // wchar_t, char16_t and char32_t are integral types but are neither + // signed integer types not unsigned integer types, so must be + // transformed to the unsigned integer type with the smallest rank. + // Use the partial specialization for enumeration types to do that. +#if defined(_GLIBCXX_USE_WCHAR_T) + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; +#endif + + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; + + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; }; // Given an integral/enum type, return the corresponding unsigned @@ -1686,21 +1709,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __make_signed { typedef signed long long __type; }; -#if defined(_GLIBCXX_USE_WCHAR_T) && defined(__WCHAR_UNSIGNED__) - template<> - struct __make_signed : __make_signed<__WCHAR_TYPE__> - { }; -#endif - -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 - template<> - struct __make_signed : __make_signed - { }; - template<> - struct __make_signed : __make_signed - { }; -#endif - #if defined(__GLIBCXX_TYPE_INT_N_0) template<> struct __make_signed @@ -1731,14 +1739,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template class __make_signed_selector<_Tp, true, false> { - typedef __make_signed::type> __signedt; - typedef typename __signedt::__type __signed_type; - typedef __match_cv_qualifiers<_Tp, __signed_type> __cv_signed; + using __signed_type + = typename __make_signed::type>::__type; public: - typedef typename __cv_signed::__type __type; + using __type + = typename __match_cv_qualifiers<_Tp, __signed_type>::__type; }; + // Choose signed integer type with the smallest rank and same size as _Tp template class __make_signed_selector<_Tp, false, true> { @@ -1748,6 +1757,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename __make_signed_selector<__unsigned_type>::__type __type; }; + // wchar_t, char16_t and char32_t are integral types but are neither + // signed integer types not unsigned integer types, so must be + // transformed to the signed integer type with the smallest rank. + // Use the partial specialization for enumeration types to do that. +#if defined(_GLIBCXX_USE_WCHAR_T) + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; +#endif + + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; + + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; + // Given an integral/enum type, return the corresponding signed // integer type. // Primary template. diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-3.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-3.cc index 3f50952..79e0a70 100644 --- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-3.cc +++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-3.cc @@ -59,8 +59,21 @@ using I4 = smallest_rank_t; static_assert(is_same::type, I4>::value, ""); static_assert(is_same::type, I4 const>::value, ""); -// PI libstdc++/60333 +// PR libstdc++/60333 enum E5 : long long { }; using I5 = smallest_rank_t; static_assert(is_same::type, I5>::value, ""); static_assert(is_same::type, I5 const>::value, ""); + +// PR libstdc++/85951 +using I6 = smallest_rank_t; +static_assert(is_same::type, I6>::value, ""); +static_assert(is_same::type, I6 const>::value, ""); +using I7 = smallest_rank_t; +static_assert(is_same::type, I7>::value, ""); +static_assert(is_same::type, I7 const>::value, ""); +#ifdef _GLIBCXX_USE_WCHAR_T +using I8 = smallest_rank_t; +static_assert(is_same::type, I8>::value, ""); +static_assert(is_same::type, I8 const>::value, ""); +#endif 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 8d46405..13bca19 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 @@ -28,7 +28,7 @@ void test01() { using std::make_signed; - // Negative tests. + // Negative tests. typedef make_signed::type test1_type; typedef make_signed<__gnu_test::pod_uint>::type test2_type; @@ -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 *-*-* } 1757 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1793 } diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-3.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-3.cc index c901b0e..895aa1c 100644 --- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-3.cc +++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-3.cc @@ -59,8 +59,21 @@ using I4 = smallest_rank_t; static_assert(is_same::type, I4>::value, ""); static_assert(is_same::type, I4 const>::value, ""); -// PI libstdc++/60333 +// PR libstdc++/60333 enum E5 : long long { }; using I5 = smallest_rank_t; static_assert(is_same::type, I5>::value, ""); static_assert(is_same::type, I5 const>::value, ""); + +// PR libstdc++/85951 +using I6 = smallest_rank_t; +static_assert(is_same::type, I6>::value, ""); +static_assert(is_same::type, I6 const>::value, ""); +using I7 = smallest_rank_t; +static_assert(is_same::type, I7>::value, ""); +static_assert(is_same::type, I7 const>::value, ""); +#ifdef _GLIBCXX_USE_WCHAR_T +using I8 = smallest_rank_t; +static_assert(is_same::type, I8>::value, ""); +static_assert(is_same::type, I8 const>::value, ""); +#endif 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 93ae157..9df0155 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 @@ -28,7 +28,7 @@ void test01() { using std::make_unsigned; - // Negative tests. + // Negative tests. typedef make_unsigned::type test1_type; typedef make_unsigned<__gnu_test::pod_uint>::type test2_type; @@ -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 *-*-* } 1653 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1676 } -- 2.7.4