diff --git a/upstream_utils/fmt.py b/upstream_utils/fmt.py index 9380eb1c22..abb671031c 100755 --- a/upstream_utils/fmt.py +++ b/upstream_utils/fmt.py @@ -35,7 +35,7 @@ def copy_upstream_src(wpilib_root): def main(): name = "fmt" url = "https://github.com/fmtlib/fmt" - tag = "11.0.1" + tag = "11.0.2" fmt = Lib(name, url, tag, copy_upstream_src) fmt.main() diff --git a/upstream_utils/fmt_patches/0001-Suppress-warnings-we-can-t-fix.patch b/upstream_utils/fmt_patches/0001-Suppress-warnings-we-can-t-fix.patch index b528fd168e..5cd394af43 100644 --- a/upstream_utils/fmt_patches/0001-Suppress-warnings-we-can-t-fix.patch +++ b/upstream_utils/fmt_patches/0001-Suppress-warnings-we-can-t-fix.patch @@ -8,10 +8,10 @@ Subject: [PATCH] Suppress warnings we can't fix 1 file changed, 7 insertions(+) diff --git a/include/fmt/format.h b/include/fmt/format.h -index 7c2a19b4084de8f8bb9376d91c9a508f396e50df..ed372239a24466d32d5f81514efbdbe2ddafdba8 100644 +index 67f0ab739b0de55d03ab3e71424f1eb9e9c9bdfc..cf5ad9820683130ce9895f5d216d9b9efd0185ac 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h -@@ -1268,7 +1268,14 @@ inline auto equal2(const char* lhs, const char* rhs) -> bool { +@@ -1276,7 +1276,14 @@ inline auto equal2(const char* lhs, const char* rhs) -> bool { template FMT_CONSTEXPR20 FMT_INLINE void copy2(Char* dst, const char* src) { if (!is_constant_evaluated() && sizeof(Char) == sizeof(char)) { diff --git a/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/base.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/base.h index f440cffd20..6276494253 100644 --- a/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/base.h +++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/base.h @@ -23,7 +23,7 @@ #endif // The fmt library version in the form major * 10000 + minor * 100 + patch. -#define FMT_VERSION 110001 +#define FMT_VERSION 110002 // Detect compiler versions. #if defined(__clang__) && !defined(__ibmxl__) @@ -441,7 +441,8 @@ struct is_std_string_like : std::false_type {}; template struct is_std_string_like().find_first_of( typename T::value_type(), 0))>> - : std::true_type {}; + : std::is_convertible().data()), + const typename T::value_type*> {}; // Returns true iff the literal encoding is UTF-8. constexpr auto is_utf8_enabled() -> bool { @@ -466,6 +467,7 @@ template FMT_CONSTEXPR auto length(const Char* s) -> size_t { template FMT_CONSTEXPR auto compare(const Char* s1, const Char* s2, std::size_t n) -> int { + if (!is_constant_evaluated() && sizeof(Char) == 1) return memcmp(s1, s2, n); for (; n != 0; ++s1, ++s2, --n) { if (*s1 < *s2) return -1; if (*s1 > *s2) return 1; @@ -473,14 +475,22 @@ FMT_CONSTEXPR auto compare(const Char* s1, const Char* s2, std::size_t n) return 0; } +namespace adl { +using namespace std; + +template +auto invoke_back_inserter() + -> decltype(back_inserter(std::declval())); +} // namespace adl + template struct is_back_insert_iterator : std::false_type {}; + template struct is_back_insert_iterator< - It, - bool_constant())), - It>::value>> : std::true_type {}; + It, bool_constant()), + It>::value>> : std::true_type {}; // Extracts a reference to the container from *insert_iterator. template @@ -611,11 +621,12 @@ namespace detail { // to it, deducing Char. Explicitly convertible types such as the ones returned // from FMT_STRING are intentionally excluded. template ::value)> -auto to_string_view(const Char* s) -> basic_string_view { +constexpr auto to_string_view(const Char* s) -> basic_string_view { return s; } template ::value)> -auto to_string_view(const T& s) -> basic_string_view { +constexpr auto to_string_view(const T& s) + -> basic_string_view { return s; } template @@ -919,12 +930,9 @@ template class buffer { try_reserve(size_ + count); auto free_cap = capacity_ - size_; if (free_cap < count) count = free_cap; - if (std::is_same::value) { - memcpy(ptr_ + size_, begin, count * sizeof(T)); - } else { - T* out = ptr_ + size_; - for (size_t i = 0; i < count; ++i) out[i] = begin[i]; - } + // A loop is faster than memcpy on small sizes. + T* out = ptr_ + size_; + for (size_t i = 0; i < count; ++i) out[i] = begin[i]; size_ += count; begin += count; } @@ -1157,6 +1165,7 @@ template class basic_appender { using difference_type = ptrdiff_t; using pointer = T*; using reference = T&; + using container_type = detail::buffer; FMT_UNCHECKED_ITERATOR(basic_appender); FMT_CONSTEXPR basic_appender(detail::buffer& buf) : buffer_(&buf) {} @@ -1173,6 +1182,8 @@ template class basic_appender { using appender = basic_appender; namespace detail { +template +struct is_back_insert_iterator> : std::true_type {}; template struct locking : std::true_type {}; @@ -1189,12 +1200,6 @@ FMT_CONSTEXPR inline auto is_locking() -> bool { } // An optimized version of std::copy with the output value type (T). -template -auto copy(InputIt begin, InputIt end, appender out) -> appender { - get_container(out).append(begin, end); - return out; -} - template ::value)> auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { @@ -1209,14 +1214,6 @@ FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { return out; } -template -FMT_CONSTEXPR auto copy(const T* begin, const T* end, T* out) -> T* { - if (is_constant_evaluated()) return copy(begin, end, out); - auto size = to_unsigned(end - begin); - if (size > 0) memcpy(out, begin, size * sizeof(T)); - return out + size; -} - template FMT_CONSTEXPR auto copy(basic_string_view s, OutputIt out) -> OutputIt { return copy(s.begin(), s.end(), out); @@ -1238,12 +1235,25 @@ constexpr auto has_const_formatter() -> bool { return has_const_formatter_impl(static_cast(nullptr)); } +template +struct is_buffer_appender : std::false_type {}; +template +struct is_buffer_appender< + It, bool_constant< + is_back_insert_iterator::value && + std::is_base_of, + typename It::container_type>::value>> + : std::true_type {}; + // Maps an output iterator to a buffer. -template +template ::value)> auto get_buffer(OutputIt out) -> iterator_buffer { return iterator_buffer(out); } -template auto get_buffer(basic_appender out) -> buffer& { +template ::value)> +auto get_buffer(OutputIt out) -> buffer& { return get_container(out); } @@ -1475,6 +1485,12 @@ template struct arg_mapper { FMT_MAP_API auto map(void* val) -> const void* { return val; } FMT_MAP_API auto map(const void* val) -> const void* { return val; } + FMT_MAP_API auto map(volatile void* val) -> const void* { + return const_cast(val); + } + FMT_MAP_API auto map(const volatile void* val) -> const void* { + return const_cast(val); + } FMT_MAP_API auto map(std::nullptr_t val) -> const void* { return val; } // Use SFINAE instead of a const T* parameter to avoid a conflict with the @@ -1760,7 +1776,7 @@ template class basic_format_arg { * `vis(value)` will be called with the value of type `double`. */ template - FMT_CONSTEXPR auto visit(Visitor&& vis) const -> decltype(vis(0)) { + FMT_CONSTEXPR FMT_INLINE auto visit(Visitor&& vis) const -> decltype(vis(0)) { switch (type_) { case detail::type::none_type: break; diff --git a/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format-inl.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format-inl.h index 8d07cc6723..a887483b6f 100644 --- a/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format-inl.h +++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format-inl.h @@ -1443,12 +1443,26 @@ template struct span { size_t size; }; -#ifdef _WIN32 -inline void flockfile(FILE* f) { _lock_file(f); } -inline void funlockfile(FILE* f) { _unlock_file(f); } -inline int getc_unlocked(FILE* f) { return _fgetc_nolock(f); } +template auto flockfile(F* f) -> decltype(_lock_file(f)) { + _lock_file(f); +} +template auto funlockfile(F* f) -> decltype(_unlock_file(f)) { + _unlock_file(f); +} + +#ifndef getc_unlocked +template auto getc_unlocked(F* f) -> decltype(_fgetc_nolock(f)) { + return _fgetc_nolock(f); +} #endif +template +struct has_flockfile : std::false_type {}; + +template +struct has_flockfile()))>> + : std::true_type {}; + // A FILE wrapper. F is FILE defined as a template parameter to make system API // detection work. template class file_base { @@ -1619,7 +1633,15 @@ inline auto get_file(FILE* f, ...) -> fallback_file { return f; } using file_ref = decltype(get_file(static_cast(nullptr), 0)); +template class file_print_buffer : public buffer { + public: + explicit file_print_buffer(F*) : buffer(nullptr, size_t()) {} +}; + +template +class file_print_buffer::value>> + : public buffer { private: file_ref file_; @@ -1634,7 +1656,7 @@ class file_print_buffer : public buffer { } public: - explicit file_print_buffer(FILE* f) : buffer(grow, size_t()), file_(f) { + explicit file_print_buffer(F* f) : buffer(grow, size_t()), file_(f) { flockfile(f); file_.init_buffer(); auto buf = file_.get_write_buffer(); @@ -1643,7 +1665,8 @@ class file_print_buffer : public buffer { ~file_print_buffer() { file_.advance_write_buffer(size()); bool flush = file_.needs_flush(); - funlockfile(file_); + F* f = file_; // Make funlockfile depend on the template parameter F + funlockfile(f); // for the system API detection to work. if (flush) fflush(file_); } }; @@ -1692,8 +1715,9 @@ FMT_FUNC void vprint_buffered(std::FILE* f, string_view fmt, format_args args) { } FMT_FUNC void vprint(std::FILE* f, string_view fmt, format_args args) { - if (!detail::file_ref(f).is_buffered()) return vprint_buffered(f, fmt, args); - auto&& buffer = detail::file_print_buffer(f); + if (!detail::file_ref(f).is_buffered() || !detail::has_flockfile<>()) + return vprint_buffered(f, fmt, args); + auto&& buffer = detail::file_print_buffer<>(f); return detail::vformat_to(buffer, fmt, args); } diff --git a/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format.h index ed372239a2..cf5ad98206 100644 --- a/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format.h +++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format.h @@ -106,6 +106,13 @@ # define FMT_NOINLINE #endif +namespace std { +template <> struct iterator_traits { + using iterator_category = output_iterator_tag; + using value_type = char; +}; +} // namespace std + #ifndef FMT_THROW # if FMT_EXCEPTIONS # if FMT_MSC_VERSION || defined(__NVCC__) @@ -546,6 +553,7 @@ constexpr auto to_pointer(OutputIt, size_t) -> T* { template auto to_pointer(basic_appender it, size_t n) -> T* { buffer& buf = get_container(it); auto size = buf.size(); + buf.try_reserve(size + n); if (buf.capacity() < size + n) return nullptr; buf.try_resize(size + n); return buf.data() + size; @@ -1119,7 +1127,7 @@ template constexpr auto sign(Sign s) -> Char { #if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604 static_assert(std::is_same::value, ""); #endif - return static_cast("\0-+ "[s]); + return static_cast(((' ' << 24) | ('+' << 16) | ('-' << 8)) >> (s * 8)); } template FMT_CONSTEXPR auto count_digits_fallback(T n) -> int { @@ -2324,15 +2332,13 @@ FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { if (negative) abs_value = ~abs_value + 1; int num_digits = count_digits(abs_value); auto size = (negative ? 1 : 0) + static_cast(num_digits); - auto it = reserve(out, size); - if (auto ptr = to_pointer(it, size)) { + if (auto ptr = to_pointer(out, size)) { if (negative) *ptr++ = static_cast('-'); format_decimal(ptr, abs_value, num_digits); return out; } - if (negative) *it++ = static_cast('-'); - it = format_decimal(it, abs_value, num_digits).end; - return base_iterator(out, it); + if (negative) *out++ = static_cast('-'); + return format_decimal(out, abs_value, num_digits).end; } // DEPRECATED! @@ -3636,9 +3642,7 @@ auto write(OutputIt out, monostate, format_specs = {}, locale_ref = {}) template FMT_CONSTEXPR auto write(OutputIt out, basic_string_view value) -> OutputIt { - auto it = reserve(out, value.size()); - it = copy_noinline(value.begin(), value.end(), it); - return base_iterator(out, it); + return copy_noinline(value.begin(), value.end(), out); } template ::value>> : formatter, Char> { template auto format(const T& value, FormatContext& ctx) const -> decltype(ctx.out()) { - using base = formatter, Char>; auto&& val = format_as(value); // Make an lvalue reference for format. - return base::format(val, ctx); + return formatter, Char>::format(val, ctx); } }; -#define FMT_FORMAT_AS(Type, Base) \ - template \ - struct formatter : formatter {} +#define FMT_FORMAT_AS(Type, Base) \ + template \ + struct formatter : formatter { \ + template \ + auto format(Type value, FormatContext& ctx) const -> decltype(ctx.out()) { \ + return formatter::format(value, ctx); \ + } \ + } FMT_FORMAT_AS(signed char, int); FMT_FORMAT_AS(unsigned char, unsigned); diff --git a/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/ranges.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/ranges.h index f387903cf6..0d3dfbd8d3 100644 --- a/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/ranges.h +++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/ranges.h @@ -490,7 +490,7 @@ struct range_formatter< auto out = ctx.out(); auto it = detail::range_begin(range); auto end = detail::range_end(range); - if (is_debug) return write_debug_string(out, it, end); + if (is_debug) return write_debug_string(out, std::move(it), end); out = detail::copy(opening_bracket_, out); int i = 0;