From 56477077834ecedbb691a5d842bb8fc2e7422128 Mon Sep 17 00:00:00 2001 From: Florin Iucha Date: Sat, 15 Dec 2018 09:46:35 -0500 Subject: [PATCH 1/6] Fix sign conversion warnings --- include/fmt/chrono.h | 2 +- include/fmt/color.h | 17 +++++++++-------- include/fmt/format-inl.h | 16 ++++++++-------- include/fmt/format.h | 16 +++++++--------- include/fmt/time.h | 2 +- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 22bef59c1abc..5aa2db76f4d2 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -415,7 +415,7 @@ struct formatter, Char> { if (begin == end) return begin; begin = internal::parse_width(begin, end, handler); end = parse_chrono_format(begin, end, internal::chrono_format_checker()); - format_str = basic_string_view(&*begin, end - begin); + format_str = basic_string_view(&*begin, static_cast(end - begin)); return end; } diff --git a/include/fmt/color.h b/include/fmt/color.h index 8c96f7fd07e7..5db861c9331d 100644 --- a/include/fmt/color.h +++ b/include/fmt/color.h @@ -246,7 +246,8 @@ struct color_type { } FMT_CONSTEXPR color_type(rgb rgb_color) FMT_NOEXCEPT : is_rgb(true), value{} { - value.rgb_color = (rgb_color.r << 16) + (rgb_color.g << 8) + rgb_color.b; + value.rgb_color = (static_cast(rgb_color.r) << 16) + | (static_cast(rgb_color.g) << 8) | rgb_color.b; } FMT_CONSTEXPR color_type(terminal_color term_color) FMT_NOEXCEPT : is_rgb(), value{} { @@ -395,22 +396,22 @@ struct ansi_color_escape { // sequence. if (!text_color.is_rgb) { bool is_background = esc == internal::data::BACKGROUND_COLOR; - uint8_t value = text_color.value.term_color; + uint32_t value = text_color.value.term_color; // Background ASCII codes are the same as the foreground ones but with // 10 more. if (is_background) - value += 10; + value += 10u; std::size_t index = 0; buffer[index++] = static_cast('\x1b'); buffer[index++] = static_cast('['); - if (value >= 100) { + if (value >= 100u) { buffer[index++] = static_cast('1'); - value %= 100; + value %= 100u; } - buffer[index++] = static_cast('0' + value / 10); - buffer[index++] = static_cast('0' + value % 10); + buffer[index++] = static_cast('0' + value / 10u); + buffer[index++] = static_cast('0' + value % 10u); buffer[index++] = static_cast('m'); buffer[index++] = static_cast('\0'); @@ -452,7 +453,7 @@ struct ansi_color_escape { FMT_CONSTEXPR operator const Char *() const FMT_NOEXCEPT { return buffer; } private: - Char buffer[7 + 3 * 4 + 1]; + Char buffer[7u + 3u * 4u + 1u]; static FMT_CONSTEXPR void to_esc(uint8_t c, Char *out, char delimiter) FMT_NOEXCEPT { diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 9b7396359f53..69e943318468 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -464,14 +464,14 @@ FMT_FUNC fp get_cached_power(int min_exponent, int &pow10_exponent) { } FMT_FUNC bool grisu2_round( - char *buf, ptrdiff_t &size, size_t max_digits, uint64_t delta, + char *buf, int &size, int max_digits, uint64_t delta, uint64_t remainder, uint64_t exp, uint64_t diff, int &exp10) { while (remainder < diff && delta - remainder >= exp && (remainder + exp < diff || diff - remainder > remainder + exp - diff)) { --buf[size - 1]; remainder += exp; } - if (size > static_cast(max_digits)) { + if (size > max_digits) { --size; ++exp10; if (buf[size] >= '5') @@ -482,8 +482,8 @@ FMT_FUNC bool grisu2_round( // Generates output using Grisu2 digit-gen algorithm. FMT_FUNC bool grisu2_gen_digits( - char *buf, ptrdiff_t &size, uint32_t hi, uint64_t lo, int &exp, - uint64_t delta, const fp &one, const fp &diff, size_t max_digits) { + char *buf, int &size, uint32_t hi, uint64_t lo, int &exp, + uint64_t delta, const fp &one, const fp &diff, int max_digits) { // Generate digits for the most significant part (hi). while (exp > 0) { uint32_t digit = 0; @@ -507,7 +507,7 @@ FMT_FUNC bool grisu2_gen_digits( buf[size++] = static_cast('0' + digit); --exp; uint64_t remainder = (static_cast(hi) << -one.e) + lo; - if (remainder <= delta || size > static_cast(max_digits)) { + if (remainder <= delta || size > max_digits) { return grisu2_round( buf, size, max_digits, delta, remainder, static_cast(data::POWERS_OF_10_32[exp]) << -one.e, @@ -523,7 +523,7 @@ FMT_FUNC bool grisu2_gen_digits( buf[size++] = static_cast('0' + digit); lo &= one.f - 1; --exp; - if (lo < delta || size > static_cast(max_digits)) { + if (lo < delta || size > max_digits) { return grisu2_round(buf, size, max_digits, delta, lo, one.f, diff.f * data::POWERS_OF_10_32[-exp], exp); } @@ -704,7 +704,7 @@ FMT_FUNC gen_digits_params process_specs(const core_format_specs &specs, ++num_digits; break; } - params.num_digits = to_unsigned(num_digits); + params.num_digits = num_digits; char_counter counter{num_digits}; grisu2_prettify(params, params.num_digits, exp - num_digits, counter); buf.resize(to_unsigned(counter.size)); @@ -750,7 +750,7 @@ FMT_FUNC typename std::enable_if::type // lo (p2 in Grisu) contains the least significants digits of scaled_upper. // lo = supper % one. uint64_t lo = upper.f & (one.f - 1); - ptrdiff_t size = 0; + int size = 0; if (!grisu2_gen_digits(buf.data(), size, hi, lo, exp, delta, one, diff, params.num_digits)) { buf.clear(); diff --git a/include/fmt/format.h b/include/fmt/format.h index 9f1ef6f8dc8d..63fbcae26f9e 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -66,10 +66,6 @@ // many valid cases. # pragma GCC diagnostic ignored "-Wshadow" -// Disable the warning about implicit conversions that may change the sign of -// an integer; silencing it otherwise would require many explicit casts. -# pragma GCC diagnostic ignored "-Wsign-conversion" - // Disable the warning about nonliteral format strings because we construct // them dynamically when falling back to snprintf for FP formatting. # pragma GCC diagnostic ignored "-Wformat-nonliteral" @@ -959,8 +955,9 @@ inline wchar_t thousands_sep(locale_ref loc) { // thousands_sep is a functor that is called after writing each char to // add a thousands separator if necessary. template -inline Char *format_decimal(Char *buffer, UInt value, unsigned num_digits, +inline Char *format_decimal(Char *buffer, UInt value, int num_digits, ThousandsSep thousands_sep) { + FMT_ASSERT(num_digits >= 0, "invalid digit count"); buffer += num_digits; Char *end = buffer; while (value >= 100) { @@ -988,7 +985,8 @@ inline Char *format_decimal(Char *buffer, UInt value, unsigned num_digits, template inline Iterator format_decimal( - Iterator out, UInt value, unsigned num_digits, ThousandsSep sep) { + Iterator out, UInt value, int num_digits, ThousandsSep sep) { + FMT_ASSERT(num_digits >= 0, "invalid digit count"); typedef typename ThousandsSep::char_type char_type; // Buffer should be large enough to hold all digits (<= digits10 + 1). enum { max_size = std::numeric_limits::digits10 + 1 }; @@ -999,12 +997,12 @@ inline Iterator format_decimal( } template -inline It format_decimal(It out, UInt value, unsigned num_digits) { +inline It format_decimal(It out, UInt value, int num_digits) { return format_decimal(out, value, num_digits, no_thousands_sep()); } template -inline Char *format_uint(Char *buffer, UInt value, unsigned num_digits, +inline Char *format_uint(Char *buffer, UInt value, int num_digits, bool upper = false) { buffer += num_digits; Char *end = buffer; @@ -1017,7 +1015,7 @@ inline Char *format_uint(Char *buffer, UInt value, unsigned num_digits, } template -inline It format_uint(It out, UInt value, unsigned num_digits, +inline It format_uint(It out, UInt value, int num_digits, bool upper = false) { // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1) // and null. diff --git a/include/fmt/time.h b/include/fmt/time.h index fbd3c60a8482..fe798916f182 100644 --- a/include/fmt/time.h +++ b/include/fmt/time.h @@ -122,7 +122,7 @@ struct formatter { auto end = it; while (end != ctx.end() && *end != '}') ++end; - tm_format.reserve(end - it + 1); + tm_format.reserve(internal::to_unsigned(end - it + 1)); tm_format.append(it, end); tm_format.push_back('\0'); return end; From 9dc380d18276bf1efe67467f05b384fbbe5a001f Mon Sep 17 00:00:00 2001 From: Florin Iucha Date: Sat, 15 Dec 2018 15:56:06 -0500 Subject: [PATCH 2/6] Ignore unused local typedefs --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b443a158502..7709a9b86aba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,7 +75,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") -Wctor-dtor-privacy -Wdisabled-optimization -Winvalid-pch -Woverloaded-virtual -Wno-ctor-dtor-privacy -Wno-dangling-else - -Wno-format-nonliteral -Wno-sign-conversion -Wno-shadow) + -Wno-format-nonliteral -Wno-sign-conversion -Wno-shadow -Wno-unused-local-typedefs) if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6) set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wnoexcept) endif () From 9e37b68743550bfc8f0e5dba681cec696ad75edb Mon Sep 17 00:00:00 2001 From: Florin Iucha Date: Sat, 15 Dec 2018 16:02:34 -0500 Subject: [PATCH 3/6] Remove cast reported as useless on GCC --- test/core-test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core-test.cc b/test/core-test.cc index fe7583baf0d0..ef2cdb886cad 100644 --- a/test/core-test.cc +++ b/test/core-test.cc @@ -492,7 +492,7 @@ class QString { inline fmt::basic_string_view to_string_view( const QString &s) FMT_NOEXCEPT { - return {reinterpret_cast(s.utf16()), + return {s.utf16(), static_cast(s.size())}; } } From 390f6069690018676399cf51014b99a9227b0ad1 Mon Sep 17 00:00:00 2001 From: Florin Iucha Date: Sat, 15 Dec 2018 16:06:43 -0500 Subject: [PATCH 4/6] Remove warning on unused variable --- test/format-test.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/test/format-test.cc b/test/format-test.cc index 8fb6a792cf54..2ce513b254cc 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1917,6 +1917,7 @@ TEST(FormatTest, Enum) { TEST(FormatTest, EnumFormatterUnambiguous) { fmt::formatter f; + ASSERT_GE(sizeof(f), 0); // use f to avoid compiler warning } #if FMT_HAS_FEATURE(cxx_strong_enums) From 94b58e6b712cb3b4e97e5b310779d468bbade136 Mon Sep 17 00:00:00 2001 From: Florin Iucha Date: Sat, 15 Dec 2018 23:46:36 -0500 Subject: [PATCH 5/6] Enable conversion warning checking for pedantic build --- CMakeLists.txt | 9 +++++---- include/fmt/printf.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7709a9b86aba..ce9dbf95ecc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,10 +74,11 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") -Wcast-align -Wnon-virtual-dtor -Wctor-dtor-privacy -Wdisabled-optimization -Winvalid-pch -Woverloaded-virtual - -Wno-ctor-dtor-privacy -Wno-dangling-else - -Wno-format-nonliteral -Wno-sign-conversion -Wno-shadow -Wno-unused-local-typedefs) + -Wconversion + -Wno-ctor-dtor-privacy -Wno-format-nonliteral -Wno-shadow) if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6) - set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wnoexcept) + set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wnoexcept + -Wno-dangling-else -Wno-unused-local-typedefs) endif () if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wdouble-promotion @@ -92,7 +93,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") endif () if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -pedantic) + set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -pedantic -Wconversion -Wno-sign-conversion) check_cxx_compiler_flag(-Wzero-as-null-pointer-constant HAS_NULLPTR_WARNING) if (HAS_NULLPTR_WARNING) set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} diff --git a/include/fmt/printf.h b/include/fmt/printf.h index 606cea4887e3..6f2715d9fe7c 100644 --- a/include/fmt/printf.h +++ b/include/fmt/printf.h @@ -631,7 +631,7 @@ void basic_printf_context::format() { format_arg arg = get_arg(it, arg_index); if (spec.has(HASH_FLAG) && visit_format_arg(internal::is_zero_int(), arg)) - spec.flags &= ~internal::to_unsigned(HASH_FLAG); + spec.flags = static_cast(spec.flags & (~internal::to_unsigned(HASH_FLAG))); if (spec.fill_ == '0') { if (arg.is_arithmetic()) spec.align_ = ALIGN_NUMERIC; From bfe82d87fada1cdc0c97e6afcd08913135581b6c Mon Sep 17 00:00:00 2001 From: Florin Iucha Date: Sun, 16 Dec 2018 01:30:22 -0500 Subject: [PATCH 6/6] Fix sign-conversion warnings in headers --- include/fmt/chrono.h | 4 +-- include/fmt/format-inl.h | 4 +-- include/fmt/format.h | 67 ++++++++++++++++++++-------------------- 3 files changed, 38 insertions(+), 37 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 5aa2db76f4d2..209cdc25adad 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -250,7 +250,7 @@ struct chrono_formatter { void write(int value, int width) { typedef typename int_traits::main_type main_type; main_type n = to_unsigned(value); - int num_digits = static_cast(internal::count_digits(n)); + int num_digits = internal::count_digits(n); if (width > num_digits) out = std::fill_n(out, width - num_digits, '0'); out = format_decimal(out, n, num_digits); @@ -415,7 +415,7 @@ struct formatter, Char> { if (begin == end) return begin; begin = internal::parse_width(begin, end, handler); end = parse_chrono_format(begin, end, internal::chrono_format_checker()); - format_str = basic_string_view(&*begin, static_cast(end - begin)); + format_str = basic_string_view(&*begin, internal::to_unsigned(end - begin)); return end; } diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 69e943318468..552c94303316 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -172,7 +172,7 @@ void format_error_code(internal::buffer &out, int error_code, abs_value = 0 - abs_value; ++error_code_size; } - error_code_size += internal::count_digits(abs_value); + error_code_size += internal::to_unsigned(internal::count_digits(abs_value)); writer w(out); if (message.size() <= inline_buffer_size - error_code_size) { w.write(message); @@ -739,7 +739,7 @@ FMT_FUNC typename std::enable_if::type // hi (p1 in Grisu) contains the most significant digits of scaled_upper. // hi = floor(upper / one). uint32_t hi = static_cast(upper.f >> -one.e); - int exp = static_cast(count_digits(hi)); // kappa in Grisu. + int exp = count_digits(hi); // kappa in Grisu. gen_digits_params params = process_specs(specs, cached_exp + exp, buf); fp_value.normalize(); fp scaled_value = fp_value * cached_pow; diff --git a/include/fmt/format.h b/include/fmt/format.h index 63fbcae26f9e..1bb24a529687 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -766,16 +766,16 @@ typedef basic_data<> data; #ifdef FMT_BUILTIN_CLZLL // Returns the number of decimal digits in n. Leading zeros are not counted // except for n == 0 in which case count_digits returns 1. -inline unsigned count_digits(uint64_t n) { +inline int count_digits(uint64_t n) { // Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 // and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits. int t = (64 - FMT_BUILTIN_CLZLL(n | 1)) * 1233 >> 12; - return to_unsigned(t) - (n < data::ZERO_OR_POWERS_OF_10_64[t]) + 1; + return t - (n < data::ZERO_OR_POWERS_OF_10_64[t]) + 1; } #else // Fallback version of count_digits used when __builtin_clz is not available. -inline unsigned count_digits(uint64_t n) { - unsigned count = 1; +inline int count_digits(uint64_t n) { + int count = 1; for (;;) { // Integer division is slow so do it for a group of four digits instead // of for every digit. The idea comes from the talk by Alexandrescu @@ -896,9 +896,9 @@ class decimal_formatter_null : public decimal_formatter { #ifdef FMT_BUILTIN_CLZ // Optional version of count_digits for better performance on 32-bit platforms. -inline unsigned count_digits(uint32_t n) { +inline int count_digits(uint32_t n) { int t = (32 - FMT_BUILTIN_CLZ(n | 1)) * 1233 >> 12; - return to_unsigned(t) - (n < data::ZERO_OR_POWERS_OF_10_32[t]) + 1; + return t - (n < data::ZERO_OR_POWERS_OF_10_32[t]) + 1; } #endif @@ -1009,7 +1009,8 @@ inline Char *format_uint(Char *buffer, UInt value, int num_digits, do { const char *digits = upper ? "0123456789ABCDEF" : "0123456789abcdef"; unsigned digit = (value & ((1 << BASE_BITS) - 1)); - *--buffer = static_cast(BASE_BITS < 4 ? '0' + digit : digits[digit]); + *--buffer = static_cast(BASE_BITS < 4 ? static_cast('0' + digit) + : digits[digit]); } while ((value >>= BASE_BITS) != 0); return end; } @@ -1977,7 +1978,7 @@ FMT_CONSTEXPR bool find(Ptr first, Ptr last, T value, Ptr &out) { template <> inline bool find( const char *first, const char *last, char value, const char *&out) { - out = static_cast(std::memchr(first, value, last - first)); + out = static_cast(std::memchr(first, value, internal::to_unsigned(last - first))); return out != FMT_NULL; } @@ -2060,7 +2061,7 @@ class format_string_checker { public: explicit FMT_CONSTEXPR format_string_checker( basic_string_view format_str, ErrorHandler eh) - : arg_id_(-1), context_(format_str, eh), + : arg_id_((std::numeric_limits::max)()), context_(format_str, eh), parse_funcs_{&parse_format_specs...} {} FMT_CONSTEXPR void on_text(const Char *, const Char *) {} @@ -2080,7 +2081,7 @@ class format_string_checker { FMT_CONSTEXPR const Char *on_format_specs(const Char *begin, const Char *) { context_.advance_to(begin); - return to_unsigned(arg_id_) < NUM_ARGS ? + return arg_id_ < NUM_ARGS ? parse_funcs_[arg_id_](context_) : begin; } @@ -2093,14 +2094,14 @@ class format_string_checker { enum { NUM_ARGS = sizeof...(Args) }; FMT_CONSTEXPR void check_arg_id() { - if (internal::to_unsigned(arg_id_) >= NUM_ARGS) + if (arg_id_ >= NUM_ARGS) context_.on_error("argument index out of range"); } // Format specifier parsing function. typedef const Char *(*parse_func)(parse_context_type &); - int arg_id_; + unsigned arg_id_; parse_context_type context_; parse_func parse_funcs_[NUM_ARGS > 0 ? NUM_ARGS : 1]; }; @@ -2322,9 +2323,9 @@ class basic_writer { // // where are written by f(it). template - void write_int(unsigned num_digits, string_view prefix, + void write_int(int num_digits, string_view prefix, const Spec &spec, F f) { - std::size_t size = prefix.size() + num_digits; + std::size_t size = prefix.size() + internal::to_unsigned(num_digits); char_type fill = static_cast(spec.fill()); std::size_t padding = 0; if (spec.align() == ALIGN_NUMERIC) { @@ -2332,9 +2333,9 @@ class basic_writer { padding = spec.width() - size; size = spec.width(); } - } else if (spec.precision > static_cast(num_digits)) { + } else if (spec.precision > num_digits) { size = prefix.size() + internal::to_unsigned(spec.precision); - padding = internal::to_unsigned(spec.precision) - num_digits; + padding = internal::to_unsigned(spec.precision - num_digits); fill = static_cast('0'); } align_spec as = spec; @@ -2351,8 +2352,8 @@ class basic_writer { bool is_negative = internal::is_negative(value); if (is_negative) abs_value = 0 - abs_value; - unsigned num_digits = internal::count_digits(abs_value); - auto &&it = reserve((is_negative ? 1 : 0) + num_digits); + int num_digits = internal::count_digits(abs_value); + auto &&it = reserve((is_negative ? 1 : 0) + static_cast(num_digits)); if (is_negative) *it++ = static_cast('-'); it = internal::format_decimal(it, abs_value, num_digits); @@ -2373,9 +2374,9 @@ class basic_writer { // Counts the number of digits in abs_value. BITS = log2(radix). template - unsigned count_digits() const { + int count_digits() const { unsigned_type n = abs_value; - unsigned num_digits = 0; + int num_digits = 0; do { ++num_digits; } while ((n >>= BITS) != 0); @@ -2397,7 +2398,7 @@ class basic_writer { struct dec_writer { unsigned_type abs_value; - unsigned num_digits; + int num_digits; template void operator()(It &&it) const { @@ -2406,14 +2407,14 @@ class basic_writer { }; void on_dec() { - unsigned num_digits = internal::count_digits(abs_value); + int num_digits = internal::count_digits(abs_value); writer.write_int(num_digits, get_prefix(), spec, dec_writer{abs_value, num_digits}); } struct hex_writer { int_writer &self; - unsigned num_digits; + int num_digits; template void operator()(It &&it) const { @@ -2427,7 +2428,7 @@ class basic_writer { prefix[prefix_size++] = '0'; prefix[prefix_size++] = static_cast(spec.type); } - unsigned num_digits = count_digits<4>(); + int num_digits = count_digits<4>(); writer.write_int(num_digits, get_prefix(), spec, hex_writer{*this, num_digits}); } @@ -2435,7 +2436,7 @@ class basic_writer { template struct bin_writer { unsigned_type abs_value; - unsigned num_digits; + int num_digits; template void operator()(It &&it) const { @@ -2448,15 +2449,15 @@ class basic_writer { prefix[prefix_size++] = '0'; prefix[prefix_size++] = static_cast(spec.type); } - unsigned num_digits = count_digits<1>(); + int num_digits = count_digits<1>(); writer.write_int(num_digits, get_prefix(), spec, bin_writer<1>{abs_value, num_digits}); } void on_oct() { - unsigned num_digits = count_digits<3>(); + int num_digits = count_digits<3>(); if (spec.has(HASH_FLAG) && - spec.precision <= static_cast(num_digits)) { + spec.precision <= num_digits) { // Octal prefix '0' is counted as a digit, so only add it if precision // is not greater than the number of digits. prefix[prefix_size++] = '0'; @@ -2469,7 +2470,7 @@ class basic_writer { struct num_writer { unsigned_type abs_value; - unsigned size; + int size; char_type sep; template @@ -2481,9 +2482,9 @@ class basic_writer { }; void on_num() { - unsigned num_digits = internal::count_digits(abs_value); + int num_digits = internal::count_digits(abs_value); char_type sep = internal::thousands_sep(writer.locale_); - unsigned size = num_digits + SEP_SIZE * ((num_digits - 1) / 3); + int size = num_digits + SEP_SIZE * ((num_digits - 1) / 3); writer.write_int(size, get_prefix(), spec, num_writer{abs_value, size, sep}); } @@ -2907,9 +2908,9 @@ inline void format_decimal(char *&buffer, T value) { *buffer++ = internal::data::DIGITS[index + 1]; return; } - unsigned num_digits = internal::count_digits(abs_value); + int num_digits = internal::count_digits(abs_value); internal::format_decimal( - internal::make_checked(buffer, num_digits), abs_value, num_digits); + internal::make_checked(buffer, internal::to_unsigned(num_digits)), abs_value, num_digits); buffer += num_digits; }