diff --git a/add-support-for-C++17-std__to_chars-and-std__from_chars.patch b/add-support-for-C++17-std__to_chars-and-std__from_chars.patch new file mode 100644 index 0000000000000000000000000000000000000000..4e9335a37d844a4dd2528dd70cc19dd5243d655a --- /dev/null +++ b/add-support-for-C++17-std__to_chars-and-std__from_chars.patch @@ -0,0 +1,2272 @@ +This backport contains 5 patch from gcc main stream tree. +The commit id of these patchs list as following in the order of time. + +Description: +The first two patches mainly solve the problem of missing files, +so that they can support std:: to_chars and std::from_chars. +The last three patches mainly fix the constexpr list initialized member problem +when gcc-7.3 is used in combination with -std=c++17 + +0001-C-17-P0067R5-std-to_chars-and-std-from_chars-partial.patch +804b7cc438701d94db8f958c2211c59f0357b757 + +0001-charconv-__unsigned_least_t-Fix-number-of-closing-s-.patch +9a741aee62831fb98afb1c9fab8bff7dfe8c2a7f + +0001-PR-c-82461-constexpr-list-initialized-member.patch +d3a9902e523f81f07e765b2553dde7019aa098fb + +0001-PR-c-83835-C-17-error-with-constructor-ctors.patch +b76f3abcd617a8dd38437464d867516962bca5cc + +0001-PR-c-80452-Core-1579-implicit-move-semantics-on-retu.patch +4ce8c5dea53d80736b9c0ba6faa7430ed65ed365 + +diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am +index 87a41f59027..236c2d6059f 100644 +--- a/libstdc++-v3/include/Makefile.am ++++ b/libstdc++-v3/include/Makefile.am +@@ -31,6 +31,7 @@ std_headers = \ + ${std_srcdir}/array \ + ${std_srcdir}/atomic \ + ${std_srcdir}/bitset \ ++ ${std_srcdir}/charconv \ + ${std_srcdir}/chrono \ + ${std_srcdir}/codecvt \ + ${std_srcdir}/complex \ +diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in +index 7bc46060adb..39dfede549b 100644 +--- a/libstdc++-v3/include/Makefile.in ++++ b/libstdc++-v3/include/Makefile.in +@@ -324,6 +324,7 @@ std_headers = \ + ${std_srcdir}/array \ + ${std_srcdir}/atomic \ + ${std_srcdir}/bitset \ ++ ${std_srcdir}/charconv \ + ${std_srcdir}/chrono \ + ${std_srcdir}/codecvt \ + ${std_srcdir}/complex \ +diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h +index 262743a3c1b..b2993cd379f 100644 +--- a/libstdc++-v3/include/precompiled/stdc++.h ++++ b/libstdc++-v3/include/precompiled/stdc++.h +@@ -121,3 +121,7 @@ + #if __cplusplus >= 201402L + #include + #endif ++ ++#if __cplusplus > 201402L ++#include ++#endif +diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv +new file mode 100644 +index 00000000000..b8221e4e434 +--- /dev/null ++++ b/libstdc++-v3/include/std/charconv +@@ -0,0 +1,654 @@ ++// Primitive numeric conversions (to_chars and from_chars) -*- C++ -*- ++ ++// Copyright (C) 2017 Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 3, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// Under Section 7 of GPL version 3, you are granted additional ++// permissions described in the GCC Runtime Library Exception, version ++// 3.1, as published by the Free Software Foundation. ++ ++// You should have received a copy of the GNU General Public License and ++// a copy of the GCC Runtime Library Exception along with this program; ++// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ++// . ++ ++/** @file include/charconv ++ * This is a Standard C++ Library header. ++ */ ++ ++#ifndef _GLIBCXX_CHARCONV ++#define _GLIBCXX_CHARCONV 1 ++ ++#pragma GCC system_header ++ ++#if __cplusplus >= 201402L ++ ++#include ++#include ++#include ++#include // for std::errc ++ ++namespace std _GLIBCXX_VISIBILITY(default) ++{ ++_GLIBCXX_BEGIN_NAMESPACE_VERSION ++ ++ /// Result type of std::to_chars ++ struct to_chars_result ++ { ++ char* ptr; ++ errc ec; ++ }; ++ ++ /// Result type of std::from_chars ++ struct from_chars_result ++ { ++ const char* ptr; ++ errc ec; ++ }; ++ ++namespace __detail ++{ ++ template ++ using __is_one_of = __or_...>; ++ ++ template ++ using __is_int_to_chars_type = __and_, ++ __not_<__is_one_of<_Tp, bool, char16_t, char32_t ++#if _GLIBCXX_USE_WCHAR_T ++ , wchar_t ++#endif ++ >>>; ++ ++ template ++ using __integer_to_chars_result_type ++ = enable_if_t<__is_int_to_chars_type<_Tp>::value, to_chars_result>; ++ ++ template ++ using __unsigned_least_t ++ = conditional_t<(sizeof(_Tp) <= sizeof(int)), unsigned int, ++ conditional_t<(sizeof(_Tp) <= sizeof(long)), unsigned long, ++ conditional_t<(sizeof(_Tp) <= sizeof(long long)), unsigned long long, ++#if _GLIBCXX_USE_INT128 ++ conditional_t<(sizeof(_Tp) <= sizeof(__int128)), unsigned __int128, ++#endif ++ void>>>>; ++ ++ // Generic implementation for arbitrary bases. ++ template ++ constexpr unsigned ++ __to_chars_len(_Tp __value, int __base = 10) noexcept ++ { ++ static_assert(is_integral<_Tp>::value, "implementation bug"); ++ static_assert(is_unsigned<_Tp>::value, "implementation bug"); ++ ++ unsigned __n = 1; ++ const int __b2 = __base * __base; ++ const int __b3 = __b2 * __base; ++ const int __b4 = __b3 * __base; ++ for (;;) ++ { ++ if (__value < __base) return __n; ++ if (__value < __b2) return __n + 1; ++ if (__value < __b3) return __n + 2; ++ if (__value < __b4) return __n + 3; ++ __value /= (unsigned)__b4; ++ __n += 4; ++ } ++ } ++ ++ template ++ constexpr unsigned ++ __to_chars_len_2(_Tp __value) noexcept ++ { ++ static_assert(is_integral<_Tp>::value, "implementation bug"); ++ static_assert(is_unsigned<_Tp>::value, "implementation bug"); ++ ++ constexpr size_t __nbits = __CHAR_BIT__ * sizeof(_Tp); ++ ++ // N.B. __builtin_clzll is undefined if __value == 0, but std::to_chars ++ // handles zero values directly. ++ ++ // For sizeof(_Tp) > 1 this is an order of magnitude faster than ++ // the generic __to_chars_len. ++ return __nbits ++ - (__builtin_clzll(__value) ++ - ((__CHAR_BIT__ * sizeof(long long)) - __nbits)); ++ } ++ ++ template ++ constexpr unsigned ++ __to_chars_len_8(_Tp __value) noexcept ++ { ++ static_assert(is_integral<_Tp>::value, "implementation bug"); ++ static_assert(is_unsigned<_Tp>::value, "implementation bug"); ++ ++ constexpr size_t __nbits = __CHAR_BIT__ * sizeof(_Tp); ++ ++ if _GLIBCXX17_CONSTEXPR (__nbits <= 16) ++ { ++ return __value > 077777u ? 6u ++ : __value > 07777u ? 5u ++ : __value > 0777u ? 4u ++ : __value > 077u ? 3u ++ : __value > 07u ? 2u ++ : 1u; ++ } ++ else ++ return __to_chars_len(__value, 8); ++ } ++ ++ // Generic implementation for arbitrary bases. ++ template ++ to_chars_result ++ __to_chars(char* __first, char* __last, _Tp __val, int __base) noexcept ++ { ++ static_assert(is_integral<_Tp>::value, "implementation bug"); ++ static_assert(is_unsigned<_Tp>::value, "implementation bug"); ++ ++ to_chars_result __res; ++ ++ const unsigned __len = __to_chars_len(__val, __base); ++ ++ if (__builtin_expect((__last - __first) < __len, 0)) ++ { ++ __res.ptr = __last; ++ __res.ec = errc::value_too_large; ++ return __res; ++ } ++ ++ unsigned __pos = __len - 1; ++ ++ static constexpr char __digits[] ++ = "0123456789abcdefghijklmnopqrstuvwxyz"; ++ ++ while (__val >= __base) ++ { ++ auto const __quo = __val / __base; ++ auto const __rem = __val % __base; ++ __first[__pos--] = __digits[__rem]; ++ __val = __quo; ++ } ++ *__first = __digits[__val]; ++ ++ __res.ptr = __first + __len; ++ __res.ec = {}; ++ return __res; ++ } ++ ++ template ++ __integer_to_chars_result_type<_Tp> ++ __to_chars_16(char* __first, char* __last, _Tp __val) noexcept ++ { ++ static_assert(is_integral<_Tp>::value, "implementation bug"); ++ static_assert(is_unsigned<_Tp>::value, "implementation bug"); ++ ++ to_chars_result __res; ++ ++ const unsigned __len = __to_chars_len(__val, 0x10); ++ ++ if (__builtin_expect((__last - __first) < __len, 0)) ++ { ++ __res.ptr = __last; ++ __res.ec = errc::value_too_large; ++ return __res; ++ } ++ ++ static constexpr char __digits[513] = ++ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" ++ "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" ++ "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" ++ "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" ++ "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" ++ "a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" ++ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf" ++ "e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; ++ unsigned __pos = __len - 1; ++ while (__val >= 0x100) ++ { ++ auto const __num = (__val % 0x100) * 2; ++ __val /= 0x100; ++ __first[__pos] = __digits[__num + 1]; ++ __first[__pos - 1] = __digits[__num]; ++ __pos -= 2; ++ } ++ if (__val >= 0x10) ++ { ++ auto const __num = __val * 2; ++ __first[__pos] = __digits[__num + 1]; ++ __first[__pos - 1] = __digits[__num]; ++ } ++ else ++ __first[__pos] = "0123456789abcdef"[__val]; ++ __res.ptr = __first + __len; ++ __res.ec = {}; ++ return __res; ++ } ++ ++ template ++ __integer_to_chars_result_type<_Tp> ++ __to_chars_10(char* __first, char* __last, _Tp __val) noexcept ++ { ++ static_assert(is_integral<_Tp>::value, "implementation bug"); ++ static_assert(is_unsigned<_Tp>::value, "implementation bug"); ++ ++ to_chars_result __res; ++ ++ const unsigned __len = __to_chars_len(__val, 10); ++ ++ if (__builtin_expect((__last - __first) < __len, 0)) ++ { ++ __res.ptr = __last; ++ __res.ec = errc::value_too_large; ++ return __res; ++ } ++ ++ static constexpr char __digits[201] = ++ "0001020304050607080910111213141516171819" ++ "2021222324252627282930313233343536373839" ++ "4041424344454647484950515253545556575859" ++ "6061626364656667686970717273747576777879" ++ "8081828384858687888990919293949596979899"; ++ unsigned __pos = __len - 1; ++ while (__val >= 100) ++ { ++ auto const __num = (__val % 100) * 2; ++ __val /= 100; ++ __first[__pos] = __digits[__num + 1]; ++ __first[__pos - 1] = __digits[__num]; ++ __pos -= 2; ++ } ++ if (__val >= 10) ++ { ++ auto const __num = __val * 2; ++ __first[__pos] = __digits[__num + 1]; ++ __first[__pos - 1] = __digits[__num]; ++ } ++ else ++ __first[__pos] = '0' + __val; ++ __res.ptr = __first + __len; ++ __res.ec = {}; ++ return __res; ++ } ++ ++ template ++ __integer_to_chars_result_type<_Tp> ++ __to_chars_8(char* __first, char* __last, _Tp __val) noexcept ++ { ++ static_assert(is_integral<_Tp>::value, "implementation bug"); ++ static_assert(is_unsigned<_Tp>::value, "implementation bug"); ++ ++ to_chars_result __res; ++ ++ const unsigned __len = __to_chars_len_8(__val); ++ ++ if (__builtin_expect((__last - __first) < __len, 0)) ++ { ++ __res.ptr = __last; ++ __res.ec = errc::value_too_large; ++ return __res; ++ } ++ ++ static constexpr char __digits[129] = ++ "00010203040506071011121314151617" ++ "20212223242526273031323334353637" ++ "40414243444546475051525354555657" ++ "60616263646566677071727374757677"; ++ unsigned __pos = __len - 1; ++ while (__val >= 0100) ++ { ++ auto const __num = (__val % 0100) * 2; ++ __val /= 0100; ++ __first[__pos] = __digits[__num + 1]; ++ __first[__pos - 1] = __digits[__num]; ++ __pos -= 2; ++ } ++ if (__val >= 010) ++ { ++ auto const __num = __val * 2; ++ __first[__pos] = __digits[__num + 1]; ++ __first[__pos - 1] = __digits[__num]; ++ } ++ else ++ __first[__pos] = '0' + __val; ++ __res.ptr = __first + __len; ++ __res.ec = {}; ++ return __res; ++ } ++ ++ template ++ __integer_to_chars_result_type<_Tp> ++ __to_chars_2(char* __first, char* __last, _Tp __val) noexcept ++ { ++ static_assert(is_integral<_Tp>::value, "implementation bug"); ++ static_assert(is_unsigned<_Tp>::value, "implementation bug"); ++ ++ to_chars_result __res; ++ ++ const unsigned __len = __to_chars_len_2(__val); ++ ++ if (__builtin_expect((__last - __first) < __len, 0)) ++ { ++ __res.ptr = __last; ++ __res.ec = errc::value_too_large; ++ return __res; ++ } ++ ++ unsigned __pos = __len - 1; ++ ++ while (__pos) ++ { ++ __first[__pos--] = '0' + (__val & 1); ++ __val >>= 1; ++ } ++ *__first = '0' + (__val & 1); ++ ++ __res.ptr = __first + __len; ++ __res.ec = {}; ++ return __res; ++ } ++ ++} // namespace __detail ++ ++ template ++ __detail::__integer_to_chars_result_type<_Tp> ++ to_chars(char* __first, char* __last, _Tp __value, int __base = 10) ++ { ++ __glibcxx_assert(2 <= __base && __base <= 36); ++ ++ using _Up = __detail::__unsigned_least_t<_Tp>; ++ _Up __unsigned_val = __value; ++ ++ if (__value == 0 && __first != __last) ++ { ++ *__first = '0'; ++ return { __first + 1, errc{} }; ++ } ++ ++ if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value) ++ if (__value < 0) ++ { ++ if (__builtin_expect(__first != __last, 1)) ++ *__first++ = '-'; ++ __unsigned_val = _Up(~__value) + _Up(1); ++ } ++ ++ switch (__base) ++ { ++ case 16: ++ return __detail::__to_chars_16(__first, __last, __unsigned_val); ++ case 10: ++ return __detail::__to_chars_10(__first, __last, __unsigned_val); ++ case 8: ++ return __detail::__to_chars_8(__first, __last, __unsigned_val); ++ case 2: ++ return __detail::__to_chars_2(__first, __last, __unsigned_val); ++ default: ++ return __detail::__to_chars(__first, __last, __unsigned_val, __base); ++ } ++ } ++ ++namespace __detail ++{ ++ template ++ bool ++ __raise_and_add(_Tp& __val, int __base, unsigned char __c) ++ { ++ if (__builtin_mul_overflow(__val, __base, &__val) ++ || __builtin_add_overflow(__val, __c, &__val)) ++ return false; ++ return true; ++ } ++ ++ /// std::from_chars implementation for integers in base 2. ++ template ++ bool ++ __from_chars_binary(const char*& __first, const char* __last, _Tp& __val) ++ { ++ static_assert(is_integral<_Tp>::value, "implementation bug"); ++ static_assert(is_unsigned<_Tp>::value, "implementation bug"); ++ ++ const ptrdiff_t __len = __last - __first; ++ int __i = 0; ++ while (__i < __len) ++ { ++ const unsigned char __c = (unsigned)__first[__i] - '0'; ++ if (__c < 2) ++ __val = (__val << 1) | __c; ++ else ++ break; ++ __i++; ++ } ++ __first += __i; ++ return __i <= (sizeof(_Tp) * __CHAR_BIT__); ++ } ++ ++ /// std::from_chars implementation for integers in bases 3 to 10. ++ template ++ bool ++ __from_chars_digit(const char*& __first, const char* __last, _Tp& __val, ++ int __base) ++ { ++ static_assert(is_integral<_Tp>::value, "implementation bug"); ++ static_assert(is_unsigned<_Tp>::value, "implementation bug"); ++ ++ auto __matches = [__base](char __c) { ++ return '0' <= __c && __c <= ('0' + (__base - 1)); ++ }; ++ ++ while (__first != __last) ++ { ++ const char __c = *__first; ++ if (__matches(__c)) ++ { ++ if (!__raise_and_add(__val, __base, __c - '0')) ++ { ++ while (++__first != __last && __matches(*__first)) ++ ; ++ return false; ++ } ++ __first++; ++ } ++ else ++ return true; ++ } ++ return true; ++ } ++ ++ constexpr unsigned char ++ __from_chars_alpha_to_num(char __c) ++ { ++ switch (__c) ++ { ++ case 'a': ++ case 'A': ++ return 10; ++ case 'b': ++ case 'B': ++ return 11; ++ case 'c': ++ case 'C': ++ return 12; ++ case 'd': ++ case 'D': ++ return 13; ++ case 'e': ++ case 'E': ++ return 14; ++ case 'f': ++ case 'F': ++ return 15; ++ case 'g': ++ case 'G': ++ return 16; ++ case 'h': ++ case 'H': ++ return 17; ++ case 'i': ++ case 'I': ++ return 18; ++ case 'j': ++ case 'J': ++ return 19; ++ case 'k': ++ case 'K': ++ return 20; ++ case 'l': ++ case 'L': ++ return 21; ++ case 'm': ++ case 'M': ++ return 22; ++ case 'n': ++ case 'N': ++ return 23; ++ case 'o': ++ case 'O': ++ return 24; ++ case 'p': ++ case 'P': ++ return 25; ++ case 'q': ++ case 'Q': ++ return 26; ++ case 'r': ++ case 'R': ++ return 27; ++ case 's': ++ case 'S': ++ return 28; ++ case 't': ++ case 'T': ++ return 29; ++ case 'u': ++ case 'U': ++ return 30; ++ case 'v': ++ case 'V': ++ return 31; ++ case 'w': ++ case 'W': ++ return 32; ++ case 'x': ++ case 'X': ++ return 33; ++ case 'y': ++ case 'Y': ++ return 34; ++ case 'z': ++ case 'Z': ++ return 35; ++ } ++ return std::numeric_limits::max(); ++ } ++ ++ /// std::from_chars implementation for integers in bases 11 to 26. ++ template ++ bool ++ __from_chars_alnum(const char*& __first, const char* __last, _Tp& __val, ++ int __base) ++ { ++ bool __valid = true; ++ while (__first != __last) ++ { ++ unsigned char __c = *__first; ++ if (std::isdigit(__c)) ++ __c -= '0'; ++ else ++ { ++ __c = __from_chars_alpha_to_num(__c); ++ if (__c >= __base) ++ break; ++ } ++ ++ if (__builtin_expect(__valid, 1)) ++ __valid = __raise_and_add(__val, __base, __c); ++ __first++; ++ } ++ return __valid; ++ } ++ ++ template ++ using __integer_from_chars_result_type ++ = enable_if_t<__is_int_to_chars_type<_Tp>::value, from_chars_result>; ++ ++} // namespace __detail ++ ++ /// std::from_chars for integral types. ++ template ++ __detail::__integer_from_chars_result_type<_Tp> ++ from_chars(const char* __first, const char* __last, _Tp& __value, ++ int __base = 10) ++ { ++ __glibcxx_assert(2 <= __base && __base <= 36); ++ ++ from_chars_result __res{__first, {}}; ++ ++ int __sign = 1; ++ if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value) ++ if (__first != __last && *__first == '-') ++ { ++ __sign = -1; ++ ++__first; ++ } ++ ++ using _Up = __detail::__unsigned_least_t<_Tp>; ++ _Up __val = 0; ++ ++ const auto __start = __first; ++ bool __valid; ++ if (__base == 2) ++ __valid = __detail::__from_chars_binary(__first, __last, __val); ++ else if (__base <= 10) ++ __valid = __detail::__from_chars_digit(__first, __last, __val, __base); ++ else ++ __valid = __detail::__from_chars_alnum(__first, __last, __val, __base); ++ ++ if (__builtin_expect(__first == __start, 0)) ++ __res.ec = errc::invalid_argument; ++ else ++ { ++ __res.ptr = __first; ++ if (!__valid) ++ __res.ec = errc::result_out_of_range; ++ else ++ { ++ if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value) ++ { ++ _Tp __tmp; ++ if (__builtin_mul_overflow(__val, __sign, &__tmp)) ++ __res.ec = errc::result_out_of_range; ++ else ++ __value = __tmp; ++ } ++ else ++ { ++ if _GLIBCXX17_CONSTEXPR ++ (numeric_limits<_Up>::max() > numeric_limits<_Tp>::max()) ++ { ++ if (__val > numeric_limits<_Tp>::max()) ++ __res.ec = errc::result_out_of_range; ++ else ++ __value = __val; ++ } ++ else ++ __value = __val; ++ } ++ } ++ } ++ return __res; ++ } ++ ++_GLIBCXX_END_NAMESPACE_VERSION ++} // namespace std ++#endif // C++14 ++#endif // _GLIBCXX_CHARCONV +diff --git a/libstdc++-v3/testsuite/20_util/from_chars/1.cc b/libstdc++-v3/testsuite/20_util/from_chars/1.cc +new file mode 100644 +index 00000000000..b552195ae96 +--- /dev/null ++++ b/libstdc++-v3/testsuite/20_util/from_chars/1.cc +@@ -0,0 +1,80 @@ ++// Copyright (C) 2017 Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 3, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// You should have received a copy of the GNU General Public License along ++// with this library; see the file COPYING3. If not see ++// . ++ ++// { dg-options "-std=gnu++17" } ++// { dg-do run { target c++17 } } ++ ++#include ++#include ++ ++template ++bool ++check_from_chars(I expected, std::string_view s, int base = 0, char term = '\0') ++{ ++ 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; ++} ++ ++#include ++#include ++ ++void ++test01() ++{ ++ // Using base 10 ++ VERIFY( check_from_chars(123, "123") ); ++ VERIFY( check_from_chars(-123, "-123") ); ++ VERIFY( check_from_chars(123, "123a", 10, 'a') ); ++ VERIFY( check_from_chars(123, "0000000000000000000000000000123") ); ++ VERIFY( check_from_chars(123, "0000000000000000000000000000123a", 10, 'a') ); ++} ++ ++void ++test02() ++{ ++ // "0x" parsed as "0" not as hex prefix: ++ VERIFY( check_from_chars(0, "0x1", 10, 'x') ); ++ VERIFY( check_from_chars(0, "0X1", 10, 'X') ); ++ VERIFY( check_from_chars(0, "0x1", 16, 'x') ); ++ VERIFY( check_from_chars(0, "0X1", 16, 'X') ); ++ ++ VERIFY( check_from_chars(1155, "xx", 34) ); ++ VERIFY( check_from_chars(1155, "XX", 34) ); ++ VERIFY( check_from_chars(1155, "Xx", 34) ); ++ VERIFY( check_from_chars(1224, "yy", 35) ); ++ VERIFY( check_from_chars(1224, "YY", 35) ); ++ VERIFY( check_from_chars(1224, "yY", 35) ); ++ VERIFY( check_from_chars(1295, "zz", 36) ); ++ VERIFY( check_from_chars(1295, "ZZ", 36) ); ++ VERIFY( check_from_chars(1295, "Zz", 36) ); ++ ++ // Parsing stops at first invalid digit for the given base: ++ VERIFY( check_from_chars(1, "01234", 2, '2') ); ++ VERIFY( check_from_chars(27, "1234", 4, '4') ); ++ VERIFY( check_from_chars(1155, "xxy", 34, 'y') ); ++ VERIFY( check_from_chars(1224, "yyz", 35, 'z') ); ++} ++ ++int ++main() ++{ ++ test01(); ++ test02(); ++} +diff --git a/libstdc++-v3/testsuite/20_util/from_chars/1_neg.cc b/libstdc++-v3/testsuite/20_util/from_chars/1_neg.cc +new file mode 100644 +index 00000000000..d826ba9712b +--- /dev/null ++++ b/libstdc++-v3/testsuite/20_util/from_chars/1_neg.cc +@@ -0,0 +1,38 @@ ++// Copyright (C) 2017 Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 3, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// You should have received a copy of the GNU General Public License along ++// with this library; see the file COPYING3. If not see ++// . ++ ++// { dg-options "-std=gnu++17" } ++// { dg-do compile { target c++17 } } ++ ++#include ++ ++void ++test01(const char* first, const char* last) ++{ ++#if _GLIBCXX_USE_WCHAR_T ++ wchar_t wc; ++ std::from_chars(first, last, wc); // { dg-error "no matching" } ++ std::from_chars(first, last, wc, 10); // { dg-error "no matching" } ++#endif ++ ++ char16_t c16; ++ std::from_chars(first, last, c16); // { dg-error "no matching" } ++ std::from_chars(first, last, c16, 10); // { dg-error "no matching" } ++ char32_t c32; ++ std::from_chars(first, last, c32); // { dg-error "no matching" } ++ std::from_chars(first, last, c32, 10); // { dg-error "no matching" } ++} +diff --git a/libstdc++-v3/testsuite/20_util/from_chars/2.cc b/libstdc++-v3/testsuite/20_util/from_chars/2.cc +new file mode 100644 +index 00000000000..117cf74662a +--- /dev/null ++++ b/libstdc++-v3/testsuite/20_util/from_chars/2.cc +@@ -0,0 +1,205 @@ ++// Copyright (C) 2017 Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 3, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// You should have received a copy of the GNU General Public License along ++// with this library; see the file COPYING3. If not see ++// . ++ ++// { dg-options "-std=gnu++17" } ++// { dg-do run { target c++17 } } ++ ++#include ++#include ++#include ++ ++// Test std::from_chars error handling. ++ ++void ++test01() ++{ ++ std::from_chars_result r; ++ int i = 999; ++ std::string_view s; ++ ++ s = ""; ++ r = std::from_chars(s.begin(), s.end(), i); ++ VERIFY( r.ec == std::errc::invalid_argument ); ++ VERIFY( r.ptr == s.begin() ); ++ VERIFY( i == 999 ); ++ ++ s = "*"; ++ r = std::from_chars(s.begin(), s.end(), i); ++ VERIFY( r.ec == std::errc::invalid_argument ); ++ VERIFY( r.ptr == s.begin() ); ++ VERIFY( i == 999 ); ++ ++ s = "-"; ++ r = std::from_chars(s.begin(), s.end(), i); ++ VERIFY( r.ec == std::errc::invalid_argument ); ++ VERIFY( r.ptr == s.begin() ); ++ VERIFY( i == 999 ); ++ ++ s = "-*"; ++ r = std::from_chars(s.begin(), s.end(), i); ++ VERIFY( r.ec == std::errc::invalid_argument ); ++ VERIFY( r.ptr == s.begin() ); ++ VERIFY( i == 999 ); ++ ++ unsigned u = 888; ++ s = "-1"; ++ r = std::from_chars(s.begin(), s.end(), u); ++ VERIFY( r.ec == std::errc::invalid_argument ); ++ VERIFY( r.ptr == s.begin() ); ++ s = "-a"; ++ r = std::from_chars(s.begin(), s.end(), u); ++ VERIFY( r.ec == std::errc::invalid_argument ); ++ VERIFY( r.ptr == s.begin() ); ++ s = "-"; ++ r = std::from_chars(s.begin(), s.end(), u); ++ VERIFY( r.ec == std::errc::invalid_argument ); ++ VERIFY( r.ptr == s.begin() ); ++ VERIFY( u == 888 ); ++ ++ for (int base = 2; base <= 36; ++base) ++ { ++ const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz*"; ++ const char buf[2] = { '-', digits[base] }; ++ r = std::from_chars(buf, buf + 1, i, base); ++ VERIFY( r.ec == std::errc::invalid_argument ); ++ VERIFY( r.ptr == buf ); ++ VERIFY( i == 999 ); ++ r = std::from_chars(buf + 1, buf + 2, i, base); ++ VERIFY( r.ec == std::errc::invalid_argument ); ++ VERIFY( r.ptr == buf + 1 ); ++ VERIFY( i == 999 ); ++ r = std::from_chars(buf, buf + 2, i, base); ++ VERIFY( r.ec == std::errc::invalid_argument ); ++ VERIFY( r.ptr == buf ); ++ VERIFY( i == 999 ); ++ } ++} ++ ++void ++test02() ++{ ++ std::from_chars_result r; ++ std::string_view s; ++ ++ signed char c = -5; ++ s = "-10000001"; ++ r = std::from_chars(s.begin(), s.end(), c, 2); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.end() ); ++ s = "-10000001*"; ++ r = std::from_chars(s.begin(), s.end(), c, 2); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 9 ); ++ s = "-10000001000*"; ++ r = std::from_chars(s.begin(), s.end(), c, 2); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 12 ); ++ s = "-129"; ++ r = std::from_chars(s.begin(), s.end(), c, 10); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.end() ); ++ s = "-129*"; ++ r = std::from_chars(s.begin(), s.end(), c, 10); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 4 ); ++ s = "-100"; ++ r = std::from_chars(s.begin(), s.end(), c, 16); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.end() ); ++ s = "-100*"; ++ r = std::from_chars(s.begin(), s.end(), c, 16); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 4 ); ++ s = "-81"; ++ r = std::from_chars(s.begin(), s.end(), c, 16); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.end() ); ++ s = "-81*"; ++ r = std::from_chars(s.begin(), s.end(), c, 16); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 3 ); ++ s = "128"; ++ r = std::from_chars(s.begin(), s.end(), c, 10); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.end() ); ++ s = "128*"; ++ r = std::from_chars(s.begin(), s.end(), c, 10); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 3 ); ++ s = "80"; ++ r = std::from_chars(s.begin(), s.end(), c, 16); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.end() ); ++ s = "80*"; ++ r = std::from_chars(s.begin(), s.end(), c, 16); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 2 ); ++ VERIFY( c == -5 ); ++ ++ unsigned char uc = 9; ++ s = "100000000"; ++ r = std::from_chars(s.begin(), s.end(), uc, 2); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.end() ); ++ s = "100000000*"; ++ r = std::from_chars(s.begin(), s.end(), uc, 2); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 9 ); ++ s = "100000000000*"; ++ r = std::from_chars(s.begin(), s.end(), uc, 2); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 12 ); ++ s = "256"; ++ r = std::from_chars(s.begin(), s.end(), uc, 10); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.end() ); ++ s = "256**"; ++ r = std::from_chars(s.begin(), s.end(), uc, 10); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 3 ); ++ s = "256000**"; ++ r = std::from_chars(s.begin(), s.end(), uc, 10); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 6 ); ++ s = "100"; ++ r = std::from_chars(s.begin(), s.end(), uc, 16); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.end() ); ++ s = "100**"; ++ r = std::from_chars(s.begin(), s.end(), uc, 16); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 3 ); ++ s = "100000**"; ++ r = std::from_chars(s.begin(), s.end(), uc, 16); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 6 ); ++ VERIFY( uc == 9 ); ++ ++ unsigned long long ull = 123; ++ s = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz****"; ++ r = std::from_chars(s.begin(), s.end(), ull, 36); ++ VERIFY( r.ec == std::errc::result_out_of_range ); ++ VERIFY( r.ptr == s.begin() + 42 ); ++ VERIFY( ull == 123 ); ++} ++ ++int ++main() ++{ ++ test01(); ++ test02(); ++} +diff --git a/libstdc++-v3/testsuite/20_util/from_chars/requirements.cc b/libstdc++-v3/testsuite/20_util/from_chars/requirements.cc +new file mode 100644 +index 00000000000..00b7d875664 +--- /dev/null ++++ b/libstdc++-v3/testsuite/20_util/from_chars/requirements.cc +@@ -0,0 +1,61 @@ ++// Copyright (C) 2017 Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 3, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// You should have received a copy of the GNU General Public License along ++// with this library; see the file COPYING3. If not see ++// . ++ ++// { dg-options "-std=gnu++17" } ++// { dg-do compile { target c++17 } } ++ ++#include ++ ++namespace std ++{ ++ struct from_chars_result; ++ ++ const char* from_chars_result::*pm2 = &from_chars_result::ptr; ++ errc from_chars_result::*pm1 = &from_chars_result::ec; ++ ++ from_chars_result (*f1)(const char*, const char*, char&, int) ++ = &from_chars; ++ from_chars_result (*f2)(const char*, const char*, signed char&, int) ++ = &from_chars; ++ from_chars_result (*f3)(const char*, const char*, unsigned char&, int) ++ = &from_chars; ++ from_chars_result (*f4)(const char*, const char*, signed short&, int) ++ = &from_chars; ++ from_chars_result (*f5)(const char*, const char*, unsigned short&, int) ++ = &from_chars; ++ from_chars_result (*f6)(const char*, const char*, signed int&, int) ++ = &from_chars; ++ from_chars_result (*f7)(const char*, const char*, unsigned int&, int) ++ = &from_chars; ++ from_chars_result (*f8)(const char*, const char*, signed long&, int) ++ = &from_chars; ++ from_chars_result (*f9)(const char*, const char*, unsigned long&, int) ++ = &from_chars; ++ from_chars_result (*f10)(const char*, const char*, signed long long&, int) ++ = &from_chars; ++ from_chars_result (*f11)(const char*, const char*, unsigned long long&, int) ++ = &from_chars; ++} ++ ++void bind() ++{ ++ const char buf[1] = ""; ++ int i; ++ auto [p, e] = std::from_chars(buf, buf + 1, i, 10); ++ const char** pa = &p; ++ std::errc* ea = &e; ++} +diff --git a/libstdc++-v3/testsuite/20_util/to_chars/1.cc b/libstdc++-v3/testsuite/20_util/to_chars/1.cc +new file mode 100644 +index 00000000000..bdd961104a2 +--- /dev/null ++++ b/libstdc++-v3/testsuite/20_util/to_chars/1.cc +@@ -0,0 +1,661 @@ ++// Copyright (C) 2017 Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 3, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// You should have received a copy of the GNU General Public License along ++// with this library; see the file COPYING3. If not see ++// . ++ ++// { dg-options "-std=gnu++17" } ++// { dg-do run { target c++17 } } ++ ++#include ++#include ++ ++template ++bool ++check_to_chars(I val, std::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; ++} ++ ++#include ++#include ++#include ++ ++// Using default base 10 ++void ++test01() ++{ ++ VERIFY( check_to_chars(0, "0") ); ++ VERIFY( check_to_chars(0, "0") ); ++ VERIFY( check_to_chars(0, "0") ); ++ VERIFY( check_to_chars(0, "0") ); ++ VERIFY( check_to_chars(0, "0") ); ++ VERIFY( check_to_chars(0, "0") ); ++ VERIFY( check_to_chars(0, "0") ); ++ VERIFY( check_to_chars(0, "0") ); ++ VERIFY( check_to_chars(0, "0") ); ++ VERIFY( check_to_chars(0, "0") ); ++ VERIFY( check_to_chars(0, "0") ); ++ ++ VERIFY( check_to_chars(1, "1") ); ++ VERIFY( check_to_chars(1, "1") ); ++ VERIFY( check_to_chars(1, "1") ); ++ VERIFY( check_to_chars(1, "1") ); ++ VERIFY( check_to_chars(1, "1") ); ++ VERIFY( check_to_chars(1, "1") ); ++ VERIFY( check_to_chars(1, "1") ); ++ VERIFY( check_to_chars(1, "1") ); ++ VERIFY( check_to_chars(1, "1") ); ++ VERIFY( check_to_chars(1, "1") ); ++ VERIFY( check_to_chars(1, "1") ); ++ ++ VERIFY( check_to_chars(123, "123") ); ++ VERIFY( check_to_chars(123, "123") ); ++ VERIFY( check_to_chars(123, "123") ); ++ VERIFY( check_to_chars(123, "123") ); ++ VERIFY( check_to_chars(123, "123") ); ++ VERIFY( check_to_chars(123, "123") ); ++ VERIFY( check_to_chars(123, "123") ); ++ VERIFY( check_to_chars(123, "123") ); ++ VERIFY( check_to_chars(123, "123") ); ++ VERIFY( check_to_chars(123, "123") ); ++ VERIFY( check_to_chars(123, "123") ); ++ ++ if constexpr (std::is_signed_v) ++ VERIFY( check_to_chars(-79, "-79") ); ++ VERIFY( check_to_chars(-79, "-79") ); ++ VERIFY( check_to_chars(-79, "-79") ); ++ VERIFY( check_to_chars(-79, "-79") ); ++ VERIFY( check_to_chars(-79, "-79") ); ++ VERIFY( check_to_chars(-79, "-79") ); ++ ++ using std::to_string; ++ ++ VERIFY( check_to_chars(CHAR_MAX, to_string(CHAR_MAX)) ); ++ VERIFY( check_to_chars(SCHAR_MAX, to_string(SCHAR_MAX)) ); ++ VERIFY( check_to_chars(UCHAR_MAX, to_string(UCHAR_MAX)) ); ++ VERIFY( check_to_chars(SHRT_MAX, to_string(SHRT_MAX)) ); ++ VERIFY( check_to_chars(USHRT_MAX, to_string(USHRT_MAX)) ); ++ VERIFY( check_to_chars(INT_MAX, to_string(INT_MAX)) ); ++ VERIFY( check_to_chars(UINT_MAX, to_string(UINT_MAX)) ); ++ VERIFY( check_to_chars(LONG_MAX, to_string(LONG_MAX)) ); ++ VERIFY( check_to_chars(ULONG_MAX, to_string(ULONG_MAX)) ); ++ VERIFY( check_to_chars(LLONG_MAX, to_string(LLONG_MAX)) ); ++ VERIFY( check_to_chars(ULLONG_MAX, to_string(ULLONG_MAX)) ); ++ ++ VERIFY( check_to_chars(CHAR_MIN, to_string(CHAR_MIN)) ); ++ VERIFY( check_to_chars(SCHAR_MIN, to_string(SCHAR_MIN)) ); ++ VERIFY( check_to_chars(SHRT_MIN, to_string(SHRT_MIN)) ); ++ VERIFY( check_to_chars(INT_MIN, to_string(INT_MIN)) ); ++ VERIFY( check_to_chars(LONG_MIN, to_string(LONG_MIN)) ); ++ VERIFY( check_to_chars(LLONG_MIN, to_string(LLONG_MIN)) ); ++ ++ VERIFY( check_to_chars(CHAR_MAX/2, to_string(CHAR_MAX/2)) ); ++ VERIFY( check_to_chars(SCHAR_MAX/2, to_string(SCHAR_MAX/2)) ); ++ VERIFY( check_to_chars(UCHAR_MAX/2, to_string(UCHAR_MAX/2)) ); ++ VERIFY( check_to_chars(SHRT_MAX/2, to_string(SHRT_MAX/2)) ); ++ VERIFY( check_to_chars(USHRT_MAX/2, to_string(USHRT_MAX/2)) ); ++ VERIFY( check_to_chars(INT_MAX/2, to_string(INT_MAX/2)) ); ++ VERIFY( check_to_chars(UINT_MAX/2, to_string(UINT_MAX/2)) ); ++ VERIFY( check_to_chars(LONG_MAX/2, to_string(LONG_MAX/2)) ); ++ VERIFY( check_to_chars(ULONG_MAX/2, to_string(ULONG_MAX/2)) ); ++ VERIFY( check_to_chars(LLONG_MAX/2, to_string(LLONG_MAX/2)) ); ++ VERIFY( check_to_chars(ULLONG_MAX/2, to_string(ULLONG_MAX/2)) ); ++} ++ ++// Using explicit base 10 ++void ++test02() ++{ ++ VERIFY( check_to_chars(0, "0", 10) ); ++ VERIFY( check_to_chars(0, "0", 10) ); ++ VERIFY( check_to_chars(0, "0", 10) ); ++ VERIFY( check_to_chars(0, "0", 10) ); ++ VERIFY( check_to_chars(0, "0", 10) ); ++ VERIFY( check_to_chars(0, "0", 10) ); ++ VERIFY( check_to_chars(0, "0", 10) ); ++ VERIFY( check_to_chars(0, "0", 10) ); ++ VERIFY( check_to_chars(0, "0", 10) ); ++ VERIFY( check_to_chars(0, "0", 10) ); ++ VERIFY( check_to_chars(0, "0", 10) ); ++ ++ VERIFY( check_to_chars(1, "1", 10) ); ++ VERIFY( check_to_chars(1, "1", 10) ); ++ VERIFY( check_to_chars(1, "1", 10) ); ++ VERIFY( check_to_chars(1, "1", 10) ); ++ VERIFY( check_to_chars(1, "1", 10) ); ++ VERIFY( check_to_chars(1, "1", 10) ); ++ VERIFY( check_to_chars(1, "1", 10) ); ++ VERIFY( check_to_chars(1, "1", 10) ); ++ VERIFY( check_to_chars(1, "1", 10) ); ++ VERIFY( check_to_chars(1, "1", 10) ); ++ VERIFY( check_to_chars(1, "1", 10) ); ++ ++ VERIFY( check_to_chars(123, "123", 10) ); ++ VERIFY( check_to_chars(123, "123", 10) ); ++ VERIFY( check_to_chars(123, "123", 10) ); ++ VERIFY( check_to_chars(123, "123", 10) ); ++ VERIFY( check_to_chars(123, "123", 10) ); ++ VERIFY( check_to_chars(123, "123", 10) ); ++ VERIFY( check_to_chars(123, "123", 10) ); ++ VERIFY( check_to_chars(123, "123", 10) ); ++ VERIFY( check_to_chars(123, "123", 10) ); ++ VERIFY( check_to_chars(123, "123", 10) ); ++ VERIFY( check_to_chars(123, "123", 10) ); ++ ++ if constexpr (std::is_signed_v) ++ VERIFY( check_to_chars(-79, "-79", 10) ); ++ VERIFY( check_to_chars(-79, "-79", 10) ); ++ VERIFY( check_to_chars(-79, "-79", 10) ); ++ VERIFY( check_to_chars(-79, "-79", 10) ); ++ VERIFY( check_to_chars(-79, "-79", 10) ); ++ VERIFY( check_to_chars(-79, "-79", 10) ); ++ ++ using std::to_string; ++ ++ VERIFY( check_to_chars(CHAR_MAX, to_string(CHAR_MAX), 10) ); ++ VERIFY( check_to_chars(SCHAR_MAX, to_string(SCHAR_MAX), 10) ); ++ VERIFY( check_to_chars(UCHAR_MAX, to_string(UCHAR_MAX), 10) ); ++ VERIFY( check_to_chars(SHRT_MAX, to_string(SHRT_MAX), 10) ); ++ VERIFY( check_to_chars(USHRT_MAX, to_string(USHRT_MAX), 10) ); ++ VERIFY( check_to_chars(INT_MAX, to_string(INT_MAX), 10) ); ++ VERIFY( check_to_chars(UINT_MAX, to_string(UINT_MAX), 10) ); ++ VERIFY( check_to_chars(LONG_MAX, to_string(LONG_MAX), 10) ); ++ VERIFY( check_to_chars(ULONG_MAX, to_string(ULONG_MAX), 10) ); ++ VERIFY( check_to_chars(LLONG_MAX, to_string(LLONG_MAX), 10) ); ++ VERIFY( check_to_chars(ULLONG_MAX, to_string(ULLONG_MAX), 10) ); ++ ++ VERIFY( check_to_chars(CHAR_MIN, to_string(CHAR_MIN), 10) ); ++ VERIFY( check_to_chars(SCHAR_MIN, to_string(SCHAR_MIN), 10) ); ++ VERIFY( check_to_chars(SHRT_MIN, to_string(SHRT_MIN), 10) ); ++ VERIFY( check_to_chars(INT_MIN, to_string(INT_MIN), 10) ); ++ VERIFY( check_to_chars(LONG_MIN, to_string(LONG_MIN), 10) ); ++ VERIFY( check_to_chars(LLONG_MIN, to_string(LLONG_MIN), 10) ); ++ ++ VERIFY( check_to_chars(CHAR_MAX/2, to_string(CHAR_MAX/2), 10) ); ++ VERIFY( check_to_chars(SCHAR_MAX/2, to_string(SCHAR_MAX/2), 10) ); ++ VERIFY( check_to_chars(UCHAR_MAX/2, to_string(UCHAR_MAX/2), 10) ); ++ VERIFY( check_to_chars(SHRT_MAX/2, to_string(SHRT_MAX/2), 10) ); ++ VERIFY( check_to_chars(USHRT_MAX/2, to_string(USHRT_MAX/2), 10) ); ++ VERIFY( check_to_chars(INT_MAX/2, to_string(INT_MAX/2), 10) ); ++ VERIFY( check_to_chars(UINT_MAX/2, to_string(UINT_MAX/2), 10) ); ++ VERIFY( check_to_chars(LONG_MAX/2, to_string(LONG_MAX/2), 10) ); ++ VERIFY( check_to_chars(ULONG_MAX/2, to_string(ULONG_MAX/2), 10) ); ++ VERIFY( check_to_chars(LLONG_MAX/2, to_string(LLONG_MAX/2), 10) ); ++ VERIFY( check_to_chars(ULLONG_MAX/2, to_string(ULLONG_MAX/2), 10) ); ++} ++ ++// Using all bases ++void ++test03() ++{ ++ // -2017 in all bases from [2,36] ++ const char* str2017[37] = { nullptr, nullptr, ++ "-11111100001", ++ "-2202201", ++ "-133201", ++ "-31032", ++ "-13201", ++ "-5611", ++ "-3741", ++ "-2681", ++ "-2017", ++ "-1574", ++ "-1201", ++ "-bc2", ++ "-a41", ++ "-8e7", ++ "-7e1", ++ "-6gb", ++ "-641", ++ "-5b3", ++ "-50h", ++ "-4c1", ++ "-43f", ++ "-3ig", ++ "-3c1", ++ "-35h", ++ "-2pf", ++ "-2kj", ++ "-2g1", ++ "-2bg", ++ "-277", ++ "-232", ++ "-1v1", ++ "-1s4", ++ "-1pb", ++ "-1mm", ++ "-1k1" ++ }; ++ // -12345 in all bases from [2,36] ++ const char* str12345[37] = { nullptr, nullptr, ++ "-11000000111001", ++ "-121221020", ++ "-3000321", ++ "-343340", ++ "-133053", ++ "-50664", ++ "-30071", ++ "-17836", ++ "-12345", ++ "-9303", ++ "-7189", ++ "-5808", ++ "-46db", ++ "-39d0", ++ "-3039", ++ "-28c3", ++ "-221f", ++ "-1f3e", ++ "-1ah5", ++ "-16ki", ++ "-13b3", ++ "-107h", ++ "-la9", ++ "-jik", ++ "-i6l", ++ "-gp6", ++ "-fkp", ++ "-ejk", ++ "-dlf", ++ "-cq7", ++ "-c1p", ++ "-bb3", ++ "-an3", ++ "-a2p", ++ "-9ix" ++ }; ++ // -23456 in all bases from [2,36] ++ const char* str23456[37] = { nullptr, nullptr, ++ "-101101110100000", ++ "-1012011202", ++ "-11232200", ++ "-1222311", ++ "-300332", ++ "-125246", ++ "-55640", ++ "-35152", ++ "-23456", ++ "-16694", ++ "-116a8", ++ "-a8a4", ++ "-8796", ++ "-6e3b", ++ "-5ba0", ++ "-4d2d", ++ "-4072", ++ "-37ia", ++ "-2icg", ++ "-2b3k", ++ "-24a4", ++ "-1l7j", ++ "-1gh8", ++ "-1cd6", ++ "-18i4", ++ "-154k", ++ "-11pk", ++ "-rpo", ++ "-q1q", ++ "-ock", ++ "-mt0", ++ "-lhq", ++ "-k9u", ++ "-j56", ++ "-i3k" ++ }; ++ // INT_MIN in all bases from [2,36] ++ const char* strINT_MIN[37] = { nullptr, nullptr, ++ "-10000000000000000000000000000000", ++ "-12112122212110202102", ++ "-2000000000000000", ++ "-13344223434043", ++ "-553032005532", ++ "-104134211162", ++ "-20000000000", ++ "-5478773672", ++ "-2147483648", ++ "-a02220282", ++ "-4bb2308a8", ++ "-282ba4aab", ++ "-1652ca932", ++ "-c87e66b8", ++ "-80000000", ++ "-53g7f549", ++ "-3928g3h2", ++ "-27c57h33", ++ "-1db1f928", ++ "-140h2d92", ++ "-ikf5bf2", ++ "-ebelf96", ++ "-b5gge58", ++ "-8jmdnkn", ++ "-6oj8ioo", ++ "-5ehnckb", ++ "-4clm98g", ++ "-3hk7988", ++ "-2sb6cs8", ++ "-2d09uc2", ++ "-2000000", ++ "-1lsqtl2", ++ "-1d8xqrq", ++ "-15v22un", ++ "-zik0zk" ++ }; ++ ++ for (int base = 2; base <= 36; ++base) ++ { ++ VERIFY( check_to_chars(0, "0", base) ); ++ VERIFY( check_to_chars(0, "0", base) ); ++ VERIFY( check_to_chars(0, "0", base) ); ++ VERIFY( check_to_chars(0, "0", base) ); ++ VERIFY( check_to_chars(0, "0", base) ); ++ VERIFY( check_to_chars(0, "0", base) ); ++ VERIFY( check_to_chars(0, "0", base) ); ++ VERIFY( check_to_chars(0, "0", base) ); ++ VERIFY( check_to_chars(0, "0", base) ); ++ VERIFY( check_to_chars(0, "0", base) ); ++ VERIFY( check_to_chars(0, "0", base) ); ++ ++ VERIFY( check_to_chars(1, "1", base) ); ++ VERIFY( check_to_chars(1, "1", base) ); ++ VERIFY( check_to_chars(1, "1", base) ); ++ VERIFY( check_to_chars(1, "1", base) ); ++ VERIFY( check_to_chars(1, "1", base) ); ++ VERIFY( check_to_chars(1, "1", base) ); ++ VERIFY( check_to_chars(1, "1", base) ); ++ VERIFY( check_to_chars(1, "1", base) ); ++ VERIFY( check_to_chars(1, "1", base) ); ++ VERIFY( check_to_chars(1, "1", base) ); ++ VERIFY( check_to_chars(1, "1", base) ); ++ ++ if constexpr (std::is_signed_v) ++ VERIFY( check_to_chars(-1, "-1", base) ); ++ VERIFY( check_to_chars(-1, "-1", base) ); ++ VERIFY( check_to_chars(-1, "-1", base) ); ++ VERIFY( check_to_chars(-1, "-1", base) ); ++ VERIFY( check_to_chars(-1, "-1", base) ); ++ VERIFY( check_to_chars(-1, "-1", base) ); ++ ++ if (base > 2) ++ { ++ VERIFY( check_to_chars(2, "2", base) ); ++ VERIFY( check_to_chars(2, "2", base) ); ++ VERIFY( check_to_chars(2, "2", base) ); ++ VERIFY( check_to_chars(2, "2", base) ); ++ VERIFY( check_to_chars(2, "2", base) ); ++ VERIFY( check_to_chars(2, "2", base) ); ++ VERIFY( check_to_chars(2, "2", base) ); ++ VERIFY( check_to_chars(2, "2", base) ); ++ VERIFY( check_to_chars(2, "2", base) ); ++ VERIFY( check_to_chars(2, "2", base) ); ++ VERIFY( check_to_chars(2, "2", base) ); ++ ++ if constexpr (std::is_signed_v) ++ VERIFY( check_to_chars(-2, "-2", base) ); ++ VERIFY( check_to_chars(-2, "-2", base) ); ++ VERIFY( check_to_chars(-2, "-2", base) ); ++ VERIFY( check_to_chars(-2, "-2", base) ); ++ VERIFY( check_to_chars(-2, "-2", base) ); ++ VERIFY( check_to_chars(-2, "-2", base) ); ++ } ++ ++ VERIFY( check_to_chars(2017u, str2017[base]+1, base) ); ++ VERIFY( check_to_chars(2017, str2017[base]+1, base) ); ++ VERIFY( check_to_chars(-2017, str2017[base], base) ); ++ VERIFY( check_to_chars(12345u, str12345[base]+1, base) ); ++ VERIFY( check_to_chars(12345, str12345[base]+1, base) ); ++ VERIFY( check_to_chars(-12345, str12345[base], base) ); ++ VERIFY( check_to_chars(23456u, str23456[base]+1, base) ); ++ VERIFY( check_to_chars(23456, str23456[base]+1, base) ); ++ VERIFY( check_to_chars(-23456, str23456[base], base) ); ++ VERIFY( check_to_chars(INT_MAX + 1ull, strINT_MIN[base]+1, base) ); ++ VERIFY( check_to_chars(INT_MAX + 1ll, strINT_MIN[base]+1, base) ); ++ VERIFY( check_to_chars(INT_MIN, strINT_MIN[base], base) ); ++ } ++ ++ VERIFY( check_to_chars(1155, "xx", 34) ); ++ VERIFY( check_to_chars(1224, "yy", 35) ); ++ VERIFY( check_to_chars(1295, "zz", 36) ); ++} ++ ++#include ++#include ++ ++// base 8 ++void ++test04() ++{ ++ auto to_string = [](auto val) { ++ std::ostringstream ss; ++ ss << std::oct; ++ if (val < 0) ++ ss << '-' << (~val + 1ull); ++ else if (sizeof(val) == 1) ++ ss << (int)val; ++ else ++ ss << val; ++ return ss.str(); ++ }; ++ ++ VERIFY( check_to_chars(123, to_string(123), 8) ); ++ VERIFY( check_to_chars(123, to_string(123), 8) ); ++ VERIFY( check_to_chars(123, to_string(123), 8) ); ++ VERIFY( check_to_chars(123, to_string(123), 8) ); ++ VERIFY( check_to_chars(123, to_string(123), 8) ); ++ VERIFY( check_to_chars(123, to_string(123), 8) ); ++ VERIFY( check_to_chars(123, to_string(123), 8) ); ++ VERIFY( check_to_chars(123, to_string(123), 8) ); ++ VERIFY( check_to_chars(123, to_string(123), 8) ); ++ VERIFY( check_to_chars(123, to_string(123), 8) ); ++ VERIFY( check_to_chars(123, to_string(123), 8) ); ++ ++ if constexpr (std::is_signed_v) ++ 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) ); ++ 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) ); ++ ++ VERIFY( check_to_chars(CHAR_MAX, to_string(CHAR_MAX), 8) ); ++ VERIFY( check_to_chars(SCHAR_MAX, to_string(SCHAR_MAX), 8) ); ++ VERIFY( check_to_chars(UCHAR_MAX, to_string(UCHAR_MAX), 8) ); ++ VERIFY( check_to_chars(SHRT_MAX, to_string(SHRT_MAX), 8) ); ++ VERIFY( check_to_chars(USHRT_MAX, to_string(USHRT_MAX), 8) ); ++ VERIFY( check_to_chars(INT_MAX, to_string(INT_MAX), 8) ); ++ VERIFY( check_to_chars(UINT_MAX, to_string(UINT_MAX), 8) ); ++ VERIFY( check_to_chars(LONG_MAX, to_string(LONG_MAX), 8) ); ++ VERIFY( check_to_chars(ULONG_MAX, to_string(ULONG_MAX), 8) ); ++ VERIFY( check_to_chars(LLONG_MAX, to_string(LLONG_MAX), 8) ); ++ VERIFY( check_to_chars(ULLONG_MAX, to_string(ULLONG_MAX), 8) ); ++ ++ VERIFY( check_to_chars(CHAR_MIN, to_string(CHAR_MIN), 8) ); ++ VERIFY( check_to_chars(SCHAR_MIN, to_string(SCHAR_MIN), 8) ); ++ VERIFY( check_to_chars(SHRT_MIN, to_string(SHRT_MIN), 8) ); ++ VERIFY( check_to_chars(INT_MIN, to_string(INT_MIN), 8) ); ++ VERIFY( check_to_chars(LONG_MIN, to_string(LONG_MIN), 8) ); ++ VERIFY( check_to_chars(LLONG_MIN, to_string(LLONG_MIN), 8) ); ++ ++ VERIFY( check_to_chars(CHAR_MAX/2, to_string(CHAR_MAX/2), 8) ); ++ VERIFY( check_to_chars(SCHAR_MAX/2, to_string(SCHAR_MAX/2), 8) ); ++ VERIFY( check_to_chars(UCHAR_MAX/2, to_string(UCHAR_MAX/2), 8) ); ++ VERIFY( check_to_chars(SHRT_MAX/2, to_string(SHRT_MAX/2), 8) ); ++ VERIFY( check_to_chars(USHRT_MAX/2, to_string(USHRT_MAX/2), 8) ); ++ VERIFY( check_to_chars(INT_MAX/2, to_string(INT_MAX/2), 8) ); ++ VERIFY( check_to_chars(UINT_MAX/2, to_string(UINT_MAX/2), 8) ); ++ VERIFY( check_to_chars(LONG_MAX/2, to_string(LONG_MAX/2), 8) ); ++ VERIFY( check_to_chars(ULONG_MAX/2, to_string(ULONG_MAX/2), 8) ); ++ VERIFY( check_to_chars(LLONG_MAX/2, to_string(LLONG_MAX/2), 8) ); ++ VERIFY( check_to_chars(ULLONG_MAX/2, to_string(ULLONG_MAX/2), 8) ); ++} ++ ++// base 16 ++void ++test05() ++{ ++ auto to_string = [](auto val) { ++ std::ostringstream ss; ++ ss << std::hex; ++ if (val < 0) ++ ss << '-' << (~val + 1ull); ++ else if (sizeof(val) == 1) ++ ss << (int)val; ++ else ++ ss << val; ++ return ss.str(); ++ }; ++ ++ VERIFY( check_to_chars(123, to_string(123), 16) ); ++ VERIFY( check_to_chars(123, to_string(123), 16) ); ++ VERIFY( check_to_chars(123, to_string(123), 16) ); ++ VERIFY( check_to_chars(123, to_string(123), 16) ); ++ VERIFY( check_to_chars(123, to_string(123), 16) ); ++ VERIFY( check_to_chars(123, to_string(123), 16) ); ++ VERIFY( check_to_chars(123, to_string(123), 16) ); ++ VERIFY( check_to_chars(123, to_string(123), 16) ); ++ VERIFY( check_to_chars(123, to_string(123), 16) ); ++ VERIFY( check_to_chars(123, to_string(123), 16) ); ++ VERIFY( check_to_chars(123, to_string(123), 16) ); ++ ++ if constexpr (std::is_signed_v) ++ 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) ); ++ 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) ); ++ ++ VERIFY( check_to_chars(CHAR_MAX, to_string(CHAR_MAX), 16) ); ++ VERIFY( check_to_chars(SCHAR_MAX, to_string(SCHAR_MAX), 16) ); ++ VERIFY( check_to_chars(UCHAR_MAX, to_string(UCHAR_MAX), 16) ); ++ VERIFY( check_to_chars(SHRT_MAX, to_string(SHRT_MAX), 16) ); ++ VERIFY( check_to_chars(USHRT_MAX, to_string(USHRT_MAX), 16) ); ++ VERIFY( check_to_chars(INT_MAX, to_string(INT_MAX), 16) ); ++ VERIFY( check_to_chars(UINT_MAX, to_string(UINT_MAX), 16) ); ++ VERIFY( check_to_chars(LONG_MAX, to_string(LONG_MAX), 16) ); ++ VERIFY( check_to_chars(ULONG_MAX, to_string(ULONG_MAX), 16) ); ++ VERIFY( check_to_chars(LLONG_MAX, to_string(LLONG_MAX), 16) ); ++ VERIFY( check_to_chars(ULLONG_MAX, to_string(ULLONG_MAX), 16) ); ++ ++ VERIFY( check_to_chars(CHAR_MIN, to_string(CHAR_MIN), 16) ); ++ VERIFY( check_to_chars(SCHAR_MIN, to_string(SCHAR_MIN), 16) ); ++ VERIFY( check_to_chars(SHRT_MIN, to_string(SHRT_MIN), 16) ); ++ VERIFY( check_to_chars(INT_MIN, to_string(INT_MIN), 16) ); ++ VERIFY( check_to_chars(LONG_MIN, to_string(LONG_MIN), 16) ); ++ VERIFY( check_to_chars(LLONG_MIN, to_string(LLONG_MIN), 16) ); ++ ++ VERIFY( check_to_chars(CHAR_MAX/2, to_string(CHAR_MAX/2), 16) ); ++ VERIFY( check_to_chars(SCHAR_MAX/2, to_string(SCHAR_MAX/2), 16) ); ++ VERIFY( check_to_chars(UCHAR_MAX/2, to_string(UCHAR_MAX/2), 16) ); ++ VERIFY( check_to_chars(SHRT_MAX/2, to_string(SHRT_MAX/2), 16) ); ++ VERIFY( check_to_chars(USHRT_MAX/2, to_string(USHRT_MAX/2), 16) ); ++ VERIFY( check_to_chars(INT_MAX/2, to_string(INT_MAX/2), 16) ); ++ VERIFY( check_to_chars(UINT_MAX/2, to_string(UINT_MAX/2), 16) ); ++ VERIFY( check_to_chars(LONG_MAX/2, to_string(LONG_MAX/2), 16) ); ++ VERIFY( check_to_chars(ULONG_MAX/2, to_string(ULONG_MAX/2), 16) ); ++ VERIFY( check_to_chars(LLONG_MAX/2, to_string(LLONG_MAX/2), 16) ); ++ VERIFY( check_to_chars(ULLONG_MAX/2, to_string(ULLONG_MAX/2), 16) ); ++} ++ ++#include ++ ++// base 2 ++void ++test06() ++{ ++ auto to_string = [](auto val) { ++ std::string s, sign; ++ if (val < 0) ++ { ++ auto absval = ~val + 1ull; ++ s = std::bitset(absval).to_string(); ++ sign = '-'; ++ } ++ else ++ s = std::bitset(val).to_string(); ++ auto pos = s.find_first_not_of("0"); ++ if (pos == std::string::npos) ++ s.resize(1); ++ else ++ s.erase(0, pos); ++ return sign + s; ++ }; ++ ++ VERIFY( check_to_chars(123, to_string(123), 2) ); ++ VERIFY( check_to_chars(123, to_string(123), 2) ); ++ VERIFY( check_to_chars(123, to_string(123), 2) ); ++ VERIFY( check_to_chars(123, to_string(123), 2) ); ++ VERIFY( check_to_chars(123, to_string(123), 2) ); ++ VERIFY( check_to_chars(123, to_string(123), 2) ); ++ VERIFY( check_to_chars(123, to_string(123), 2) ); ++ VERIFY( check_to_chars(123, to_string(123), 2) ); ++ VERIFY( check_to_chars(123, to_string(123), 2) ); ++ VERIFY( check_to_chars(123, to_string(123), 2) ); ++ VERIFY( check_to_chars(123, to_string(123), 2) ); ++ ++ if constexpr (std::is_signed_v) ++ 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) ); ++ 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) ); ++ ++ VERIFY( check_to_chars(CHAR_MAX, to_string(CHAR_MAX), 2) ); ++ VERIFY( check_to_chars(SCHAR_MAX, to_string(SCHAR_MAX), 2) ); ++ VERIFY( check_to_chars(UCHAR_MAX, to_string(UCHAR_MAX), 2) ); ++ VERIFY( check_to_chars(SHRT_MAX, to_string(SHRT_MAX), 2) ); ++ VERIFY( check_to_chars(USHRT_MAX, to_string(USHRT_MAX), 2) ); ++ VERIFY( check_to_chars(INT_MAX, to_string(INT_MAX), 2) ); ++ VERIFY( check_to_chars(UINT_MAX, to_string(UINT_MAX), 2) ); ++ VERIFY( check_to_chars(LONG_MAX, to_string(LONG_MAX), 2) ); ++ VERIFY( check_to_chars(ULONG_MAX, to_string(ULONG_MAX), 2) ); ++ VERIFY( check_to_chars(LLONG_MAX, to_string(LLONG_MAX), 2) ); ++ VERIFY( check_to_chars(ULLONG_MAX, to_string(ULLONG_MAX), 2) ); ++ ++ VERIFY( check_to_chars(CHAR_MIN, to_string(CHAR_MIN), 2) ); ++ VERIFY( check_to_chars(SCHAR_MIN, to_string(SCHAR_MIN), 2) ); ++ VERIFY( check_to_chars(SHRT_MIN, to_string(SHRT_MIN), 2) ); ++ VERIFY( check_to_chars(INT_MIN, to_string(INT_MIN), 2) ); ++ VERIFY( check_to_chars(LONG_MIN, to_string(LONG_MIN), 2) ); ++ VERIFY( check_to_chars(LLONG_MIN, to_string(LLONG_MIN), 2) ); ++ ++ VERIFY( check_to_chars(CHAR_MAX/2, to_string(CHAR_MAX/2), 2) ); ++ VERIFY( check_to_chars(SCHAR_MAX/2, to_string(SCHAR_MAX/2), 2) ); ++ VERIFY( check_to_chars(UCHAR_MAX/2, to_string(UCHAR_MAX/2), 2) ); ++ VERIFY( check_to_chars(SHRT_MAX/2, to_string(SHRT_MAX/2), 2) ); ++ VERIFY( check_to_chars(USHRT_MAX/2, to_string(USHRT_MAX/2), 2) ); ++ VERIFY( check_to_chars(INT_MAX/2, to_string(INT_MAX/2), 2) ); ++ VERIFY( check_to_chars(UINT_MAX/2, to_string(UINT_MAX/2), 2) ); ++ VERIFY( check_to_chars(LONG_MAX/2, to_string(LONG_MAX/2), 2) ); ++ VERIFY( check_to_chars(ULONG_MAX/2, to_string(ULONG_MAX/2), 2) ); ++ VERIFY( check_to_chars(LLONG_MAX/2, to_string(LLONG_MAX/2), 2) ); ++ VERIFY( check_to_chars(ULLONG_MAX/2, to_string(ULLONG_MAX/2), 2) ); ++} ++ ++int ++main() ++{ ++ test01(); ++ test02(); ++ test03(); ++ test04(); ++ test05(); ++ test06(); ++} +diff --git a/libstdc++-v3/testsuite/20_util/to_chars/1_neg.cc b/libstdc++-v3/testsuite/20_util/to_chars/1_neg.cc +new file mode 100644 +index 00000000000..8302b250cd0 +--- /dev/null ++++ b/libstdc++-v3/testsuite/20_util/to_chars/1_neg.cc +@@ -0,0 +1,35 @@ ++// Copyright (C) 2017 Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 3, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// You should have received a copy of the GNU General Public License along ++// with this library; see the file COPYING3. If not see ++// . ++ ++// { dg-options "-std=gnu++17" } ++// { dg-do compile { target c++17 } } ++ ++#include ++ ++void ++test01(char* first, char* last) ++{ ++#if _GLIBCXX_USE_WCHAR_T ++ std::to_chars(first, last, L'\x1'); // { dg-error "no matching" } ++ std::to_chars(first, last, L'\x1', 10); // { dg-error "no matching" } ++#endif ++ ++ std::to_chars(first, last, u'\x1'); // { dg-error "no matching" } ++ std::to_chars(first, last, u'\x1', 10); // { dg-error "no matching" } ++ std::to_chars(first, last, U'\x1'); // { dg-error "no matching" } ++ std::to_chars(first, last, U'\x1', 10); // { dg-error "no matching" } ++} +diff --git a/libstdc++-v3/testsuite/20_util/to_chars/2.cc b/libstdc++-v3/testsuite/20_util/to_chars/2.cc +new file mode 100644 +index 00000000000..b28320cc7b8 +--- /dev/null ++++ b/libstdc++-v3/testsuite/20_util/to_chars/2.cc +@@ -0,0 +1,78 @@ ++// Copyright (C) 2017 Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 3, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// You should have received a copy of the GNU General Public License along ++// with this library; see the file COPYING3. If not see ++// . ++ ++// { dg-options "-std=gnu++17" } ++// { dg-do run { target c++17 } } ++ ++#include ++#include ++ ++// Test std::to_chars error handling. ++ ++void ++test01() ++{ ++ char buf[9] = "********"; ++ std::to_chars_result r; ++ ++ r = std::to_chars(buf, buf, 1); ++ VERIFY( r.ec == std::errc::value_too_large ); ++ VERIFY( r.ptr == buf ); ++ VERIFY( *r.ptr == '*' ); ++ ++ r = std::to_chars(buf, buf + 3, 0b1000, 2); ++ VERIFY( r.ec == std::errc::value_too_large ); ++ VERIFY( r.ptr == buf + 3 ); ++ VERIFY( *r.ptr == '*' ); ++ r = std::to_chars(buf, buf + 4, 0b1000, 2); ++ VERIFY( r.ec == std::errc{} ); ++ VERIFY( r.ptr == buf + 4 ); ++ VERIFY( *r.ptr == '*' ); ++ ++ r = std::to_chars(buf, buf + 4, 010000, 8); ++ VERIFY( r.ec == std::errc::value_too_large ); ++ VERIFY( r.ptr == buf + 4 ); ++ VERIFY( *r.ptr == '*' ); ++ r = std::to_chars(buf, buf + 5, 010000, 8); ++ VERIFY( r.ec == std::errc{} ); ++ VERIFY( r.ptr == buf + 5 ); ++ VERIFY( *r.ptr == '*' ); ++ ++ r = std::to_chars(buf, buf + 5, 100000, 10); ++ VERIFY( r.ec == std::errc::value_too_large ); ++ VERIFY( r.ptr == buf + 5 ); ++ VERIFY( *r.ptr == '*' ); ++ r = std::to_chars(buf, buf + 6, 100000, 10); ++ VERIFY( r.ec == std::errc{} ); ++ VERIFY( r.ptr == buf + 6 ); ++ VERIFY( *r.ptr == '*' ); ++ ++ r = std::to_chars(buf, buf + 6, 0x1000000, 16); ++ VERIFY( r.ec == std::errc::value_too_large ); ++ VERIFY( r.ptr == buf + 6 ); ++ VERIFY( *r.ptr == '*' ); ++ r = std::to_chars(buf, buf + 7, 0x1000000, 16); ++ VERIFY( r.ec == std::errc{} ); ++ VERIFY( r.ptr == buf + 7 ); ++ VERIFY( *r.ptr == '*' ); ++} ++ ++int ++main() ++{ ++ test01(); ++} +diff --git a/libstdc++-v3/testsuite/20_util/to_chars/requirements.cc b/libstdc++-v3/testsuite/20_util/to_chars/requirements.cc +new file mode 100644 +index 00000000000..d50588bd902 +--- /dev/null ++++ b/libstdc++-v3/testsuite/20_util/to_chars/requirements.cc +@@ -0,0 +1,49 @@ ++// Copyright (C) 2017 Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 3, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// You should have received a copy of the GNU General Public License along ++// with this library; see the file COPYING3. If not see ++// . ++ ++// { dg-options "-std=gnu++17" } ++// { dg-do compile { target c++17 } } ++ ++#include ++ ++namespace std ++{ ++ struct to_chars_result; ++ ++ char* to_chars_result::*pm2 = &to_chars_result::ptr; ++ errc to_chars_result::*pm1 = &to_chars_result::ec; ++ ++ to_chars_result (*f1)(char*, char*, char, int) = &to_chars; ++ to_chars_result (*f2)(char*, char*, signed char, int) = &to_chars; ++ to_chars_result (*f3)(char*, char*, unsigned char, int) = &to_chars; ++ to_chars_result (*f4)(char*, char*, signed short, int) = &to_chars; ++ to_chars_result (*f5)(char*, char*, unsigned short, int) = &to_chars; ++ to_chars_result (*f6)(char*, char*, signed int, int) = &to_chars; ++ to_chars_result (*f7)(char*, char*, unsigned int, int) = &to_chars; ++ to_chars_result (*f8)(char*, char*, signed long, int) = &to_chars; ++ to_chars_result (*f9)(char*, char*, unsigned long, int) = &to_chars; ++ to_chars_result (*f10)(char*, char*, signed long long, int) = &to_chars; ++ to_chars_result (*f11)(char*, char*, unsigned long long, int) = &to_chars; ++} ++ ++void bind() ++{ ++ char buf[1]; ++ auto [p, e] = std::to_chars(buf, buf + 1, 1, 10); ++ char** pa = &p; ++ std::errc* ea = &e; ++} + + +diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv +index b8221e4e434..e5d6c106f70 100644 +--- a/libstdc++-v3/include/std/charconv ++++ b/libstdc++-v3/include/std/charconv +@@ -81,7 +81,11 @@ namespace __detail + #if _GLIBCXX_USE_INT128 + conditional_t<(sizeof(_Tp) <= sizeof(__int128)), unsigned __int128, + #endif +- void>>>>; ++ void ++#if _GLIBCXX_USE_INT128 ++ > ++#endif ++ >>>; + + // Generic implementation for arbitrary bases. + template + + +diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c +index 8984613aa41..9a548d29bbc 100644 +--- a/gcc/cp/constexpr.c ++++ b/gcc/cp/constexpr.c +@@ -5726,7 +5726,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, + return RECUR (TREE_OPERAND (t, 1), want_rval); + + case TARGET_EXPR: +- if (!literal_type_p (TREE_TYPE (t))) ++ if (!TARGET_EXPR_DIRECT_INIT_P (t) ++ && !literal_type_p (TREE_TYPE (t))) + { + if (flags & tf_error) + { +diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-list2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-list2.C +new file mode 100644 +index 00000000000..780a64dbbc4 +--- /dev/null ++++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-list2.C +@@ -0,0 +1,20 @@ ++// PR c++/82461 ++// { dg-do compile { target c++11 } } ++ ++class A { ++private: ++public: ++ constexpr A() {} ++ ~A() {} ++}; ++ ++class B { ++private: ++ A a; ++public: ++ constexpr B() : a{} {} ++// works ++// constexpr B() : a() {} ++ ++ ~B() {} ++}; + + +diff --git a/gcc/cp/call.c b/gcc/cp/call.c +index 5698ff60a4d..d3d0966f65c 100644 +--- a/gcc/cp/call.c ++++ b/gcc/cp/call.c +@@ -8834,6 +8834,9 @@ build_special_member_call (tree instance, tree name, vec **args, + { + if (is_dummy_object (instance)) + return arg; ++ else if (TREE_CODE (arg) == TARGET_EXPR) ++ TARGET_EXPR_DIRECT_INIT_P (arg) = true; ++ + if ((complain & tf_error) + && (flags & LOOKUP_DELEGATING_CONS)) + check_self_delegation (arg); +diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor21.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor21.C +new file mode 100644 +index 00000000000..4bf57b9e897 +--- /dev/null ++++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor21.C +@@ -0,0 +1,15 @@ ++// PR c++/83835 ++// { dg-do compile { target c++11 } } ++ ++struct Z ++{ ++ void const * p_; ++ constexpr Z( void const * p ): p_( p ) {} ++ ~Z(); ++}; ++ ++struct Y ++{ ++ Z z_; ++ constexpr Y() noexcept: z_( this ) {} ++}; + + +diff --git a/gcc/cp/call.c b/gcc/cp/call.c +index 4903119adca..37902991f3f 100644 +--- a/gcc/cp/call.c ++++ b/gcc/cp/call.c +@@ -101,7 +101,7 @@ struct conversion { + /* If KIND is ck_ref_bind, true when either an lvalue reference is + being bound to an lvalue expression or an rvalue reference is + being bound to an rvalue expression. If KIND is ck_rvalue, +- true when we should treat an lvalue as an rvalue (12.8p33). If ++ true when we are treating an lvalue as an rvalue (12.8p33). If + KIND is ck_base, always false. */ + BOOL_BITFIELD rvaluedness_matches_p: 1; + BOOL_BITFIELD check_narrowing: 1; +@@ -1161,6 +1161,7 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, + } + conv = build_conv (ck_rvalue, from, conv); + if (flags & LOOKUP_PREFER_RVALUE) ++ /* Tell convert_like_real to set LOOKUP_PREFER_RVALUE. */ + conv->rvaluedness_matches_p = true; + } + +@@ -1629,11 +1630,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, + conv = build_identity_conv (tfrom, expr); + conv = direct_reference_binding (rto, conv); + +- if (flags & LOOKUP_PREFER_RVALUE) +- /* The top-level caller requested that we pretend that the lvalue +- be treated as an rvalue. */ +- conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto); +- else if (TREE_CODE (rfrom) == REFERENCE_TYPE) ++ if (TREE_CODE (rfrom) == REFERENCE_TYPE) + /* Handle rvalue reference to function properly. */ + conv->rvaluedness_matches_p + = (TYPE_REF_IS_RVALUE (rto) == TYPE_REF_IS_RVALUE (rfrom)); +@@ -1659,8 +1656,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, + /* Don't allow binding of lvalues (other than function lvalues) to + rvalue references. */ + if (is_lvalue && TYPE_REF_IS_RVALUE (rto) +- && TREE_CODE (to) != FUNCTION_TYPE +- && !(flags & LOOKUP_PREFER_RVALUE)) ++ && TREE_CODE (to) != FUNCTION_TYPE) + conv->bad_p = true; + + /* Nor the reverse. */ +@@ -7716,6 +7713,19 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) + ++arg_index; + parm = TREE_CHAIN (parm); + } ++ ++ if (flags & LOOKUP_PREFER_RVALUE) ++ { ++ /* The implicit move specified in 15.8.3/3 fails "...if the type of ++ the first parameter of the selected constructor is not an rvalue ++ reference to the object’s type (possibly cv-qualified)...." */ ++ gcc_assert (!(complain & tf_error)); ++ tree ptype = convs[0]->type; ++ if (TREE_CODE (ptype) != REFERENCE_TYPE ++ || !TYPE_REF_IS_RVALUE (ptype) ++ || CONVERSION_RANK (convs[0]) > cr_exact) ++ return error_mark_node; ++ } + } + /* Bypass access control for 'this' parameter. */ + else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) +diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h +index 3a0bd1687e8..6c4153d558b 100644 +--- a/gcc/cp/cp-tree.h ++++ b/gcc/cp/cp-tree.h +@@ -5296,7 +5296,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; + (Normally, these entities are registered in the symbol table, but + not found by lookup.) */ + #define LOOKUP_HIDDEN (LOOKUP_PREFER_NAMESPACES << 1) +-/* Prefer that the lvalue be treated as an rvalue. */ ++/* We're trying to treat an lvalue as an rvalue. */ + #define LOOKUP_PREFER_RVALUE (LOOKUP_HIDDEN << 1) + /* We're inside an init-list, so narrowing conversions are ill-formed. */ + #define LOOKUP_NO_NARROWING (LOOKUP_PREFER_RVALUE << 1) +diff --git a/gcc/cp/except.c b/gcc/cp/except.c +index 208e52a405b..b25b91b97be 100644 +--- a/gcc/cp/except.c ++++ b/gcc/cp/except.c +@@ -665,6 +665,7 @@ build_throw (tree exp) + { + int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING; + vec *exp_vec; ++ bool converted = false; + + /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes + treated as an rvalue for the purposes of overload resolution +@@ -675,14 +676,31 @@ build_throw (tree exp) + && ! TREE_STATIC (exp) + /* The variable must not have the `volatile' qualifier. */ + && !(cp_type_quals (TREE_TYPE (exp)) & TYPE_QUAL_VOLATILE)) +- flags = flags | LOOKUP_PREFER_RVALUE; ++ { ++ tree moved = move (exp); ++ exp_vec = make_tree_vector_single (moved); ++ moved = (build_special_member_call ++ (object, complete_ctor_identifier, &exp_vec, ++ TREE_TYPE (object), flags|LOOKUP_PREFER_RVALUE, ++ tf_none)); ++ release_tree_vector (exp_vec); ++ if (moved != error_mark_node) ++ { ++ exp = moved; ++ converted = true; ++ } ++ } + + /* Call the copy constructor. */ +- exp_vec = make_tree_vector_single (exp); +- exp = (build_special_member_call +- (object, complete_ctor_identifier, &exp_vec, +- TREE_TYPE (object), flags, tf_warning_or_error)); +- release_tree_vector (exp_vec); ++ if (!converted) ++ { ++ exp_vec = make_tree_vector_single (exp); ++ exp = (build_special_member_call ++ (object, complete_ctor_identifier, &exp_vec, ++ TREE_TYPE (object), flags, tf_warning_or_error)); ++ release_tree_vector (exp_vec); ++ } ++ + if (exp == error_mark_node) + { + error (" in thrown expression"); +diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c +index 3ce39061010..a5a363bc942 100644 +--- a/gcc/cp/typeck.c ++++ b/gcc/cp/typeck.c +@@ -9156,6 +9156,7 @@ check_return_expr (tree retval, bool *no_warning) + + Note that these conditions are similar to, but not as strict as, + the conditions for the named return value optimization. */ ++ bool converted = false; + if ((cxx_dialect != cxx98) + && ((VAR_P (retval) && !DECL_HAS_VALUE_EXPR_P (retval)) + || TREE_CODE (retval) == PARM_DECL) +@@ -9163,14 +9164,25 @@ check_return_expr (tree retval, bool *no_warning) + && !TREE_STATIC (retval) + /* This is only interesting for class type. */ + && CLASS_TYPE_P (functype)) +- flags = flags | LOOKUP_PREFER_RVALUE; ++ { ++ tree moved = move (retval); ++ moved = convert_for_initialization ++ (NULL_TREE, functype, moved, flags|LOOKUP_PREFER_RVALUE, ++ ICR_RETURN, NULL_TREE, 0, tf_none); ++ if (moved != error_mark_node) ++ { ++ retval = moved; ++ converted = true; ++ } ++ } + + /* First convert the value to the function's return type, then + to the type of return value's location to handle the + case that functype is smaller than the valtype. */ +- retval = convert_for_initialization +- (NULL_TREE, functype, retval, flags, ICR_RETURN, NULL_TREE, 0, +- tf_warning_or_error); ++ if (!converted) ++ retval = convert_for_initialization ++ (NULL_TREE, functype, retval, flags, ICR_RETURN, NULL_TREE, 0, ++ tf_warning_or_error); + retval = convert (valtype, retval); + + /* If the conversion failed, treat this just like `return;'. */ +diff --git a/gcc/testsuite/g++.dg/cpp0x/move-return1.C b/gcc/testsuite/g++.dg/cpp0x/move-return1.C +new file mode 100644 +index 00000000000..dc2b313fee6 +--- /dev/null ++++ b/gcc/testsuite/g++.dg/cpp0x/move-return1.C +@@ -0,0 +1,22 @@ ++// PR c++/80452 ++// { dg-do compile { target c++11 } } ++ ++template struct check { }; ++template struct check; ++ ++struct A { ++ A() = default; ++ A(A&&) = default; ++ A(const A&) = delete; ++}; ++ ++template ++struct B { ++ template B(U&&) { check u; } ++}; ++ ++B f() ++{ ++ A a; ++ return a; ++} diff --git a/gcc.spec b/gcc.spec index 44af5834a6bcb123ddbe46243a058972320b824a..012b86f764f7b2868374d0622b8255b93d78eaca 100644 --- a/gcc.spec +++ b/gcc.spec @@ -41,7 +41,7 @@ Version: 7.3.0 # number 2020033101 meaning the openEuler 20.03 release date plus 01 to # replace DATE and will never change it in the future. %global openEulerDATE 2020033101 -Release: %{openEulerDATE}.49 +Release: %{openEulerDATE}.50 License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ with exceptions and LGPLv2+ and BSD Group: Development/Languages #Source0: hcc-aarch64-linux-release.tar.bz2 @@ -96,6 +96,7 @@ Patch39: fix-PR83666-punt-BLKmode-when-expand_debug_expr.patch Patch40: fix-AArch64-128-bit-immediate-ICEs.patch Patch41: PR-c-83227-C-17-ICE-with-init-list-derived.patch Patch42: Remove-_GLIBCXX_USE_INT128-autoconf-macro.patch +Patch43: add-support-for-C++17-std__to_chars-and-std__from_chars.patch #AutoReqProv: off AutoReq: true @@ -582,6 +583,7 @@ package or when debugging this package. %patch40 -p1 %patch41 -p1 %patch42 -p1 +%patch43 -p1 %if 0%{?_enable_debug_packages} cat > split-debuginfo.sh <<\EOF @@ -3338,6 +3340,10 @@ fi %changelog +* Sun May 08 2022 dingguangya - 7.3.0-2020033101.50 +- add-support-for-C++17-std__to_chars-and-std__from_chars.patch: New patch for bugfix +- gcc.spec: Add new patch + * Wed Apr 20 2022 benniaobufeijiushiji - 7.3.0-2020033101.49 - gcc.spec: Bugfix for removing Date in release version, use a const number instead.