From 34b54183599207632cbd8cfcd389173b4f90b8b8 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Thu, 13 Jun 2019 07:25:29 -0700 Subject: [PATCH 1/4] Fix warnings --- include/fmt/chrono.h | 22 +++++++++++----------- include/fmt/format.h | 5 +---- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index ff23cfba601e..e891b0425642 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -385,9 +385,9 @@ inline bool isnan(T value) { return std::isnan(value); } -template inline int to_int(T value) { - FMT_ASSERT(isnan(value) || (value >= (std::numeric_limits::min)() && - value <= (std::numeric_limits::max)()), +// Convers value to int and checks that it's in the range [0, upper). +template inline int to_int(T value, int upper) { + FMT_ASSERT(isnan(value) || (value >= 0 && value <= upper), "invalid value"); return static_cast(value); } @@ -483,9 +483,9 @@ struct chrono_formatter { std::tm time() const { auto time = std::tm(); - time.tm_hour = to_int(hour()); - time.tm_min = to_int(minute()); - time.tm_sec = to_int(second()); + time.tm_hour = to_int(hour(), 24); + time.tm_min = to_int(minute(), 60); + time.tm_sec = to_int(second(), 60); return time; } @@ -500,7 +500,7 @@ struct chrono_formatter { write_sign(); if (isnan(value)) return write_nan(); typedef typename int_traits::main_type main_type; - main_type n = to_unsigned(to_int(value)); + main_type n = to_unsigned(to_int(value, (std::numeric_limits::max)())); 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); @@ -541,21 +541,21 @@ struct chrono_formatter { void on_24_hour(numeric_system ns) { if (ns == numeric_system::standard) return write(hour(), 2); auto time = tm(); - time.tm_hour = to_int(hour()); + time.tm_hour = to_int(hour(), 24); format_localized(time, "%OH"); } void on_12_hour(numeric_system ns) { if (ns == numeric_system::standard) return write(hour12(), 2); auto time = tm(); - time.tm_hour = to_int(hour12()); + time.tm_hour = to_int(hour12(), 12); format_localized(time, "%OI"); } void on_minute(numeric_system ns) { if (ns == numeric_system::standard) return write(minute(), 2); auto time = tm(); - time.tm_min = to_int(minute()); + time.tm_min = to_int(minute(), 60); format_localized(time, "%OM"); } @@ -570,7 +570,7 @@ struct chrono_formatter { return; } auto time = tm(); - time.tm_sec = to_int(second()); + time.tm_sec = to_int(second(), 60); format_localized(time, "%OS"); } diff --git a/include/fmt/format.h b/include/fmt/format.h index 0ed2716751e8..3e248039f2bb 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -94,10 +95,6 @@ # endif #endif -#if FMT_SECURE_SCL -# include -#endif - #ifdef __has_builtin # define FMT_HAS_BUILTIN(x) __has_builtin(x) #else From a9940192fbdda1910ce62859529db9bee426ca61 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Thu, 13 Jun 2019 08:55:33 -0700 Subject: [PATCH 2/4] Fix warnings --- include/fmt/chrono.h | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index e891b0425642..e080b958b384 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -386,9 +386,16 @@ inline bool isnan(T value) { } // Convers value to int and checks that it's in the range [0, upper). -template inline int to_int(T value, int upper) { - FMT_ASSERT(isnan(value) || (value >= 0 && value <= upper), - "invalid value"); +template ::value)> +inline int to_nonnegative_int(T value, int upper) { + FMT_ASSERT(value >= 0 && value <= upper, "invalid value"); + return static_cast(value); +} +template ::value)> +inline int to_nonnegative_int(T value, int upper) { + FMT_ASSERT( + std::isnan(value) || (value >= 0 && value <= static_cast(upper)), + "invalid value"); return static_cast(value); } @@ -483,9 +490,9 @@ struct chrono_formatter { std::tm time() const { auto time = std::tm(); - time.tm_hour = to_int(hour(), 24); - time.tm_min = to_int(minute(), 60); - time.tm_sec = to_int(second(), 60); + time.tm_hour = to_nonnegative_int(hour(), 24); + time.tm_min = to_nonnegative_int(minute(), 60); + time.tm_sec = to_nonnegative_int(second(), 60); return time; } @@ -500,7 +507,8 @@ struct chrono_formatter { write_sign(); if (isnan(value)) return write_nan(); typedef typename int_traits::main_type main_type; - main_type n = to_unsigned(to_int(value, (std::numeric_limits::max)())); + main_type n = to_unsigned( + to_nonnegative_int(value, (std::numeric_limits::max)())); 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); @@ -541,21 +549,21 @@ struct chrono_formatter { void on_24_hour(numeric_system ns) { if (ns == numeric_system::standard) return write(hour(), 2); auto time = tm(); - time.tm_hour = to_int(hour(), 24); + time.tm_hour = to_nonnegative_int(hour(), 24); format_localized(time, "%OH"); } void on_12_hour(numeric_system ns) { if (ns == numeric_system::standard) return write(hour12(), 2); auto time = tm(); - time.tm_hour = to_int(hour12(), 12); + time.tm_hour = to_nonnegative_int(hour12(), 12); format_localized(time, "%OI"); } void on_minute(numeric_system ns) { if (ns == numeric_system::standard) return write(minute(), 2); auto time = tm(); - time.tm_min = to_int(minute(), 60); + time.tm_min = to_nonnegative_int(minute(), 60); format_localized(time, "%OM"); } @@ -570,7 +578,7 @@ struct chrono_formatter { return; } auto time = tm(); - time.tm_sec = to_int(second(), 60); + time.tm_sec = to_nonnegative_int(second(), 60); format_localized(time, "%OS"); } From 874d6727e4eeaa132aa3d078de5ada71a19b36da Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Thu, 13 Jun 2019 20:16:06 -0700 Subject: [PATCH 3/4] Remove workarounds for pre-C++11 compilers --- include/fmt/format.h | 38 +++++++------------------------------- include/fmt/printf.h | 12 +++++------- test/format | 4 +--- test/format-impl-test.cc | 4 ++-- test/format-test.cc | 4 +--- 5 files changed, 16 insertions(+), 46 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 3e248039f2bb..e0edd3f6879a 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -265,31 +265,9 @@ inline Dest bit_cast(const Source& source) { return dest; } -// An implementation of begin and end for pre-C++11 compilers such as gcc 4. -template -FMT_CONSTEXPR auto begin(const C& c) -> decltype(c.begin()) { - return c.begin(); -} -template -FMT_CONSTEXPR T* begin(T (&array)[N]) FMT_NOEXCEPT { - return array; -} -template FMT_CONSTEXPR auto end(const C& c) -> decltype(c.end()) { - return c.end(); -} -template -FMT_CONSTEXPR T* end(T (&array)[N]) FMT_NOEXCEPT { - return array + N; -} - -// An implementation of iterator_t for pre-C++20 compilers such as gcc 4. +// An implementation of iterator_t for pre-C++20 systems. template struct iterator_t { - typedef decltype(internal::begin(std::declval())) type; -}; - -// For std::result_of in gcc 4.4. -template struct function { - template struct result { typedef Result type; }; + typedef decltype(std::begin(std::declval())) type; }; template @@ -1531,7 +1509,7 @@ FMT_CONSTEXPR unsigned parse_nonnegative_int(const Char*& begin, return value; } -template class custom_formatter : public function { +template class custom_formatter { private: typedef typename Context::char_type char_type; @@ -1558,8 +1536,7 @@ template struct is_integer { }; }; -template -class width_checker : public function { +template class width_checker { public: explicit FMT_CONSTEXPR width_checker(ErrorHandler& eh) : handler_(eh) {} @@ -1579,8 +1556,7 @@ class width_checker : public function { ErrorHandler& handler_; }; -template -class precision_checker : public function { +template class precision_checker { public: explicit FMT_CONSTEXPR precision_checker(ErrorHandler& eh) : handler_(eh) {} @@ -3339,13 +3315,13 @@ arg_join join(It begin, It end, wstring_view sep) { template arg_join::type, char> join( const Range& range, string_view sep) { - return join(internal::begin(range), internal::end(range), sep); + return join(std::begin(range), std::end(range), sep); } template arg_join::type, wchar_t> join( const Range& range, wstring_view sep) { - return join(internal::begin(range), internal::end(range), sep); + return join(std::begin(range), std::end(range), sep); } #endif diff --git a/include/fmt/printf.h b/include/fmt/printf.h index c3a48ed4794e..d52f849c7600 100644 --- a/include/fmt/printf.h +++ b/include/fmt/printf.h @@ -38,7 +38,7 @@ template <> struct int_checker { static bool fits_in_int(int) { return true; } }; -class printf_precision_handler : public function { +class printf_precision_handler { public: template ::value)> int operator()(T value) { @@ -55,7 +55,7 @@ class printf_precision_handler : public function { }; // An argument visitor that returns true iff arg is a zero integer. -class is_zero_int : public function { +class is_zero_int { public: template ::value)> bool operator()(T value) { @@ -72,8 +72,7 @@ template struct make_unsigned_or_bool : std::make_unsigned {}; template <> struct make_unsigned_or_bool { typedef bool type; }; -template -class arg_converter : public function { +template class arg_converter { private: typedef typename Context::char_type Char; @@ -129,7 +128,7 @@ void convert_arg(basic_format_arg& arg, Char type) { } // Converts an integer argument to char for printf. -template class char_converter : public function { +template class char_converter { private: basic_format_arg& arg_; @@ -148,8 +147,7 @@ template class char_converter : public function { // Checks if an argument is a valid printf width specifier and sets // left alignment if it is negative. -template -class printf_width_handler : public function { +template class printf_width_handler { private: typedef basic_format_specs format_specs; diff --git a/test/format b/test/format index 53a7b5df5c14..60dc60e56a49 100644 --- a/test/format +++ b/test/format @@ -489,9 +489,7 @@ namespace detail { template class arg_formatter - : public fmt::internal::function< - typename fmt::internal::arg_formatter_base::iterator>, - public fmt::internal::arg_formatter_base { + : public fmt::internal::arg_formatter_base { private: using char_type = typename Range::value_type; using base = fmt::internal::arg_formatter_base; diff --git a/test/format-impl-test.cc b/test/format-impl-test.cc index 94bc5eeafbbf..2b0067b0f850 100644 --- a/test/format-impl-test.cc +++ b/test/format-impl-test.cc @@ -143,7 +143,7 @@ TEST(FPTest, GrisuFormatCompilesWithNonIEEEDouble) { grisu_format(4.2f, buf, -1, false, exp); } -template struct ValueExtractor : fmt::internal::function { +template struct value_extractor { T operator()(T value) { return value; } template FMT_NORETURN T operator()(U) { @@ -157,7 +157,7 @@ TEST(FormatTest, ArgConverter) { fmt::visit_format_arg( fmt::internal::arg_converter(arg, 'd'), arg); - EXPECT_EQ(value, fmt::visit_format_arg(ValueExtractor(), arg)); + EXPECT_EQ(value, fmt::visit_format_arg(value_extractor(), arg)); } TEST(FormatTest, FormatNegativeNaN) { diff --git a/test/format-test.cc b/test/format-test.cc index 0d7153e36da8..6c05854cd289 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1890,9 +1890,7 @@ TEST(FormatTest, FixedEnum) { EXPECT_EQ("0", fmt::format("{}", B)); } typedef fmt::back_insert_range> buffer_range; class mock_arg_formatter - : public fmt::internal::function< - fmt::internal::arg_formatter_base::iterator>, - public fmt::internal::arg_formatter_base { + : public fmt::internal::arg_formatter_base { private: MOCK_METHOD1(call, void(long long value)); From 12f468388384846c35cc9151c4b860fbfa80ab71 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Thu, 13 Jun 2019 21:32:58 -0700 Subject: [PATCH 4/4] Make iterator_t an alias template --- include/fmt/format.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index e0edd3f6879a..d6130983ec04 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -266,9 +266,8 @@ inline Dest bit_cast(const Source& source) { } // An implementation of iterator_t for pre-C++20 systems. -template struct iterator_t { - typedef decltype(std::begin(std::declval())) type; -}; +template +using iterator_t = decltype(std::begin(std::declval())); template typename Allocator::value_type* allocate(Allocator& alloc, std::size_t n) { @@ -3313,13 +3312,13 @@ arg_join join(It begin, It end, wstring_view sep) { \endrst */ template -arg_join::type, char> join( +arg_join, char> join( const Range& range, string_view sep) { return join(std::begin(range), std::end(range), sep); } template -arg_join::type, wchar_t> join( +arg_join, wchar_t> join( const Range& range, wstring_view sep) { return join(std::begin(range), std::end(range), sep); }