diff --git a/include/fmt/format.h b/include/fmt/format.h index 433966d39ba30..4945fa0f690f4 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -43,7 +43,6 @@ #include // std::memcpy #include // std::initializer_list #include // std::numeric_limits -#include // std::allocator_traits #include // std::runtime_error #include // std::string #include // std::system_error @@ -907,8 +906,8 @@ class basic_memory_buffer : public detail::buffer { static FMT_CONSTEXPR20 void grow(detail::buffer& buf, size_t size) { detail::abort_fuzzing_if(size > 5000); auto& self = static_cast(buf); - const size_t max_size = - std::allocator_traits::max_size(self.alloc_); + constexpr size_t max_size = + detail::max_value() / sizeof(T); size_t old_capacity = buf.capacity(); size_t new_capacity = old_capacity + old_capacity / 2; if (size > new_capacity) @@ -916,8 +915,7 @@ class basic_memory_buffer : public detail::buffer { else if (new_capacity > max_size) new_capacity = size > max_size ? size : max_size; T* old_data = buf.data(); - T* new_data = - std::allocator_traits::allocate(self.alloc_, new_capacity); + T* new_data = self.alloc_.allocate(new_capacity); // Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481). detail::assume(buf.size() <= new_capacity); // The following code doesn't throw, so the raw pointer above doesn't leak. diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index c0acfa7747563..f66b34102667c 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -360,9 +360,7 @@ struct formatter struct is_range { static constexpr const bool value = - detail::is_range_::value && !detail::has_to_string_view::value && - !std::is_convertible>::value && - !std::is_convertible>::value; + detail::is_range_::value && !detail::has_to_string_view::value; }; namespace detail { diff --git a/test/format-test.cc b/test/format-test.cc index 3e53147d3f681..a76c44cf76505 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -413,37 +413,30 @@ TEST(memory_buffer_test, exception_in_deallocate) { EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size)); } -template -class max_size_allocator : public Allocator { +class smol_allocator : public std::allocator { public: - using typename Allocator::value_type; - size_t max_size() const noexcept { return MaxSize; } - value_type* allocate(size_t n) { - if (n > max_size()) { + using size_type = unsigned char; + + auto allocate(size_t n) -> value_type* { + if (n > fmt::detail::max_value()) throw std::length_error("size > max_size"); - } - return std::allocator_traits::allocate( - *static_cast(this), n); + return std::allocator::allocate(n); } void deallocate(value_type* p, size_t n) { - std::allocator_traits::deallocate(*static_cast(this), - p, n); + std::allocator::deallocate(p, n); } }; TEST(memory_buffer_test, max_size_allocator) { - // 160 = 128 + 32 - using test_allocator = max_size_allocator, 160>; - basic_memory_buffer buffer; - buffer.resize(128); - // new_capacity = 128 + 128/2 = 192 > 160 - buffer.resize(160); // Shouldn't throw. + basic_memory_buffer buffer; + buffer.resize(200); + // new_capacity = 200 + 200/2 = 300 > 256 + buffer.resize(255); // Shouldn't throw. } TEST(memory_buffer_test, max_size_allocator_overflow) { - using test_allocator = max_size_allocator, 160>; - basic_memory_buffer buffer; - EXPECT_THROW(buffer.resize(161), std::exception); + basic_memory_buffer buffer; + EXPECT_THROW(buffer.resize(256), std::exception); } TEST(format_test, exception_from_lib) { diff --git a/test/mock-allocator.h b/test/mock-allocator.h index dc4942f1758df..baba1cda0ba95 100644 --- a/test/mock-allocator.h +++ b/test/mock-allocator.h @@ -17,9 +17,12 @@ template class mock_allocator { public: + using value_type = T; + using size_type = size_t; + mock_allocator() {} mock_allocator(const mock_allocator&) {} - using value_type = T; + MOCK_METHOD(T*, allocate, (size_t)); MOCK_METHOD(void, deallocate, (T*, size_t)); }; @@ -35,6 +38,7 @@ template class allocator_ref { public: using value_type = typename Allocator::value_type; + using size_type = typename Allocator::size_type; explicit allocator_ref(Allocator* alloc = nullptr) : alloc_(alloc) {}