From c104e8f1b67a75ea82c62f1fd2aac69c09127562 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 7 Apr 2020 17:18:21 +0100 Subject: [PATCH] libstdc++: Restore ability to use in C++14 (PR 94520) This C++17 header is supported in C++14 as a GNU extension, but stopped working last year because I made it depend on an internal helper which is only defined for C++17 and up. PR libstdc++/94520 * include/std/charconv (__integer_to_chars_result_type) (__integer_from_chars_result_type): Use __or_ instead of __or_v_ to allow use in C++14. * testsuite/20_util/from_chars/1.cc: Run test as C++14 and replace use of std::string_view with std::string. * testsuite/20_util/from_chars/2.cc: Likewise. * testsuite/20_util/to_chars/1.cc: Likewise. * testsuite/20_util/to_chars/2.cc: Likewise. --- libstdc++-v3/ChangeLog | 12 ++ libstdc++-v3/include/std/charconv | 12 +- .../testsuite/20_util/from_chars/1.cc | 16 ++- .../testsuite/20_util/from_chars/2.cc | 130 +++++++++--------- libstdc++-v3/testsuite/20_util/to_chars/1.cc | 30 ++-- libstdc++-v3/testsuite/20_util/to_chars/2.cc | 4 +- 6 files changed, 112 insertions(+), 92 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4d7b5780189..b95a89373db 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,15 @@ +2020-04-07 Jonathan Wakely + + PR libstdc++/94520 + * include/std/charconv (__integer_to_chars_result_type) + (__integer_from_chars_result_type): Use __or_ instead of __or_v_ to + allow use in C++14. + * testsuite/20_util/from_chars/1.cc: Run test as C++14 and replace + use of std::string_view with std::string. + * testsuite/20_util/from_chars/2.cc: Likewise. + * testsuite/20_util/to_chars/1.cc: Likewise. + * testsuite/20_util/to_chars/2.cc: Likewise. + 2020-04-06 Jonathan Wakely PR libstdc++/94498 diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv index 35f8efc7e35..8c9ce9d280e 100644 --- a/libstdc++-v3/include/std/charconv +++ b/libstdc++-v3/include/std/charconv @@ -68,9 +68,9 @@ namespace __detail { template using __integer_to_chars_result_type - = enable_if_t<__or_v<__is_signed_integer<_Tp>, - __is_unsigned_integer<_Tp>, - is_same>>, + = enable_if_t<__or_<__is_signed_integer<_Tp>, + __is_unsigned_integer<_Tp>, + is_same>>::value, to_chars_result>; // Pick an unsigned type of suitable size. This is used to reduce the @@ -564,9 +564,9 @@ namespace __detail template using __integer_from_chars_result_type - = enable_if_t<__or_v<__is_signed_integer<_Tp>, - __is_unsigned_integer<_Tp>, - is_same>>, + = enable_if_t<__or_<__is_signed_integer<_Tp>, + __is_unsigned_integer<_Tp>, + is_same>>::value, from_chars_result>; } // namespace __detail diff --git a/libstdc++-v3/testsuite/20_util/from_chars/1.cc b/libstdc++-v3/testsuite/20_util/from_chars/1.cc index 6ce95590793..916025bc7c6 100644 --- a/libstdc++-v3/testsuite/20_util/from_chars/1.cc +++ b/libstdc++-v3/testsuite/20_util/from_chars/1.cc @@ -15,21 +15,23 @@ // with this library; see the file COPYING3. If not see // . -// { dg-options "-std=gnu++17" } -// { dg-do run { target c++17 } } +// is supported in C++14 as a GNU extension +// { dg-do run { target c++14 } } #include -#include +#include template bool -check_from_chars(I expected, std::string_view s, int base = 0, char term = '\0') +check_from_chars(I expected, std::string s, int base = 0, char term = '\0') { + const char* begin = s.data(); + const char* end = s.data() + s.length(); I val; std::from_chars_result r = base == 0 - ? std::from_chars(s.begin(), s.end(), val) - : std::from_chars(s.begin(), s.end(), val, base); - return r.ec == std::errc{} && (r.ptr == s.end() || *r.ptr == term) && val == expected; + ? std::from_chars(begin, end, val) + : std::from_chars(begin, end, val, base); + return r.ec == std::errc{} && (r.ptr == end || *r.ptr == term) && val == expected; } #include diff --git a/libstdc++-v3/testsuite/20_util/from_chars/2.cc b/libstdc++-v3/testsuite/20_util/from_chars/2.cc index caff17e66b2..902092fd423 100644 --- a/libstdc++-v3/testsuite/20_util/from_chars/2.cc +++ b/libstdc++-v3/testsuite/20_util/from_chars/2.cc @@ -15,11 +15,11 @@ // with this library; see the file COPYING3. If not see // . -// { dg-options "-std=gnu++17" } -// { dg-do run { target c++17 } } +// is supported in C++14 as a GNU extension +// { dg-do run { target c++14 } } #include -#include +#include #include // Test std::from_chars error handling. @@ -29,45 +29,45 @@ test01() { std::from_chars_result r; int i = 999; - std::string_view s; + std::string s; s = ""; - r = std::from_chars(s.begin(), s.end(), i); + r = std::from_chars(s.data(), s.data() + s.length(), i); VERIFY( r.ec == std::errc::invalid_argument ); - VERIFY( r.ptr == s.begin() ); + VERIFY( r.ptr == s.data() ); VERIFY( i == 999 ); s = "*"; - r = std::from_chars(s.begin(), s.end(), i); + r = std::from_chars(s.data(), s.data() + s.length(), i); VERIFY( r.ec == std::errc::invalid_argument ); - VERIFY( r.ptr == s.begin() ); + VERIFY( r.ptr == s.data() ); VERIFY( i == 999 ); s = "-"; - r = std::from_chars(s.begin(), s.end(), i); + r = std::from_chars(s.data(), s.data() + s.length(), i); VERIFY( r.ec == std::errc::invalid_argument ); - VERIFY( r.ptr == s.begin() ); + VERIFY( r.ptr == s.data() ); VERIFY( i == 999 ); s = "-*"; - r = std::from_chars(s.begin(), s.end(), i); + r = std::from_chars(s.data(), s.data() + s.length(), i); VERIFY( r.ec == std::errc::invalid_argument ); - VERIFY( r.ptr == s.begin() ); + VERIFY( r.ptr == s.data() ); VERIFY( i == 999 ); unsigned u = 888; s = "-1"; - r = std::from_chars(s.begin(), s.end(), u); + r = std::from_chars(s.data(), s.data() + s.length(), u); VERIFY( r.ec == std::errc::invalid_argument ); - VERIFY( r.ptr == s.begin() ); + VERIFY( r.ptr == s.data() ); s = "-a"; - r = std::from_chars(s.begin(), s.end(), u); + r = std::from_chars(s.data(), s.data() + s.length(), u); VERIFY( r.ec == std::errc::invalid_argument ); - VERIFY( r.ptr == s.begin() ); + VERIFY( r.ptr == s.data() ); s = "-"; - r = std::from_chars(s.begin(), s.end(), u); + r = std::from_chars(s.data(), s.data() + s.length(), u); VERIFY( r.ec == std::errc::invalid_argument ); - VERIFY( r.ptr == s.begin() ); + VERIFY( r.ptr == s.data() ); VERIFY( u == 888 ); for (int base = 2; base <= 36; ++base) @@ -93,107 +93,107 @@ void test02() { std::from_chars_result r; - std::string_view s; + std::string s; signed char c = -5; s = "-10000001"; - r = std::from_chars(s.begin(), s.end(), c, 2); + r = std::from_chars(s.data(), s.data() + s.length(), c, 2); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.end() ); + VERIFY( r.ptr == s.data() + s.length() ); s = "-10000001*"; - r = std::from_chars(s.begin(), s.end(), c, 2); + r = std::from_chars(s.data(), s.data() + s.length(), c, 2); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 9 ); + VERIFY( r.ptr == s.data() + 9 ); s = "-10000001000*"; - r = std::from_chars(s.begin(), s.end(), c, 2); + r = std::from_chars(s.data(), s.data() + s.length(), c, 2); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 12 ); + VERIFY( r.ptr == s.data() + 12 ); s = "-129"; - r = std::from_chars(s.begin(), s.end(), c, 10); + r = std::from_chars(s.data(), s.data() + s.length(), c, 10); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.end() ); + VERIFY( r.ptr == s.data() + s.length() ); s = "-129*"; - r = std::from_chars(s.begin(), s.end(), c, 10); + r = std::from_chars(s.data(), s.data() + s.length(), c, 10); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 4 ); + VERIFY( r.ptr == s.data() + 4 ); s = "-100"; - r = std::from_chars(s.begin(), s.end(), c, 16); + r = std::from_chars(s.data(), s.data() + s.length(), c, 16); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.end() ); + VERIFY( r.ptr == s.data() + s.length() ); s = "-100*"; - r = std::from_chars(s.begin(), s.end(), c, 16); + r = std::from_chars(s.data(), s.data() + s.length(), c, 16); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 4 ); + VERIFY( r.ptr == s.data() + 4 ); s = "-81"; - r = std::from_chars(s.begin(), s.end(), c, 16); + r = std::from_chars(s.data(), s.data() + s.length(), c, 16); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.end() ); + VERIFY( r.ptr == s.data() + s.length() ); s = "-81*"; - r = std::from_chars(s.begin(), s.end(), c, 16); + r = std::from_chars(s.data(), s.data() + s.length(), c, 16); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 3 ); + VERIFY( r.ptr == s.data() + 3 ); s = "128"; - r = std::from_chars(s.begin(), s.end(), c, 10); + r = std::from_chars(s.data(), s.data() + s.length(), c, 10); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.end() ); + VERIFY( r.ptr == s.data() + s.length() ); s = "128*"; - r = std::from_chars(s.begin(), s.end(), c, 10); + r = std::from_chars(s.data(), s.data() + s.length(), c, 10); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 3 ); + VERIFY( r.ptr == s.data() + 3 ); s = "80"; - r = std::from_chars(s.begin(), s.end(), c, 16); + r = std::from_chars(s.data(), s.data() + s.length(), c, 16); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.end() ); + VERIFY( r.ptr == s.data() + s.length() ); s = "80*"; - r = std::from_chars(s.begin(), s.end(), c, 16); + r = std::from_chars(s.data(), s.data() + s.length(), c, 16); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 2 ); + VERIFY( r.ptr == s.data() + 2 ); VERIFY( c == -5 ); unsigned char uc = 9; s = "100000000"; - r = std::from_chars(s.begin(), s.end(), uc, 2); + r = std::from_chars(s.data(), s.data() + s.length(), uc, 2); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.end() ); + VERIFY( r.ptr == s.data() + s.length() ); s = "100000000*"; - r = std::from_chars(s.begin(), s.end(), uc, 2); + r = std::from_chars(s.data(), s.data() + s.length(), uc, 2); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 9 ); + VERIFY( r.ptr == s.data() + 9 ); s = "100000000000*"; - r = std::from_chars(s.begin(), s.end(), uc, 2); + r = std::from_chars(s.data(), s.data() + s.length(), uc, 2); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 12 ); + VERIFY( r.ptr == s.data() + 12 ); s = "256"; - r = std::from_chars(s.begin(), s.end(), uc, 10); + r = std::from_chars(s.data(), s.data() + s.length(), uc, 10); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.end() ); + VERIFY( r.ptr == s.data() + s.length() ); s = "256**"; - r = std::from_chars(s.begin(), s.end(), uc, 10); + r = std::from_chars(s.data(), s.data() + s.length(), uc, 10); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 3 ); + VERIFY( r.ptr == s.data() + 3 ); s = "256000**"; - r = std::from_chars(s.begin(), s.end(), uc, 10); + r = std::from_chars(s.data(), s.data() + s.length(), uc, 10); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 6 ); + VERIFY( r.ptr == s.data() + 6 ); s = "100"; - r = std::from_chars(s.begin(), s.end(), uc, 16); + r = std::from_chars(s.data(), s.data() + s.length(), uc, 16); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.end() ); + VERIFY( r.ptr == s.data() + s.length() ); s = "100**"; - r = std::from_chars(s.begin(), s.end(), uc, 16); + r = std::from_chars(s.data(), s.data() + s.length(), uc, 16); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 3 ); + VERIFY( r.ptr == s.data() + 3 ); s = "100000**"; - r = std::from_chars(s.begin(), s.end(), uc, 16); + r = std::from_chars(s.data(), s.data() + s.length(), uc, 16); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 6 ); + VERIFY( r.ptr == s.data() + 6 ); VERIFY( uc == 9 ); unsigned long long ull = 123; s = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz****"; - r = std::from_chars(s.begin(), s.end(), ull, 36); + r = std::from_chars(s.data(), s.data() + s.length(), ull, 36); VERIFY( r.ec == std::errc::result_out_of_range ); - VERIFY( r.ptr == s.begin() + 42 ); + VERIFY( r.ptr == s.data() + 42 ); VERIFY( ull == 123 ); } diff --git a/libstdc++-v3/testsuite/20_util/to_chars/1.cc b/libstdc++-v3/testsuite/20_util/to_chars/1.cc index 7e2f1cec08d..9c459219010 100644 --- a/libstdc++-v3/testsuite/20_util/to_chars/1.cc +++ b/libstdc++-v3/testsuite/20_util/to_chars/1.cc @@ -15,23 +15,29 @@ // with this library; see the file COPYING3. If not see // . -// { dg-options "-std=gnu++17" } -// { dg-do run { target c++17 } } +// { dg-do run { target c++14 } } // { dg-require-string-conversions "" } #include -#include +#if __cplusplus >= 201703L +# include +using std::string_view; +#else +// is supported in C++14 as a GNU extension +# include +using string_view = std::string; +#endif template bool -check_to_chars(I val, std::string_view expected, int base = 0) +check_to_chars(I val, string_view expected, int base = 0) { // Space for minus sign, 64 binary digits, final '*', and null terminator: char buf[67] = "******************************************************************"; std::to_chars_result r = base == 0 ? std::to_chars(buf, buf+sizeof(buf), val) : std::to_chars(buf, buf+sizeof(buf), val, base); - return r.ec == std::errc{} && *r.ptr == '*' && std::string_view(buf, r.ptr - buf) == expected; + return r.ec == std::errc{} && *r.ptr == '*' && string_view(buf, r.ptr - buf) == expected; } #include @@ -78,7 +84,7 @@ test01() VERIFY( check_to_chars(123, "123") ); VERIFY( check_to_chars(123, "123") ); - if constexpr (std::is_signed_v) + if (std::is_signed::value) VERIFY( check_to_chars(-79, "-79") ); VERIFY( check_to_chars(-79, "-79") ); VERIFY( check_to_chars(-79, "-79") ); @@ -160,7 +166,7 @@ test02() VERIFY( check_to_chars(123, "123", 10) ); VERIFY( check_to_chars(123, "123", 10) ); - if constexpr (std::is_signed_v) + if (std::is_signed::value) VERIFY( check_to_chars(-79, "-79", 10) ); VERIFY( check_to_chars(-79, "-79", 10) ); VERIFY( check_to_chars(-79, "-79", 10) ); @@ -385,7 +391,7 @@ test03() VERIFY( check_to_chars(1, "1", base) ); VERIFY( check_to_chars(1, "1", base) ); - if constexpr (std::is_signed_v) + if (std::is_signed::value) VERIFY( check_to_chars(-1, "-1", base) ); VERIFY( check_to_chars(-1, "-1", base) ); VERIFY( check_to_chars(-1, "-1", base) ); @@ -407,7 +413,7 @@ test03() VERIFY( check_to_chars(2, "2", base) ); VERIFY( check_to_chars(2, "2", base) ); - if constexpr (std::is_signed_v) + if (std::is_signed::value) VERIFY( check_to_chars(-2, "-2", base) ); VERIFY( check_to_chars(-2, "-2", base) ); VERIFY( check_to_chars(-2, "-2", base) ); @@ -466,7 +472,7 @@ test04() VERIFY( check_to_chars(123, to_string(123), 8) ); VERIFY( check_to_chars(123, to_string(123), 8) ); - if constexpr (std::is_signed_v) + if (std::is_signed::value) VERIFY( check_to_chars(-79, to_string(-79), 8) ); VERIFY( check_to_chars(-79, to_string(-79), 8) ); VERIFY( check_to_chars(-79, to_string(-79), 8) ); @@ -534,7 +540,7 @@ test05() VERIFY( check_to_chars(123, to_string(123), 16) ); VERIFY( check_to_chars(123, to_string(123), 16) ); - if constexpr (std::is_signed_v) + if (std::is_signed::value) VERIFY( check_to_chars(-79, to_string(-79), 16) ); VERIFY( check_to_chars(-79, to_string(-79), 16) ); VERIFY( check_to_chars(-79, to_string(-79), 16) ); @@ -610,7 +616,7 @@ test06() VERIFY( check_to_chars(123, to_string(123), 2) ); VERIFY( check_to_chars(123, to_string(123), 2) ); - if constexpr (std::is_signed_v) + if (std::is_signed::value) VERIFY( check_to_chars(-79, to_string(-79), 2) ); VERIFY( check_to_chars(-79, to_string(-79), 2) ); VERIFY( check_to_chars(-79, to_string(-79), 2) ); diff --git a/libstdc++-v3/testsuite/20_util/to_chars/2.cc b/libstdc++-v3/testsuite/20_util/to_chars/2.cc index cc9c79066da..8b9119f701f 100644 --- a/libstdc++-v3/testsuite/20_util/to_chars/2.cc +++ b/libstdc++-v3/testsuite/20_util/to_chars/2.cc @@ -15,8 +15,8 @@ // with this library; see the file COPYING3. If not see // . -// { dg-options "-std=gnu++17" } -// { dg-do run { target c++17 } } +// is supported in C++14 as a GNU extension +// { dg-do run { target c++14 } } #include #include -- 2.30.2