From 72c6ac6f529f879a8a45917e3de92575f76ba797 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 10 Feb 2023 11:30:33 -0800 Subject: [PATCH 01/25] Add specific overloads --- include/boost/charconv/to_chars.hpp | 80 +++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/include/boost/charconv/to_chars.hpp b/include/boost/charconv/to_chars.hpp index 76f1ea4..d9e91ac 100644 --- a/include/boost/charconv/to_chars.hpp +++ b/include/boost/charconv/to_chars.hpp @@ -433,31 +433,81 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char return {first + num_chars, 0}; } -} // Namespace detail - -template ::value, bool>::type = true> +template BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, Integer value, int base = 10) noexcept { if (base == 10) { - #ifdef BOOST_CHARCONV_HAS_INT128 - BOOST_IF_CONSTEXPR(std::is_same::value || std::is_same::value) - { - return detail::to_chars_128integer_impl(first, last, value); - } - else - #endif - { - return detail::to_chars_integer_impl(first, last, value); - } + return detail::to_chars_integer_impl(first, last, value); } return detail::to_chars_integer_impl(first, last, value, base); } -template <> -BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, bool value, int base) noexcept = delete; +#ifdef BOOST_CHARCONV_HAS_INT128 +template +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars128(char* first, char* last, Integer value, int base = 10) noexcept +{ + if (base == 10) + { + return to_chars_128integer_impl(first, last, value); + } + return to_chars_integer_impl(first, last, value, base); +} +#endif + +} // Namespace detail + +// integer overloads +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, bool value, int base) noexcept = delete; +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, char value, int base = 10) noexcept +{ + return detail::to_chars(first, last, value, base); +} +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, signed char value, int base = 10) noexcept +{ + return detail::to_chars(first, last, value, base); +} +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned char value, int base = 10) noexcept +{ + return detail::to_chars(first, last, value, base); +} +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, int value, int base = 10) noexcept +{ + return detail::to_chars(first, last, value, base); +} +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned int value, int base = 10) noexcept +{ + return detail::to_chars(first, last, value, base); +} +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, long value, int base = 10) noexcept +{ + return detail::to_chars(first, last, value, base); +} +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned long value, int base = 10) noexcept +{ + return detail::to_chars(first, last, value, base); +} +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, long long value, int base = 10) noexcept +{ + return detail::to_chars(first, last, value, base); +} +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned long long value, int base = 10) noexcept +{ + return detail::to_chars(first, last, value, base); +} + +#ifdef BOOST_CHARCONV_HAS_INT128 +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, boost::int128_type value, int base = 10) noexcept +{ + return detail::to_chars128(first, last, value, base); +} +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, boost::uint128_type value, int base = 10) noexcept +{ + return detail::to_chars128(first, last, value, base); +} +#endif // floating point overloads BOOST_CHARCONV_DECL to_chars_result to_chars( char* first, char* last, float value ) noexcept; From 4cf3d9e3296b250ea4005ec254ee12609089f5bb Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 10 Feb 2023 11:30:53 -0800 Subject: [PATCH 02/25] Remove requirement for __STRICT_ANSI__ --- include/boost/charconv/config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/charconv/config.hpp b/include/boost/charconv/config.hpp index 454cc80..c753aa6 100644 --- a/include/boost/charconv/config.hpp +++ b/include/boost/charconv/config.hpp @@ -46,7 +46,7 @@ #endif // Use 128 bit integers and supress warnings for using extensions -#if defined(BOOST_HAS_INT128) && !defined(__STRICT_ANSI__) +#if defined(BOOST_HAS_INT128) # define BOOST_CHARCONV_HAS_INT128 #endif From 85444fa3f439c3cd602fe2f1f4ab51d03cdd4d9f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 10 Feb 2023 12:05:40 -0800 Subject: [PATCH 03/25] Fixes for to_chars --- include/boost/charconv/to_chars.hpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/include/boost/charconv/to_chars.hpp b/include/boost/charconv/to_chars.hpp index d9e91ac..3272090 100644 --- a/include/boost/charconv/to_chars.hpp +++ b/include/boost/charconv/to_chars.hpp @@ -251,12 +251,12 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c } // Strip the sign from the value and apply at the end after parsing if the type is signed - BOOST_IF_CONSTEXPR (std::is_signed::value) + BOOST_IF_CONSTEXPR (std::is_same::value) { if (value < 0) { is_negative = true; - unsigned_value = apply_sign(value); + unsigned_value = -(static_cast(value)); } else { @@ -270,12 +270,6 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c auto converted_value = static_cast(unsigned_value); - // If the value fits into 64 bits use the other method of processing - if (converted_value < (std::numeric_limits::max)()) - { - return to_chars_integer_impl(first, last, value); - } - const int converted_value_digits = num_digits(converted_value); if (converted_value_digits > user_buffer_size) @@ -288,6 +282,12 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c *first++ = '-'; } + // If the value fits into 64 bits use the other method of processing + if (converted_value < (std::numeric_limits::max)()) + { + return to_chars_integer_impl(first, last, static_cast(value)); + } + constexpr std::uint32_t ten_9 = UINT32_C(1000000000); char buffer[5][10] {}; int num_chars[5] {}; @@ -323,13 +323,11 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c // All other bases // Use a simple lookup table to put together the Integer in character form -template +template BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char* last, Integer value, int base) noexcept { BOOST_CHARCONV_ASSERT_MSG(base >= 2 && base <= 36, "Base must be between 2 and 36 (inclusive)"); - using Unsigned_Integer = typename std::make_unsigned::type; - const std::ptrdiff_t output_length = last - first; if (!(first <= last)) @@ -351,7 +349,7 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char if (value < 0) { *first++ = '-'; - unsigned_value = apply_sign(value); + unsigned_value = -(static_cast(value)); } else { @@ -436,12 +434,13 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char template BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, Integer value, int base = 10) noexcept { + using Unsigned_Integer = typename std::make_unsigned::type; if (base == 10) { return detail::to_chars_integer_impl(first, last, value); } - return detail::to_chars_integer_impl(first, last, value, base); + return detail::to_chars_integer_impl(first, last, value, base); } #ifdef BOOST_CHARCONV_HAS_INT128 @@ -453,7 +452,7 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars128(char* first, char* last, In return to_chars_128integer_impl(first, last, value); } - return to_chars_integer_impl(first, last, value, base); + return to_chars_integer_impl(first, last, value, base); } #endif From 60c9233f5268111ecead5fd9b9a5a13c6389fad8 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 08:50:30 -0800 Subject: [PATCH 04/25] Add short overloads --- include/boost/charconv/to_chars.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/boost/charconv/to_chars.hpp b/include/boost/charconv/to_chars.hpp index 3272090..e57cf9a 100644 --- a/include/boost/charconv/to_chars.hpp +++ b/include/boost/charconv/to_chars.hpp @@ -472,6 +472,14 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsig { return detail::to_chars(first, last, value, base); } +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, short value, int base = 10) noexcept +{ + return detail::to_chars(first, last, value, base); +} +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, unsigned short value, int base = 10) noexcept +{ + return detail::to_chars(first, last, value, base); +} BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, int value, int base = 10) noexcept { return detail::to_chars(first, last, value, base); From c902e09e091e9f317ce11988adf1293683d2bcfa Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 08:59:33 -0800 Subject: [PATCH 05/25] Add macros for numeric limits of (u)int128 --- include/boost/charconv/config.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/boost/charconv/config.hpp b/include/boost/charconv/config.hpp index c753aa6..31f0c3c 100644 --- a/include/boost/charconv/config.hpp +++ b/include/boost/charconv/config.hpp @@ -7,6 +7,7 @@ // https://www.boost.org/LICENSE_1_0.txt #include +#include // This header implements separate compilation features as described in // http://www.boost.org/more/separate_compilation.html @@ -48,6 +49,15 @@ // Use 128 bit integers and supress warnings for using extensions #if defined(BOOST_HAS_INT128) # define BOOST_CHARCONV_HAS_INT128 +# define BOOST_CHARCONV_INT128_MAX (boost::int128_type)(((boost::uint128_type) 1 << 127) - 1) +# define BOOST_CHARCONV_INT128_MIN (-BOOST_CHARCONV_INT128_MAX - 1) +# define BOOST_CHARCONV_UINT128_MAX ((2 * (boost::uint128_type) BOOST_CHARCONV_INT128_MAX) + 1) +#endif + +#if defined(__GNUC__) && __GNUC__ == 5 +# define BOOST_CHARCONV_GCC5_CONSTEXPR inline +#else +# define BOOST_CHARCONV_GCC5_CONSTEXPR BOOST_CXX14_CONSTEXPR #endif #endif // BOOST_CHARCONV_CONFIG_HPP_INCLUDED From f189277046ed418fe7b225f2421f145e02f37bbf Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 09:00:03 -0800 Subject: [PATCH 06/25] Add specific type overloads --- include/boost/charconv/from_chars.hpp | 94 ++++++++++++++++++++------- 1 file changed, 72 insertions(+), 22 deletions(-) diff --git a/include/boost/charconv/from_chars.hpp b/include/boost/charconv/from_chars.hpp index 46b0f75..fa003be 100644 --- a/include/boost/charconv/from_chars.hpp +++ b/include/boost/charconv/from_chars.hpp @@ -68,10 +68,9 @@ constexpr unsigned char digit_from_char(char val) noexcept return uchar_values[static_cast(val)]; } -template +template BOOST_CXX14_CONSTEXPR boost::charconv::from_chars_result from_chars_integer_impl(const char* first, const char* last, Integer& value, int base) noexcept { - using Unsigned_Integer = typename std::make_unsigned::type; Unsigned_Integer result = 0; Unsigned_Integer overflow_value = 0; Unsigned_Integer max_digit = 0; @@ -173,39 +172,90 @@ BOOST_CXX14_CONSTEXPR boost::charconv::from_chars_result from_chars_integer_impl { if (is_negative) { - value = apply_sign(value); + value = -(static_cast(value)); } } return {next, 0}; } +// Only from_chars for integer types is constexpr (as of C++23) +template +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, Integer& value, int base = 10) noexcept +{ + using Unsigned_Integer = typename std::make_unsigned::type; + return detail::from_chars_integer_impl(first, last, value, base); +} + +#ifdef BOOST_HAS_INT128 +template +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars128(const char* first, const char* last, Integer& value, int base = 10) noexcept +{ + using Unsigned_Integer = boost::uint128_type; + return detail::from_chars_integer_impl(first, last, value, base); +} +#endif + } // Namespace detail -// GCC 5 does not support constexpr comparison of const char* -#if defined(__GNUC__) && __GNUC__ == 5 -template ::value, bool>::type = true> -inline from_chars_result from_chars(const char* first, const char* last, Integer& value, int base = 10) noexcept +// integer overloads + +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, bool& value, int base = 10) noexcept = delete; +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, char& value, int base = 10) noexcept { - return detail::from_chars_integer_impl(first, last, value, base); + return detail::from_chars(first, last, value, base); +} +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, signed char& value, int base = 10) noexcept +{ + return detail::from_chars(first, last, value, base); +} +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned char& value, int base = 10) noexcept +{ + return detail::from_chars(first, last, value, base); +} +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, short& value, int base = 10) noexcept +{ + return detail::from_chars(first, last, value, base); +} +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned short& value, int base = 10) noexcept +{ + return detail::from_chars(first, last, value, base); +} +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, int& value, int base = 10) noexcept +{ + return detail::from_chars(first, last, value, base); +} +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned int& value, int base = 10) noexcept +{ + return detail::from_chars(first, last, value, base); +} +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, long& value, int base = 10) noexcept +{ + return detail::from_chars(first, last, value, base); +} +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned long& value, int base = 10) noexcept +{ + return detail::from_chars(first, last, value, base); +} +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, long long& value, int base = 10) noexcept +{ + return detail::from_chars(first, last, value, base); +} +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, unsigned long long& value, int base = 10) noexcept +{ + return detail::from_chars(first, last, value, base); } -template<> -inline from_chars_result from_chars(const char* first, const char* last, bool& value, int base) noexcept = delete; - -#else - -// Only from_chars for integer types is constexpr (as of C++23) -template ::value, bool>::type = true> -BOOST_CXX14_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, Integer& value, int base = 10) noexcept +#ifdef BOOST_CHARCONV_HAS_INT128 +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, boost::int128_type& value, int base = 10) noexcept { - return detail::from_chars_integer_impl(first, last, value, base); + return detail::from_chars128(first, last, value, base); } - -template <> -BOOST_CXX14_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, bool& value, int base) noexcept = delete; - -#endif // GCC5 workarounds +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, boost::uint128_type& value, int base = 10) noexcept +{ + return detail::from_chars128(first, last, value, base); +} +#endif // floating point overloads From dc5410558a6b618d038e81c7b2cd9e04a8cb20a6 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 09:13:24 -0800 Subject: [PATCH 07/25] Suppress MSVC warnings --- include/boost/charconv/from_chars.hpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/boost/charconv/from_chars.hpp b/include/boost/charconv/from_chars.hpp index fa003be..fca155d 100644 --- a/include/boost/charconv/from_chars.hpp +++ b/include/boost/charconv/from_chars.hpp @@ -68,8 +68,13 @@ constexpr unsigned char digit_from_char(char val) noexcept return uchar_values[static_cast(val)]; } +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable: 4146) +#endif + template -BOOST_CXX14_CONSTEXPR boost::charconv::from_chars_result from_chars_integer_impl(const char* first, const char* last, Integer& value, int base) noexcept +BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* first, const char* last, Integer& value, int base) noexcept { Unsigned_Integer result = 0; Unsigned_Integer overflow_value = 0; @@ -179,6 +184,10 @@ BOOST_CXX14_CONSTEXPR boost::charconv::from_chars_result from_chars_integer_impl return {next, 0}; } +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + // Only from_chars for integer types is constexpr (as of C++23) template BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, Integer& value, int base = 10) noexcept From 90bff4885d94908245a0c0d0b4cc7f1a85c0c2e6 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 09:24:18 -0800 Subject: [PATCH 08/25] Use macros instead of numeric_limits for 128 bit types [ci skip] --- include/boost/charconv/from_chars.hpp | 32 +++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/include/boost/charconv/from_chars.hpp b/include/boost/charconv/from_chars.hpp index fca155d..8505cc7 100644 --- a/include/boost/charconv/from_chars.hpp +++ b/include/boost/charconv/from_chars.hpp @@ -91,7 +91,11 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs // Negative sign will be appended at the end of parsing BOOST_ATTRIBUTE_UNUSED bool is_negative = false; auto next = first; + #ifdef BOOST_CHARCONV_HAS_INT128 + BOOST_IF_CONSTEXPR (std::is_same::value || std::is_signed::value) + #else BOOST_IF_CONSTEXPR (std::is_signed::value) + #endif { if (next != last) { @@ -106,8 +110,18 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs } } - overflow_value = (std::numeric_limits::max)(); - max_digit = (std::numeric_limits::max)(); + #ifdef BOOST_CHARCONV_HAS_INT128 + BOOST_IF_CONSTEXPR (std::is_same::value) + { + overflow_value = BOOST_CHARCONV_INT128_MAX; + max_digit = BOOST_CHARCONV_INT128_MAX; + } + else + #endif + { + overflow_value = (std::numeric_limits::max)(); + max_digit = (std::numeric_limits::max)(); + } if (is_negative) { @@ -129,8 +143,18 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs } } - overflow_value = (std::numeric_limits::max)(); - max_digit = (std::numeric_limits::max)(); + #ifdef BOOST_CHARCONV_HAS_INT128 + BOOST_IF_CONSTEXPR (std::is_same::value) + { + overflow_value = BOOST_CHARCONV_UINT128_MAX; + max_digit = BOOST_CHARCONV_UINT128_MAX; + } + else + #endif + { + overflow_value = (std::numeric_limits::max)(); + max_digit = (std::numeric_limits::max)(); + } } overflow_value /= static_cast(base); From 7d71fac5cb07b0bd41e5119f8f1441b63cfaadca Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 09:39:07 -0800 Subject: [PATCH 09/25] Avoid signed/unsigned conversion warnings --- include/boost/charconv/from_chars.hpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/include/boost/charconv/from_chars.hpp b/include/boost/charconv/from_chars.hpp index 8505cc7..2ef7a18 100644 --- a/include/boost/charconv/from_chars.hpp +++ b/include/boost/charconv/from_chars.hpp @@ -87,10 +87,13 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs return {first, EINVAL}; } + Unsigned_Integer unsigned_base = static_cast(base); + // Strip sign if the type is signed // Negative sign will be appended at the end of parsing BOOST_ATTRIBUTE_UNUSED bool is_negative = false; auto next = first; + #ifdef BOOST_CHARCONV_HAS_INT128 BOOST_IF_CONSTEXPR (std::is_same::value || std::is_signed::value) #else @@ -157,8 +160,8 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs } } - overflow_value /= static_cast(base); - max_digit %= base; + overflow_value /= unsigned_base; + max_digit %= unsigned_base; // If the only character was a sign abort now if (next == last) @@ -169,16 +172,16 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs bool overflowed = false; while (next != last) { - auto current_digit = digit_from_char(*next); + const unsigned char current_digit = digit_from_char(*next); - if (current_digit >= base) + if (current_digit >= unsigned_base) { break; } if (result < overflow_value || (result == overflow_value && current_digit <= max_digit)) { - result = static_cast(result * base + current_digit); + result = static_cast(result * unsigned_base + current_digit); } else { From 6caa200ccffa95b219987e2f62ccd773a6e86743 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 09:46:22 -0800 Subject: [PATCH 10/25] Change type in integer trees [ci skip] --- .../charconv/detail/integer_search_trees.hpp | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/include/boost/charconv/detail/integer_search_trees.hpp b/include/boost/charconv/detail/integer_search_trees.hpp index ebe8398..7123acf 100644 --- a/include/boost/charconv/detail/integer_search_trees.hpp +++ b/include/boost/charconv/detail/integer_search_trees.hpp @@ -167,30 +167,30 @@ static constexpr std::array powers_of_10 = // Assume that if someone is using 128 bit ints they are favoring the top end of the range // Max value is 340,282,366,920,938,463,463,374,607,431,768,211,455 (39 digits) -BOOST_CXX14_CONSTEXPR inline int num_digits(unsigned __int128 x) noexcept +BOOST_CXX14_CONSTEXPR inline int num_digits(boost::uint128_type x) noexcept { - // There is not literal for unsigned __int128 so we need to calculate them using the max value of the + // There is not literal for boost::uint128_type so we need to calculate them using the max value of the // std::uint64_t powers of 10 - constexpr unsigned __int128 digits_39 = static_cast(UINT64_C(10000000000000000000)) * - static_cast(UINT64_C(1000000000000000000)); - constexpr unsigned __int128 digits_38 = digits_39 / 10; - constexpr unsigned __int128 digits_37 = digits_38 / 10; - constexpr unsigned __int128 digits_36 = digits_37 / 10; - constexpr unsigned __int128 digits_35 = digits_36 / 10; - constexpr unsigned __int128 digits_34 = digits_35 / 10; - constexpr unsigned __int128 digits_33 = digits_34 / 10; - constexpr unsigned __int128 digits_32 = digits_33 / 10; - constexpr unsigned __int128 digits_31 = digits_32 / 10; - constexpr unsigned __int128 digits_30 = digits_31 / 10; - constexpr unsigned __int128 digits_29 = digits_30 / 10; - constexpr unsigned __int128 digits_28 = digits_29 / 10; - constexpr unsigned __int128 digits_27 = digits_28 / 10; - constexpr unsigned __int128 digits_26 = digits_27 / 10; - constexpr unsigned __int128 digits_25 = digits_26 / 10; - constexpr unsigned __int128 digits_24 = digits_25 / 10; - constexpr unsigned __int128 digits_23 = digits_24 / 10; - constexpr unsigned __int128 digits_22 = digits_23 / 10; - constexpr unsigned __int128 digits_21 = digits_22 / 10; + constexpr boost::uint128_type digits_39 = static_cast(UINT64_C(10000000000000000000)) * + static_cast(UINT64_C(1000000000000000000)); + constexpr boost::uint128_type digits_38 = digits_39 / 10; + constexpr boost::uint128_type digits_37 = digits_38 / 10; + constexpr boost::uint128_type digits_36 = digits_37 / 10; + constexpr boost::uint128_type digits_35 = digits_36 / 10; + constexpr boost::uint128_type digits_34 = digits_35 / 10; + constexpr boost::uint128_type digits_33 = digits_34 / 10; + constexpr boost::uint128_type digits_32 = digits_33 / 10; + constexpr boost::uint128_type digits_31 = digits_32 / 10; + constexpr boost::uint128_type digits_30 = digits_31 / 10; + constexpr boost::uint128_type digits_29 = digits_30 / 10; + constexpr boost::uint128_type digits_28 = digits_29 / 10; + constexpr boost::uint128_type digits_27 = digits_28 / 10; + constexpr boost::uint128_type digits_26 = digits_27 / 10; + constexpr boost::uint128_type digits_25 = digits_26 / 10; + constexpr boost::uint128_type digits_24 = digits_25 / 10; + constexpr boost::uint128_type digits_23 = digits_24 / 10; + constexpr boost::uint128_type digits_22 = digits_23 / 10; + constexpr boost::uint128_type digits_21 = digits_22 / 10; return (x > digits_39) ? 39 : (x > digits_38) ? 38 : From 8f63d52a8d603318c506b1689c7b9198ed2cb8e6 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 09:57:53 -0800 Subject: [PATCH 11/25] Dummy check test case [ci skip] --- test/to_chars.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/to_chars.cpp b/test/to_chars.cpp index bdd9cb5..a96dc46 100644 --- a/test/to_chars.cpp +++ b/test/to_chars.cpp @@ -52,6 +52,7 @@ void test_128bit_int() T v5 = 0; auto r5 = boost::charconv::from_chars(buffer5, buffer5 + std::strlen(buffer5), v5); BOOST_TEST(r5.ec == 0); + BOOST_TEST(v5 < 0); char buffer6[64] {}; auto r6 = boost::charconv::to_chars(buffer6, buffer6 + sizeof(buffer6), v5); From 0b38425753889df13d60a8fdb3ed45620222add0 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 10:41:54 -0800 Subject: [PATCH 12/25] Change check for negative value [ci skip] --- include/boost/charconv/from_chars.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/boost/charconv/from_chars.hpp b/include/boost/charconv/from_chars.hpp index 2ef7a18..dbe577c 100644 --- a/include/boost/charconv/from_chars.hpp +++ b/include/boost/charconv/from_chars.hpp @@ -200,7 +200,11 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs } value = static_cast(result); + #ifdef BOOST_CHARCONV_HAS_INT128 + BOOST_IF_CONSTEXPR (std::is_same::value || std::is_signed::value) + #else BOOST_IF_CONSTEXPR (std::is_signed::value) + #endif { if (is_negative) { @@ -285,11 +289,11 @@ BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, co #ifdef BOOST_CHARCONV_HAS_INT128 BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, boost::int128_type& value, int base = 10) noexcept { - return detail::from_chars128(first, last, value, base); + return detail::from_chars_integer_impl(first, last, value, base); } BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, boost::uint128_type& value, int base = 10) noexcept { - return detail::from_chars128(first, last, value, base); + return detail::from_chars_integer_impl(first, last, value, base); } #endif From 4d1ffb8829a686848b2e46fc5b3be4dd289ecc8e Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 10:45:44 -0800 Subject: [PATCH 13/25] Change test so we can see the failed value [ci skip] --- test/roundtrip.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/roundtrip.cpp b/test/roundtrip.cpp index 9b56538..5f16bb6 100644 --- a/test/roundtrip.cpp +++ b/test/roundtrip.cpp @@ -82,7 +82,8 @@ template void test_roundtrip( T value, int base ) T v2 = 0; auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2, base ); - BOOST_TEST_EQ( r2.ec, 0 ) && BOOST_TEST_EQ( v2, value ); + BOOST_TEST_EQ( r2.ec, 0 ); + BOOST_TEST_EQ( v2, value ); } template void test_roundtrip_int8( int base ) From 6f9833be591caf488046096ac546f9a90d6a58d1 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 11:08:36 -0800 Subject: [PATCH 14/25] Add more diagnostics [ci skip] --- test/roundtrip.cpp | 25 ++++++++++++++++++------- test/to_chars.cpp | 17 +++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/test/roundtrip.cpp b/test/roundtrip.cpp index 5f16bb6..6159c54 100644 --- a/test/roundtrip.cpp +++ b/test/roundtrip.cpp @@ -65,7 +65,9 @@ std::ostream& operator<<( std::ostream& os, boost::int128_type v ) #include #include -int const N = 1024; +// TODO: Revert +//int const N = 1024; +const int N = 10; static boost::detail::splitmix64 rng; @@ -83,7 +85,14 @@ template void test_roundtrip( T value, int base ) auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2, base ); BOOST_TEST_EQ( r2.ec, 0 ); - BOOST_TEST_EQ( v2, value ); + if (BOOST_TEST_EQ( v2, value )) + { + + } + else + { + std::cerr << "Original Value: " << value << "\nBase:" << base << "\nConverted Value: " << buffer << "\nRoundtriped Value: " << v2 << std::endl; + } } template void test_roundtrip_int8( int base ) @@ -243,6 +252,7 @@ int main() for( int base = 2; base <= 36; ++base ) { + /* test_roundtrip_int8( base ); test_roundtrip_uint8( base ); @@ -254,11 +264,11 @@ int main() test_roundtrip_int64( base ); test_roundtrip_uint64( base ); - + */ #ifdef BOOST_CHARCONV_HAS_INT128 - test_roundtrip_int128( base ); - test_roundtrip_uint128( base ); + //test_roundtrip_int128( base ); + //test_roundtrip_uint128( base ); #endif } @@ -267,6 +277,7 @@ int main() for( int base = 2; base <= 36; ++base ) { + /* test_roundtrip_bv( base ); test_roundtrip_bv( base ); test_roundtrip_bv( base ); @@ -282,11 +293,11 @@ int main() test_roundtrip_bv( base ); test_roundtrip_bv( base ); - + */ #ifdef BOOST_CHARCONV_HAS_INT128 test_roundtrip_bv( base ); - test_roundtrip_bv( base ); + //test_roundtrip_bv( base ); #endif } diff --git a/test/to_chars.cpp b/test/to_chars.cpp index a96dc46..b333f97 100644 --- a/test/to_chars.cpp +++ b/test/to_chars.cpp @@ -64,6 +64,23 @@ void test_128bit_int() auto r7 = boost::charconv::from_chars(buffer6, buffer6 + std::strlen(buffer6), v7); BOOST_TEST(r7.ec == 0); BOOST_TEST(v5 == v7);; + + // Second failing test + const char* buffer10 = "-170141183460469231731687303715884105728"; + T v10 = 0; + auto r10 = boost::charconv::from_chars(buffer10, buffer10 + std::strlen(buffer10), v10); + BOOST_TEST(r10.ec == 0); + BOOST_TEST(v10 < 0); + + char buffer11[64] {}; + auto r11 = boost::charconv::to_chars(buffer11, buffer11 + sizeof(buffer11), v10); + BOOST_TEST_EQ(r11.ec, 0); + BOOST_TEST_CSTR_EQ(buffer10, buffer11); + + T v11 = 0; + auto r12 = boost::charconv::from_chars(buffer11, buffer11 + std::strlen(buffer11), v11); + BOOST_TEST(r12.ec == 0); + BOOST_TEST(v10 == v11); } } #endif From 610c00ee220d2edd963ce7daf1be14592256d4be Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 11:28:10 -0800 Subject: [PATCH 15/25] Change guardrails for int128_type --- include/boost/charconv/from_chars.hpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/include/boost/charconv/from_chars.hpp b/include/boost/charconv/from_chars.hpp index dbe577c..492aae3 100644 --- a/include/boost/charconv/from_chars.hpp +++ b/include/boost/charconv/from_chars.hpp @@ -160,8 +160,13 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs } } - overflow_value /= unsigned_base; - max_digit %= unsigned_base; + #ifdef BOOST_CHARCONV_HAS_INT128 + BOOST_IF_CONSTEXPR (!std::is_same::value) + #endif + { + overflow_value /= base; + max_digit %= base; + } // If the only character was a sign abort now if (next == last) From de4060f5c714427464d82bd13189d8d923d8ccc4 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 11:28:20 -0800 Subject: [PATCH 16/25] Revert testing removal --- test/roundtrip.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/test/roundtrip.cpp b/test/roundtrip.cpp index 6159c54..2eecdb7 100644 --- a/test/roundtrip.cpp +++ b/test/roundtrip.cpp @@ -65,9 +65,7 @@ std::ostream& operator<<( std::ostream& os, boost::int128_type v ) #include #include -// TODO: Revert -//int const N = 1024; -const int N = 10; +int const N = 1024; static boost::detail::splitmix64 rng; @@ -252,7 +250,6 @@ int main() for( int base = 2; base <= 36; ++base ) { - /* test_roundtrip_int8( base ); test_roundtrip_uint8( base ); @@ -264,11 +261,10 @@ int main() test_roundtrip_int64( base ); test_roundtrip_uint64( base ); - */ #ifdef BOOST_CHARCONV_HAS_INT128 - //test_roundtrip_int128( base ); - //test_roundtrip_uint128( base ); + test_roundtrip_int128( base ); + test_roundtrip_uint128( base ); #endif } @@ -277,7 +273,6 @@ int main() for( int base = 2; base <= 36; ++base ) { - /* test_roundtrip_bv( base ); test_roundtrip_bv( base ); test_roundtrip_bv( base ); @@ -293,11 +288,10 @@ int main() test_roundtrip_bv( base ); test_roundtrip_bv( base ); - */ #ifdef BOOST_CHARCONV_HAS_INT128 test_roundtrip_bv( base ); - //test_roundtrip_bv( base ); + test_roundtrip_bv( base ); #endif } From 4bb917687909d971f152c94761b264b4ad1eb15f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 11:32:59 -0800 Subject: [PATCH 17/25] Fix MSVC warnings --- include/boost/charconv/from_chars.hpp | 4 ++-- include/boost/charconv/to_chars.hpp | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/boost/charconv/from_chars.hpp b/include/boost/charconv/from_chars.hpp index 492aae3..1d011ab 100644 --- a/include/boost/charconv/from_chars.hpp +++ b/include/boost/charconv/from_chars.hpp @@ -164,8 +164,8 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs BOOST_IF_CONSTEXPR (!std::is_same::value) #endif { - overflow_value /= base; - max_digit %= base; + overflow_value /= unsigned_base; + max_digit %= unsigned_base; } // If the only character was a sign abort now diff --git a/include/boost/charconv/to_chars.hpp b/include/boost/charconv/to_chars.hpp index e57cf9a..8609605 100644 --- a/include/boost/charconv/to_chars.hpp +++ b/include/boost/charconv/to_chars.hpp @@ -98,7 +98,7 @@ BOOST_CHARCONV_CONSTEXPR inline char* decompose32(std::uint32_t value, char* buf #ifdef BOOST_MSVC # pragma warning(push) -# pragma warning(disable: 4127) +# pragma warning(disable: 4127 4146) #endif template @@ -317,10 +317,6 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_128integer_impl(char* first, c } #endif -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif - // All other bases // Use a simple lookup table to put together the Integer in character form template @@ -431,6 +427,10 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars_integer_impl(char* first, char return {first + num_chars, 0}; } +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + template BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, Integer value, int base = 10) noexcept { From ce01ff3f414b01083f39375172f1434c83f3024c Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 11:33:18 -0800 Subject: [PATCH 18/25] Remove dummy test that fails on old compilers --- test/to_chars.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/to_chars.cpp b/test/to_chars.cpp index b333f97..82df20a 100644 --- a/test/to_chars.cpp +++ b/test/to_chars.cpp @@ -37,7 +37,6 @@ void test_128bit_int() auto r3 = boost::charconv::from_chars(buffer3, buffer3 + std::strlen(buffer3), v3); BOOST_TEST(r3.ec == 0); BOOST_TEST(v3 == test_value); - BOOST_TEST(std::numeric_limits::max() > static_cast(std::numeric_limits::max())); char buffer4[64] {}; auto r4 = boost::charconv::to_chars(buffer4, buffer4 + sizeof(buffer4), v3); From 26e15030b96303563a6805b00f049abcf05b607f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 11:35:53 -0800 Subject: [PATCH 19/25] Make BOOST_CHARCONV_CONSTEXPR be inline when not constexpr --- include/boost/charconv/detail/memcpy.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/charconv/detail/memcpy.hpp b/include/boost/charconv/detail/memcpy.hpp index 7509142..8bfa50b 100644 --- a/include/boost/charconv/detail/memcpy.hpp +++ b/include/boost/charconv/detail/memcpy.hpp @@ -60,7 +60,7 @@ constexpr char* memcpy(char* dest, const char* src, std::size_t count) #else // Either not C++14 or no way of telling if we are in a constexpr context -#define BOOST_CHARCONV_CONSTEXPR +#define BOOST_CHARCONV_CONSTEXPR inline inline void* memcpy(void* dest, const void* src, std::size_t count) { From 704e1e9711f1cdfb073fb94bd70269e648c05c6f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 11:38:40 -0800 Subject: [PATCH 20/25] Remove duplicate inline --- include/boost/charconv/to_chars.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/charconv/to_chars.hpp b/include/boost/charconv/to_chars.hpp index 8609605..d20f8a1 100644 --- a/include/boost/charconv/to_chars.hpp +++ b/include/boost/charconv/to_chars.hpp @@ -81,7 +81,7 @@ namespace detail { // See: https://jk-jeon.github.io/posts/2022/02/jeaiii-algorithm/ // https://arxiv.org/abs/2101.11408 -BOOST_CHARCONV_CONSTEXPR inline char* decompose32(std::uint32_t value, char* buffer) noexcept +BOOST_CHARCONV_CONSTEXPR char* decompose32(std::uint32_t value, char* buffer) noexcept { constexpr auto mask = (std::uint64_t(1) << 57) - 1; auto y = value * std::uint64_t(1441151881); From 5f277f5a52cebfe1328eb8b7af0f97d714b6b522 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 11:41:11 -0800 Subject: [PATCH 21/25] Add safety factor to overflow value --- include/boost/charconv/from_chars.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/boost/charconv/from_chars.hpp b/include/boost/charconv/from_chars.hpp index 1d011ab..3f4cca5 100644 --- a/include/boost/charconv/from_chars.hpp +++ b/include/boost/charconv/from_chars.hpp @@ -161,7 +161,13 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs } #ifdef BOOST_CHARCONV_HAS_INT128 - BOOST_IF_CONSTEXPR (!std::is_same::value) + BOOST_IF_CONSTEXPR (std::is_same::value) + { + overflow_value /= unsigned_base; + max_digit %= unsigned_base; + overflow_value *= 2; // Overflow value would cause INT128_MIN in non-base10 to fail + } + else #endif { overflow_value /= unsigned_base; From bb4691001e1ae9ce2a5de687c9af63ee17e29988 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 11:57:34 -0800 Subject: [PATCH 22/25] Change another macro to inline when not constexpr --- include/boost/charconv/config.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/boost/charconv/config.hpp b/include/boost/charconv/config.hpp index 31f0c3c..1eaeae7 100644 --- a/include/boost/charconv/config.hpp +++ b/include/boost/charconv/config.hpp @@ -54,10 +54,16 @@ # define BOOST_CHARCONV_UINT128_MAX ((2 * (boost::uint128_type) BOOST_CHARCONV_INT128_MAX) + 1) #endif +#ifndef BOOST_NO_CXX14_CONSTEXPR +# define BOOST_CHARCONV_CXX14_CONSTEXPR BOOST_CXX14_CONSTEXPR +#else +# define BOOST_CHARCONV_CXX14_CONSTEXPR inline +#endif + #if defined(__GNUC__) && __GNUC__ == 5 # define BOOST_CHARCONV_GCC5_CONSTEXPR inline #else -# define BOOST_CHARCONV_GCC5_CONSTEXPR BOOST_CXX14_CONSTEXPR +# define BOOST_CHARCONV_GCC5_CONSTEXPR BOOST_CHARCONV_CXX14_CONSTEXPR #endif #endif // BOOST_CHARCONV_CONFIG_HPP_INCLUDED From 51c145111a53c1096e443d856bf8f5e090ee5363 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 13 Feb 2023 11:58:06 -0800 Subject: [PATCH 23/25] Initialize buffer --- test/quick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/quick.cpp b/test/quick.cpp index 919b97e..1271c1d 100644 --- a/test/quick.cpp +++ b/test/quick.cpp @@ -6,7 +6,7 @@ int main() { - char buffer[ 32 ]; + char buffer[ 32 ] {}; auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), 1048576 ); int v = 0; From 2ddb84d2307347c17546341906fef5bd64e3a982 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 14 Feb 2023 10:01:43 -0800 Subject: [PATCH 24/25] Workaround for clang 5 partial inline variable support --- include/boost/charconv/limits.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/charconv/limits.hpp b/include/boost/charconv/limits.hpp index e1bfe07..b401f28 100644 --- a/include/boost/charconv/limits.hpp +++ b/include/boost/charconv/limits.hpp @@ -57,7 +57,7 @@ template<> struct limits #endif // #if defined(BOOST_HAS_INT128) -#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) +#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) || (defined(__clang__) && __clang_major__ <= 5) // Definitions of in-class constexpr members are allowed but deprecated in C++17 From 28c4bb937228c91438bfb9942d81b627269a80a4 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 14 Feb 2023 10:07:51 -0800 Subject: [PATCH 25/25] Ignore GCC 5 and 6 speculative execution warning --- include/boost/charconv/from_chars.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/boost/charconv/from_chars.hpp b/include/boost/charconv/from_chars.hpp index 3f4cca5..c51326d 100644 --- a/include/boost/charconv/from_chars.hpp +++ b/include/boost/charconv/from_chars.hpp @@ -71,6 +71,9 @@ constexpr unsigned char digit_from_char(char val) noexcept #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable: 4146) +#elif defined(__GNUC__) && (__GNUC__ == 5 || __GNUC__ == 6) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Woverflow" #endif template @@ -228,6 +231,8 @@ BOOST_CXX14_CONSTEXPR from_chars_result from_chars_integer_impl(const char* firs #ifdef BOOST_MSVC # pragma warning(pop) +#elif defined(__GNUC__) && (__GNUC__ == 5 || __GNUC__ == 6) +# pragma GCC diagnostic pop #endif // Only from_chars for integer types is constexpr (as of C++23)