On 31/05/18 13:17 +0100, Jonathan Wakely wrote:
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<wchar_t>): 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<char16_t>, __make_unsigned<char32_t>): Define.
(__make_signed_selector<_Tp, true, false>): Remove intermediate
typedefs.
(__make_signed<wchar_t>, __make_signed<char16_t>)
(__make_signed<char32_t>)): 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.
Tested powerpc64le-linux, committed to trunk.
I'll backport a simpler version without the refactoring.
This is the backport I'm committing to the branches. I forgot that one
of the reasons I did the refactoring was to avoid std::conditional,
which isn't defined yet and so can't be used by the new explicit
specializations of __make_unsigned and __make_signed. To solve that
problem on the branches I'll just put the new specializations later in
the file.
Tested x86_64-linux, committed to gcc-8-branch (and others to follow
soon).
commit a200d73247acdf8394574fe28250b7d3bf817576
Author: Jonathan Wakely <jwak...@redhat.com>
Date: Thu May 31 13:42:20 2018 +0100
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.
PR libstdc++/85951
* include/std/type_traits [_GLIBCXX_USE_C99_STDINT_TR1]: Do not define
uint_least16_t and uint_least32_t.
(__make_unsigned<wchar_t>): Define unconditionally.
(__make_unsigned<char16_t>, __make_unsigned<char32_t>): Define.
(__make_signed<wchar_t>, __make_signed<char16_t>)
(__make_signed<char32_t>)): 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.
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 711d6c50dd1..41607f63096 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -37,18 +37,6 @@
#include <bits/c++config.h>
-#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 <cstdint>
-# endif
-#endif
-
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -1576,12 +1564,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __make_unsigned<long long>
{ typedef unsigned long long __type; };
-#if defined(_GLIBCXX_USE_WCHAR_T) && !defined(__WCHAR_UNSIGNED__)
- template<>
- struct __make_unsigned<wchar_t> : __make_unsigned<__WCHAR_TYPE__>
- { };
-#endif
-
#if defined(__GLIBCXX_TYPE_INT_N_0)
template<>
struct __make_unsigned<__GLIBCXX_TYPE_INT_N_0>
@@ -1686,21 +1668,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __make_signed<unsigned long long>
{ typedef signed long long __type; };
-#if defined(_GLIBCXX_USE_WCHAR_T) && defined(__WCHAR_UNSIGNED__)
- template<>
- struct __make_signed<wchar_t> : __make_signed<__WCHAR_TYPE__>
- { };
-#endif
-
-#ifdef _GLIBCXX_USE_C99_STDINT_TR1
- template<>
- struct __make_signed<char16_t> : __make_signed<uint_least16_t>
- { };
- template<>
- struct __make_signed<char32_t> : __make_signed<uint_least32_t>
- { };
-#endif
-
#if defined(__GLIBCXX_TYPE_INT_N_0)
template<>
struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_0>
@@ -2092,6 +2059,59 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __declval<_Tp>(0);
}
+ // 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 integer type with the smallest rank that has the
+ // same size and signedness.
+ // Use the partial specialization for enumeration types to do that,
+ // which means these explicit specializations must be defined after
+ // std::conditional has been defined.
+
+#if defined(_GLIBCXX_USE_WCHAR_T)
+ template<>
+ struct __make_unsigned<wchar_t>
+ {
+ using __type
+ = typename __make_unsigned_selector<wchar_t, false, true>::__type;
+ };
+
+ template<>
+ struct __make_signed<wchar_t>
+ {
+ using __type
+ = typename __make_signed_selector<wchar_t, false, true>::__type;
+ };
+#endif
+
+ template<>
+ struct __make_unsigned<char16_t>
+ {
+ using __type
+ = typename __make_unsigned_selector<char16_t, false, true>::__type;
+ };
+
+ template<>
+ struct __make_signed<char16_t>
+ {
+ using __type
+ = typename __make_signed_selector<char16_t, false, true>::__type;
+ };
+
+ template<>
+ struct __make_unsigned<char32_t>
+ {
+ using __type
+ = typename __make_unsigned_selector<char32_t, false, true>::__type;
+ };
+
+ template<>
+ struct __make_signed<char32_t>
+ {
+ using __type
+ = typename __make_signed_selector<char32_t, false, true>::__type;
+ };
+
+
/// result_of
template<typename _Signature>
class result_of;
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 3f50952fa3f..79e0a700d09 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<E4>;
static_assert(is_same<make_signed<E4>::type, I4>::value, "");
static_assert(is_same<make_signed<E4 const>::type, I4 const>::value, "");
-// PI libstdc++/60333
+// PR libstdc++/60333
enum E5 : long long { };
using I5 = smallest_rank_t<E5>;
static_assert(is_same<make_signed<E5>::type, I5>::value, "");
static_assert(is_same<make_signed<E5 const>::type, I5 const>::value, "");
+
+// PR libstdc++/85951
+using I6 = smallest_rank_t<char16_t>;
+static_assert(is_same<make_signed<char16_t>::type, I6>::value, "");
+static_assert(is_same<make_signed<char16_t const>::type, I6 const>::value, "");
+using I7 = smallest_rank_t<char32_t>;
+static_assert(is_same<make_signed<char32_t>::type, I7>::value, "");
+static_assert(is_same<make_signed<char32_t const>::type, I7 const>::value, "");
+#ifdef _GLIBCXX_USE_WCHAR_T
+using I8 = smallest_rank_t<wchar_t>;
+static_assert(is_same<make_signed<wchar_t>::type, I8>::value, "");
+static_assert(is_same<make_signed<wchar_t const>::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 8d46405165e..fc05b35d842 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<bool>::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 *-*-* } 1724 }
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 c901b0e08b1..895aa1c59b9 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<E4>;
static_assert(is_same<make_unsigned<E4>::type, I4>::value, "");
static_assert(is_same<make_unsigned<E4 const>::type, I4 const>::value, "");
-// PI libstdc++/60333
+// PR libstdc++/60333
enum E5 : long long { };
using I5 = smallest_rank_t<E5>;
static_assert(is_same<make_unsigned<E5>::type, I5>::value, "");
static_assert(is_same<make_unsigned<E5 const>::type, I5 const>::value, "");
+
+// PR libstdc++/85951
+using I6 = smallest_rank_t<char16_t>;
+static_assert(is_same<make_unsigned<char16_t>::type, I6>::value, "");
+static_assert(is_same<make_unsigned<char16_t const>::type, I6 const>::value, "");
+using I7 = smallest_rank_t<char32_t>;
+static_assert(is_same<make_unsigned<char32_t>::type, I7>::value, "");
+static_assert(is_same<make_unsigned<char32_t const>::type, I7 const>::value, "");
+#ifdef _GLIBCXX_USE_WCHAR_T
+using I8 = smallest_rank_t<wchar_t>;
+static_assert(is_same<make_unsigned<wchar_t>::type, I8>::value, "");
+static_assert(is_same<make_unsigned<wchar_t const>::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 93ae15723cf..b07c3eebcc9 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<bool>::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 *-*-* } 1635 }