[libcxx-commits] [libcxx] [libc++] Avoid heap allocation for default-precision double formatting (PR #212502)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Jul 28 07:11:15 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Adib Pathan (adxb-pxthxn)

<details>
<summary>Changes</summary>

Fixes #<!-- -->211909.

## Summary

When formatting floating-point values with unspecified precision (`{}`), libc++ initializes `__float_buffer` precision to `_Traits::__max_fractional`. For `double`, that inflates the computed buffer size beyond the stack buffer threshold and causes an unnecessary heap allocation on the default path.

This patch uses the Standard's default precision (`6`) when no precision is specified, so the common `double` formatting path stays within the stack buffer.

Discussion on #<!-- -->211909 noted that simply increasing `__stack_buffer_size` is not ideal. @<!-- -->philnik777 suggested keeping the common case stack-backed rather than pessimistically reserving worst-case space (format into the stack buffer first, and only allocate if needed). This change follows that direction for the default-precision case by avoiding worst-case precision sizing up front.

## Test plan

- [x] Added regression in `libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp`
- [x] Test verifies `std::format("{}", 1.23)` does not allocate (via `count_new.h`)
- [x] `ninja -C build runtimes-test-depends`
- [x] `build/bin/llvm-lit -sv build/runtimes/runtimes-bins/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp`

---
Full diff: https://github.com/llvm/llvm-project/pull/212502.diff


2 Files Affected:

- (modified) libcxx/include/__format/formatter_floating_point.h (+1-1) 
- (modified) libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp (+10) 


``````````diff
diff --git a/libcxx/include/__format/formatter_floating_point.h b/libcxx/include/__format/formatter_floating_point.h
index f4de8b927651a..8728f996e78f9 100644
--- a/libcxx/include/__format/formatter_floating_point.h
+++ b/libcxx/include/__format/formatter_floating_point.h
@@ -154,7 +154,7 @@ class __float_buffer {
   // may be too much for some platforms. For these cases a better estimate is
   // required.
   explicit _LIBCPP_HIDE_FROM_ABI __float_buffer(int __precision)
-      : __precision_(__precision != -1 ? __precision : _Traits::__max_fractional) {
+      : __precision_(__precision != -1 ? __precision : 6) {
     // When the precision is larger than _Traits::__max_fractional the digits in
     // the range (_Traits::__max_fractional, precision] will contain the value
     // zero. There's no need to request to_chars to write these zeros:
diff --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp
index 3ad84577b90d2..fb410591ab7c5 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp
@@ -42,6 +42,7 @@
 #include "test_format_context.h"
 #include "test_macros.h"
 #include "make_string.h"
+#include "count_new.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
 
@@ -562,11 +563,20 @@ void test_all_float_types() {
   test_float_type<long double, CharT>();
 }
 
+void test_default_precision_double_does_not_allocate() {
+  globalMemCounter.reset();
+  DisableAllocationGuard g;
+  std::string result = std::format("{}", 1.23);
+  g.release();
+  assert(result == "1.23");
+}
+
 int main(int, char**) {
   test_all_float_types<char>();
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
   test_all_float_types<wchar_t>();
 #endif
+  test_default_precision_double_does_not_allocate();
 
   return 0;
 }

``````````

</details>


https://github.com/llvm/llvm-project/pull/212502


More information about the libcxx-commits mailing list