From fb6f874e3636bb8dc58d55adc13343a33f0f0e6b Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 30 Sep 2026 00:15:35 +0200 Subject: [PATCH] Fix CI: useless cast in the Zmij digit writer and snprintf truncation - ci_test_gcc (Linux x86-64): static_cast(d.significand % 100) was a useless cast (a std::uint64_t prvalue, the same type as std::size_t there); cast a named variable instead. - ci_test_gcc: -Werror=format-truncation for snprintf("%.*e") in unit-to_chars.cpp, whose precision GCC cannot bound; write the neighboring decimal with a stream (classic locale, std::scientific), which gives the same text. Signed-off-by: Niels Lohmann --- include/nlohmann/detail/conversions/to_chars.hpp | 3 ++- single_include/nlohmann/json.hpp | 3 ++- tests/src/unit-to_chars.cpp | 11 ++++++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/nlohmann/detail/conversions/to_chars.hpp b/include/nlohmann/detail/conversions/to_chars.hpp index 9f8aa8581..93c27c162 100644 --- a/include/nlohmann/detail/conversions/to_chars.hpp +++ b/include/nlohmann/detail/conversions/to_chars.hpp @@ -983,7 +983,8 @@ inline void shortest_digits(char* buf, int& len, int& decimal_exponent, double v std::size_t n = digits.size(); while (d.significand >= 100) { - const auto i = static_cast(d.significand % 100) * 2; + const std::uint64_t two_digits = d.significand % 100; // a variable: GCC calls a cast of the remainder useless where std::uint64_t is std::size_t + const auto i = static_cast(two_digits) * 2; d.significand /= 100; n -= 2; digits[n] = pairs[i]; diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 373abc66e..401f67ebe 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -25114,7 +25114,8 @@ inline void shortest_digits(char* buf, int& len, int& decimal_exponent, double v std::size_t n = digits.size(); while (d.significand >= 100) { - const auto i = static_cast(d.significand % 100) * 2; + const std::uint64_t two_digits = d.significand % 100; // a variable: GCC calls a cast of the remainder useless where std::uint64_t is std::size_t + const auto i = static_cast(two_digits) * 2; d.significand /= 100; n -= 2; digits[n] = pairs[i]; diff --git a/tests/src/unit-to_chars.cpp b/tests/src/unit-to_chars.cpp index 6cc8ae6da..02895cc9d 100644 --- a/tests/src/unit-to_chars.cpp +++ b/tests/src/unit-to_chars.cpp @@ -20,8 +20,11 @@ using nlohmann::detail::dtoa_impl::reinterpret_bits; #include #include #include +#include #include +#include #include +#include #include #include #include @@ -664,9 +667,11 @@ void check_shortest(double v) if (digits.size() > 1) { // the decimals of one digit fewer next to the value - std::array shorter{}; - const int n = std::snprintf(shorter.data(), shorter.size(), "%.*e", static_cast(digits.size()) - 2, v); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - const auto near = digits_and_exponent(std::string(shorter.data(), static_cast(n))); + // (a stream rather than snprintf("%.*e"), whose output GCC cannot bound) + std::ostringstream shorter; + shorter.imbue(std::locale::classic()); + shorter << std::scientific << std::setprecision(static_cast(digits.size()) - 2) << v; + const auto near = digits_and_exponent(shorter.str()); // as an integer with digits.size() - 1 digits std::string m = near.first; int e = near.second;