8043 Commits

Author SHA1 Message Date
Mayank Jaiswal
89a7f4a7ca
Fix FMT_COMPILE with ranges, tuples and maps (#4974)
nested_format_specs::write formatted the body of a padded value into a
temporary buffer using a context of the same type as the outer one. This
only works when the outer context writes to an appender, so FMT_COMPILE
and format_to with other output iterators failed to compile even when no
width was given.

Use a buffer context that takes arguments and locale from the outer
context when the outer context doesn't write to an appender.

Fixes #4949.
2026-10-18 07:11:07 -07:00
Victor Zverovich
4ded41f186 Simplify pre-epoch local_time formatting
Floor the seconds before calling gmtime instead of adjusting tm_sec, and
keep the subsecond remainder in the common duration type, which fixes
overflow for narrow reps such as duration<int16_t, std::micro>.
2026-10-18 07:02:27 -07:00
Kartikey Negi
6ba294f5a6
Fix subsecond formatting for pre-epoch local_time (#4975) (#4976) 2026-10-18 06:45:15 -07:00
Victor Zverovich
18164eaf8b Simplify printf flag tests
The sign is cleared for unsigned conversions regardless of whether the
'+' or the space flag was given, so "% o" and "% X" only repeat what
"%+o" and "%+X" already cover.
2026-10-17 07:16:33 -07:00
fhgffy
01bef95d34
Ignore '+' and space flags for unsigned printf conversions (#4977)
C only applies the '+' and space flags to signed conversions, so
fmt::sprintf("%+u", 42) should give "42" like printf does, not "+42".
The same goes for %o, %x and %X.
2026-10-17 07:11:43 -07:00
Victor Zverovich
8efd79f3f0 Simplify hexfloat formatting
For numeric alignment write the 0x prefix directly to the output and
subtract it from the width instead of tracking the prefix length
separately. This makes the extra write_padded call and the intermediate
buffer copy unnecessary, restoring write_bytes.
2026-10-17 06:42:21 -07:00
Victor Zverovich
fdf31252e6 Cache packages in Linux CI
Compilers are installed from third-party archives that periodically
return 50x or throttle to a crawl, which fails the build. Keep the
downloaded packages and restore them on the next run so that both apt
and the legacy wget-based installs work from disk instead of refetching.

apt, unlike apt-get, discards downloaded packages after installing them
unless the binary-specific Keep-Downloaded-Packages is set.

The cache is written once per key; bump the -v1 suffix to refresh it
after the package versions change.
2026-10-16 16:02:06 -07:00
Victor Zverovich
7a3b442edc Simplify sanitizer flags in Linux CI workflow
Inline the SANITIZER_FLAGS expression into CXXFLAGS and drop CFLAGS.
c-test is the only C target and CMake links it with the C++ driver because
it depends on fmt-c, so the sanitizer runtime is still linked in.
2026-10-16 12:44:14 -07:00
Victor Zverovich
615acd84dd Fix use-after-free in basic_memory_buffer move assignment
operator= deallocates the destination's storage but leaves it pointing at
the freed block with a stale capacity and size. When the allocator doesn't
propagate and the two allocators are unequal, move_alloc copies into that
pointer rather than taking over the source's storage, so it writes to freed
memory and the destructor then frees the same block again.

Restore the inline buffer after deallocating and before calling move().
2026-10-16 12:44:14 -07:00
Ivan Lazarić
b4ffa39b99
Block optimize pragma on EDG (#4980)
EDG over GCC likes to pretend to be GCC in a lot of macros,
but not all. It does not define `__OPTIMIZE__` ever.
So we would erroneously emit pragma optimize `Og`
even in optimized builds.
2026-10-11 15:29:11 -07:00
Vladislav Shchapov
35c58f084e
Fix hexfloat zero padding: zero padding must be placed after the sign and "0x" prefix (#4972)
Signed-off-by: Vladislav Shchapov <vladislav@shchapov.ru>
2026-10-08 13:06:28 -07:00
Victor Zverovich
62295c1ce2 Simplify compiled variant and expected tests
Drop the assertions that return from write_escaped_alternative before
reaching the advance_to call they were added to cover: the std::string
and char alternatives take the has_to_string_view and is_same_v<T, Char>
early returns, and expected<void, int> never calls the function at all.
All four are already checked in std-test.cc.

Merge format_unexpected into format_expected since both are guarded by
__cpp_lib_expected and the latter was a single assertion, and note that
std::unexpected has a formatter of its own so the adjacent unexpected(42)
checks are not duplicates.
2026-10-08 12:00:06 -07:00
Mishmish Dev
4faf707610
Enable ASan and UBSan in supported Linux CI builds (#4969)
* Fix null allocator reference in non-propagating move test

* Test ostream chunking with a real buffer

* Initialize the file pointer when constructing a buffer writer

* Enable ASan and UBSan in supported Linux CI builds

* Limit sanitizer CI to recent Clang and GCC configurations
2026-10-08 11:42:47 -07:00
Victor Zverovich
7338754774 Simplify high-precision float formatting and tests
Unify the duplicated trailing-zero computation in write_fixed and remove
the redundant guards around fill_n. Reduce the constexpr branch of
basic_memory_buffer::grow to a single construct loop that uses the
buffer's own allocator.

In tests, drop the MSVC version checks that FMT_USE_CONSTEVAL already
implies, replace a loop computing 2^-900 with the 0x1p-900 literal, and
report high_precision_long_double as skipped rather than passed when
long double is not an extended-precision type.
2026-10-08 11:27:22 -07:00
fhgffy
10cda465ed
Fix output position for compiled variant and expected formatting (#4968) 2026-10-07 12:32:48 -07:00
Langning Zhang
c4927e6086
Fix high-precision floating-point formatting (#4960)
* Fix trailing zeros in high-precision floating-point formatting

* fix: preserve high-precision float digits and constexpr growth

* Simplify constexpr allocation and precision tests
2026-10-07 07:16:10 -07:00
Victor Zverovich
4afd0e498e Simplify fill_n for appenders
Hoist the loop-invariant is_constant_evaluated check into a guard, matching
the fill_n overload for pointers. This lets the runtime path return out
directly instead of relying on the scalar fallback being a no-op once n
reaches 0, and leaves the fallback call only in the branch that needs it.

Also cache buf.size() per iteration as buffer::append does, so the fill
pointer is computed after try_resize rather than depending on it not
reallocating.
2026-10-04 08:50:27 -07:00
Victor Zverovich
3e0ecb247b Remove redundant escape tests
The U+1FAE0 and U+31350 cases added in #4962 duplicate the is_printable
checks for the same code points. For a code point >= 0x80 needs_escape is
exactly !is_printable(cp), and the existing U+1F984 case already covers a
printable 4-byte sequence passing through unmodified.
2026-10-04 08:30:56 -07:00
FenjuFu
85a8f9117d
Update is_printable to Unicode 17.0 (#4962)
Signed-off-by: FenjuFu <fufenjupku@gmail.com>
2026-10-04 07:59:04 -07:00
Victor Zverovich
174569c130 ci: Replace the deprecated macos-14 runner with macos-15
GitHub is retiring the macOS 14 runner image on November 2nd, 2026, with
brownouts starting October 5th. Switch to macos-15, which is also arm64,
and pin it explicitly to match how the other workflows pin their images.

Also drop the Xcode 14.3 selection step: it was gated on macos-13, which
is no longer in the matrix and has already been retired.
2026-10-04 06:49:22 -07:00
James Panayis
9197f51593
Optimize buffered padding with chunked fills (#4959)
Fill available appender storage in bulk, continuing across buffer growth and flushes
Preserve the constexpr-compatible scalar fallback
Add testing of large padded sizes
2026-10-02 11:44:42 -07:00
dependabot[bot]
ea0660a1d0
Bump urllib3 in /support in the pip group across 1 directory (#4967)
Bumps the pip group with 1 update in the /support directory: [urllib3](https://github.com/urllib3/urllib3).


Updates `urllib3` from 2.7.0 to 2.8.0
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-version: 2.8.0
  dependency-type: indirect
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-01 15:31:33 -07:00
dependabot[bot]
cdc27f91a0
Bump github/codeql-action/init from 4.36.1 to 4.38.2 (#4966)
Bumps [github/codeql-action/init](https://github.com/github/codeql-action) from 4.36.1 to 4.38.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](87557b9c84...2892aa5e19)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.38.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-01 08:47:57 -07:00
dependabot[bot]
a03dc3c6eb
Bump github/codeql-action/analyze from 4.36.1 to 4.38.2 (#4965)
Bumps [github/codeql-action/analyze](https://github.com/github/codeql-action) from 4.36.1 to 4.38.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](87557b9c84...2892aa5e19)

---
updated-dependencies:
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.38.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-01 08:47:42 -07:00
Victor Zverovich
5da4e9a3fb Run format tests without locale support
Build format-test.cc with FMT_USE_LOCALE=0 in nolocale-test instead of a
separate test file. This replaces two ad-hoc checks with the whole format
test suite. The locale-dependent tests were guarded by the removed
FMT_STATIC_THOUSANDS_SEPARATOR macro, so the guard never took effect.
2026-09-27 10:15:42 -07:00
Ivan Lazarić
225bf7f287
Avoid false positive from -Wmaybe-uninitialized in named_arg_store constructor (#4952)
Since GCC 16, in Debug (meaning `-O0`) builds,
`-Wmaybe-uninitialized` falsely warns in certain situations where
you convert a pointer to a not-yet-initialized variable to pointer-to-const.

Associated bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127470
2026-09-27 08:34:06 -07:00
Tiago
1ffdc7687f
Use classic locale grouping without locale support (#4947) 2026-09-27 08:19:52 -07:00
Victor Zverovich
0482001875 Format enums annotated with fmt::as_underlying
Format an enum as its underlying value if the enum is annotated with
fmt::as_underlying, the equivalent of std::format_as_underlying from P4267:

  enum class [[=fmt::as_underlying]] color { red = 1, green = 2, blue = 4 };
  fmt::format("{:04x}", color::blue);  // "0004"

The value is mapped before type erasure via the existing
formatter<T>::format_as hook, as in the std::byte formatter, so it is stored
as a builtin argument and can be used as dynamic width or precision.
Combining the annotation with fmt::as_identifiers is rejected with a
static_assert.
2026-09-26 11:07:11 -07:00
Ivan Lazarić
522e2c12ab
Remove fmt::path (#4953)
The class was a temporary experiment,
and is just emitting warnings now.
2026-09-25 06:56:18 -07:00
Victor Zverovich
6d71f74624 Remove redundant printf tests
%.0i and %.0u take the same path as %.0d because 'i' and 'u' are normalized
to 'd', the uppercase variants only set the upper flag which is unobservable
when there are no digits, and %-5.0d cannot be distinguished from %5.0d
because the output is empty.
2026-09-20 17:30:26 -07:00
Victor Zverovich
1d361e2f8c Simplify printf handling of a zero value with a zero precision
Reuse getsign instead of mapping the sign to a string and let write_bytes'
default_align handle align::none. Also drop the presentation type check:
printf only produces dec, oct and hex for a non-char integral argument
because 'c' converts the argument to the char type.
2026-09-20 17:30:11 -07:00
Victor Zverovich
79e48ba915 Move has_format_as to format.h and use it in the tuple formatter
The tuple formatter had a bespoke trait to keep format_as from producing an
ambiguous specialization. detail::has_format_as already answers that question
and std.h applies it the same way, so move it from std.h to format.h where
ranges.h can see it and drop the extra trait.

Check it with conditional_t rather than &&: is_tuple_formattable must not be
instantiated for types with format_as because for self-referential tuple-like
types that recurses back into formatter selection, and && short-circuits
evaluation but not instantiation.
2026-09-20 10:22:10 -07:00
Sachit Madaan
cfb57bfa3a
Fix printf conversion of a zero value with a precision of zero (#4942) 2026-09-19 07:49:15 -07:00
Wu Shuwen
fd0a9b6620
Fix format_as for tuple-like types with ranges.h (#4945) 2026-09-18 15:16:28 -07:00
Victor Zverovich
c4fb197284 Add a missing newline 2026-09-18 14:00:54 -07:00
Yongqiang Tian
c79d5d2141
Limit Clang diagnostic suppressions to fmt declarations (#4948)
format.h and std.h suppress Clang warnings for declarations provided by
fmt, but do not restore the previous diagnostic state. Including either
header therefore also hides the corresponding warning in unrelated
consumer code.

Use fmt's existing Clang diagnostic push and pop macros to limit
-Wweak-vtables to format_error and -Wbit-int-extension to the two
_BitInt aliases.

Signed-off-by: Yongqiang Tian <yqtian668@gmail.com>
2026-09-18 12:37:44 -07:00
Victor Zverovich
b9a6f9be76 Replace the locale #if in chrono.h with a shim template
Both specializations are always parsed while only the selected one is
instantiated. The #else branch it replaces is compiled by no target:
nolocale-test builds src/format.cc, which never reaches chrono.h.
2026-09-18 12:24:28 -07:00
Nebojša Cvetković
e4751cc709
Don't require std::locale in chrono.h when FMT_USE_LOCALE is 0 (#4921)
tm_writer takes a locale_ref and the localized flag instead of a std::locale
reference, and resolves the locale the same way numeric {:L} does: classic
unless localized, otherwise the one passed to the formatting function or the
global one. The facet calls are confined to three shims, so with locale
support disabled nothing pulls in std::locale. get_locale, which existed only
to materialize and own a std::locale, is no longer needed.

The std::tm formatter treated a missing locale argument as the classic locale
rather than the global one, and since #4935 routes {:L} on weekday and month
through it, {:L} without a locale argument ignored the global locale for all
calendar types. It now uses the global locale, as numeric {:L} does. Output
with an explicit locale is unchanged. With FMT_USE_LOCALE=0, {:L} no longer
consults the global locale, matching numeric formatting under that option. An
-Os test program loses all 16 of its std::locale and time_put symbols.
2026-09-16 08:37:57 -07:00
Aurora
5fc5c910c0
Fix unreachable code warning in range formatter (#4932) 2026-09-15 09:39:58 -07:00
Tiago
3a0661d7c0
Don't construct a locale when formatting year_month_day (#4940)
formatter<year_month_day>::format passes true to get_locale, so every default
format constructs a std::locale, and tm_writer then compares it against the
classic locale (is_classic_(loc_ == get_classic_locale())). The only thing
written is on_iso_date(), which is pure arithmetic and reads neither loc_ nor
is_classic_.

It is the odd one out among its siblings: formatter<day> and formatter<year>
pass false; formatter<weekday> and formatter<month> pass their localized()
flag. Only year_month_day hardcodes true, and its parse() never sets localized
in the first place.

With FMT_USE_LOCALE=0 this costs more than a copy: the loc.get<std::locale>()
arm of get_locale is compiled out, so it default-constructs instead, capturing
the current global locale in a build that asked for no locale support.

No output change: chrono_test.year_month_day already sets a non-classic global
locale and expects "2024-01-01".

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-13 08:30:16 -07:00
Tiago
e91e92761a
Don't let ADL pick to_string_view (#4938)
* Don't let ADL pick to_string_view

02bf4d1c disabled ADL for to_string_view by qualifying the is_string trait,
and has_to_string_view and char_t are qualified for the same reason. Two call
sites were left behind: value's string constructor and the write() overload
for types with a string view conversion. Both sit inside fmt::detail, where an
unqualified call adds the argument's own namespace to the overload set.

That splits the two halves of one decision. Both call sites are reached only
through has_to_string_view or char_t, which are defined by the qualified
expression, so ADL can never be needed to satisfy them - it can only add
candidates the gate never considered. When the argument's namespace declares a
to_string_view template, the two tie during partial ordering and the call is
ambiguous:

  core.h(2211): error C2668: 'to_string_view': ambiguous call to overloaded
  function
  note: could be 'string_view N::to_string_view<T>(const T&)' [found using
  argument-dependent lookup]
  note: or 'basic_string_view<char> fmt::detail::to_string_view<T,0>(const T&)'

Both are reachable. format("{}", x) stores the argument through value's
constructor; to_string(x) passes it to detail::write unmapped, which lands on
the write() overload, as do FMT_COMPILE named fields and
nested_formatter::write_arg. Reverting either line alone breaks the build of
the test that covers it.

This turned up in Microsoft Office, which declares a constrained
to_string_view template next to its own string types. It only breaks where
those types are distinct classes, so the same code compiles on platforms whose
string types are std aliases - the ADL set is namespace std there and picks up
nothing.

One behaviour change worth noting: a non-template to_string_view in the
argument's namespace used to win outright at these call sites, so a type that
satisfies is_std_string_like via find_first_of and data() but has no size()
formatted through ADL and now fails to compile, because the trait only checks
that the qualified overload is viable, not that its body instantiates. That is
the removed extension point going away rather than a new restriction; ADL
to_string_view stopped being supported in 02bf4d1c.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-12 07:14:49 -07:00
Tiago
e5d13d826f
Make nolocale-test actually disable locale (#4939)
nolocale-test defines FMT_STATIC_THOUSANDS_SEPARATOR, which stopped doing
anything in b90b4bc9 ("Remove FMT_STATIC_THOUSANDS_SEPARATOR in favor of
FMT_USE_LOCALE"). That macro no longer appears anywhere under include/, so
since then the target has compiled src/format.cc with locale support enabled.

It is not a dead target: the pedantic CI jobs build it (linux.yml, macos.yml
both pass -DFMT_PEDANTIC=ON), and it passes. So the configuration looks
covered while nothing actually tests it. #4627 - a locale-off build break -
landed during that window.

Define FMT_USE_LOCALE=0 instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-11 12:39:06 -07:00
Victor Zverovich
14174c826d Add braces for readability 2026-09-11 08:49:10 -07:00
cui fliter
6aa4a5f6f8
Fix debug string formatting for range formatters (#4936)
Signed-off-by: cuishuang <imcusg@gmail.com>
2026-09-11 08:43:46 -07:00
Victor Zverovich
1da57c78d4 Simplify calendar_padding test 2026-09-11 08:31:42 -07:00
IfkumRfnl
2012961e3e
Fix width and alignment for calendar types (#4935) 2026-09-11 08:22:02 -07:00
Victor Zverovich
56fcd0b945 Simplify named_arg_count test 2026-09-11 08:05:34 -07:00
IfkumRfnl
854fc9567a
Fix argument count in dynamic stores with named arguments (#4933) 2026-09-11 08:01:06 -07:00
ilike314272
8dc5d3f69f
Feature: dark mode docs (#4914) 2026-09-09 14:41:50 -07:00
Wu Shuwen
d566765638
Read Doxygen XML independently of the system text encoding (#4925) 2026-09-08 20:45:25 -07:00