diff --git a/include/fmt/format.h b/include/fmt/format.h index fbe37371..d0503ba8 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -53,9 +53,7 @@ # include // std::signbit # include // std::numeric_limits -# if FMT_USE_CONSTEVAL -# include // std::construct_at -# elif defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI) +# if defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI) // Workaround for pre gcc 5 libstdc++. # include // std::allocator_traits # endif @@ -894,20 +892,18 @@ template struct allocator : private std::decay { FMT_ASSERT(n <= max_value() / sizeof(T), ""); #if FMT_USE_CONSTEVAL // Use the builtin directly to avoid C++ runtime dependencies at -O0. - if (__builtin_is_constant_evaluated()) - return std::allocator().allocate(n); + if (__builtin_is_constant_evaluated()) return new T[n]; #endif return static_cast(detail::allocate(n * sizeof(T))); } - FMT_CONSTEXPR20 void deallocate(T* p, size_t n) { + FMT_CONSTEXPR20 void deallocate(T* p, size_t) { #if FMT_USE_CONSTEVAL if (__builtin_is_constant_evaluated()) { - std::allocator().deallocate(p, n); + delete[] p; return; } #endif - ignore_unused(n); free(p); } @@ -978,9 +974,10 @@ class basic_memory_buffer : public detail::buffer { T* new_data = self.alloc_.allocate(new_capacity); // The following code doesn't throw, so the raw pointer above doesn't leak. if (detail::is_constant_evaluated()) { -#if FMT_USE_CONSTEVAL - for (size_t i = 0; i < new_capacity; ++i) std::construct_at(new_data + i); -#endif + auto alloc = detail::allocator(); + for (size_t i = 0; i < new_capacity; ++i) + std::allocator_traits>::construct(alloc, + new_data + i); for (size_t i = 0; i < buf.size(); ++i) new_data[i] = old_data[i]; } else { // Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481). diff --git a/test/format-test.cc b/test/format-test.cc index 9a65c94c..da5562aa 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1272,10 +1272,6 @@ TEST(format_test, high_precision_trailing_zeros) { EXPECT_EQ(std::string("0.5") + std::string(767, '0'), fmt::format("{:#.768g}", 0.5)); - EXPECT_EQ(std::string("1.") + std::string(766, '0'), - fmt::format("{:.766f}", 1.0)); - EXPECT_EQ(std::string("0.5") + std::string(766, '0'), - fmt::format("{:#.767g}", 0.5)); EXPECT_EQ(std::string("1.") + std::string(767, '0'), fmt::format("{:#.768g}", 1.0)); EXPECT_EQ("0.5", fmt::format("{:.768g}", 0.5)); @@ -1284,10 +1280,6 @@ TEST(format_test, high_precision_trailing_zeros) { auto general = std::string("0.0625") + std::string(765, '0'); EXPECT_EQ(fixed, fmt::format("{:.768f}", 0.0625)); EXPECT_EQ(general, fmt::format("{:#.768g}", 0.0625)); - EXPECT_EQ(std::string("-0.5") + std::string(767, '0'), - fmt::format("{:.{}f}", -0.5f, 768)); - EXPECT_EQ(std::string("-0.0625") + std::string(765, '0'), - fmt::format("{:#.{}g}", -0.0625, 768)); EXPECT_EQ(std::string(" ") + fixed, fmt::format("{:>772.768f}", 0.0625)); EXPECT_EQ(std::string(" ") + general, fmt::format("{:>#772.768g}", 0.0625)); } @@ -1315,18 +1307,12 @@ TEST(format_test, high_precision_long_double) { char buffer[3004]; safe_sprintf(buffer, "%.1000Lf", tiny); EXPECT_EQ(buffer, fmt::format("{:.1000f}", tiny)); - safe_sprintf(buffer, "%.1000Lf", -tiny); - EXPECT_EQ(buffer, fmt::format("{:.1000f}", -tiny)); safe_sprintf(buffer, "%.3000Lf", tiny); EXPECT_EQ(buffer, fmt::format("{:.3000f}", tiny)); safe_sprintf(buffer, "%#.1000Lg", large); EXPECT_EQ(buffer, fmt::format("{:#.1000g}", large)); safe_sprintf(buffer, "%.0Lf", large); EXPECT_EQ(buffer, fmt::format("{:.0f}", large)); - EXPECT_EQ("0." + std::string(1000, '0'), fmt::format("{:.1000f}", 0.0L)); - EXPECT_EQ("-0." + std::string(1000, '0'), fmt::format("{:.1000f}", -0.0L)); - EXPECT_EQ("0.5" + std::string(999, '0'), fmt::format("{:.1000f}", 0.5L)); - EXPECT_EQ("-0.5" + std::string(999, '0'), fmt::format("{:.1000f}", -0.5L)); } TEST(format_test, large_precision) {