Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Format string checking incorrectly assumes repeated evaluation of string literal will produce the same pointer #4177

Closed
zygoloid opened this issue Sep 27, 2024 · 11 comments

Comments

@zygoloid
Copy link

zygoloid commented Sep 27, 2024

In the fstring constructor from a type that is convertible to string view, the s argument is passed to two different functions, which both internally convert it to a string_view. This s argument is frequently created by the FMT_STRING macro which has a conversion to string_view that evaluates a string literal expression.

Each evaluation of a string literal expression can produce a different pointer. Therefore it is not correct to assume that the two conversions of s to a string_view produce related string_views, but the code does assume this. Historically, compilers have let you get away with this in compile-time evaluation, but clang recently gained a more strict implementation of this rule and now rejects.

I think the fix is probably to do the same thing in this constructor that is done a few lines below in the next constructor:

   template <typename S,
             FMT_ENABLE_IF(std::is_convertible<const S&, string_view>::value)>
   FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const S& s) : str(s) {
     if (FMT_USE_CONSTEVAL)
+      FMT_CONSTEXPR auto sv = string_view(S());
-      detail::parse_format_string<char>(s, checker(s, arg_pack()));
+      detail::parse_format_string<char>(sv, checker(sv, arg_pack()));
 #ifdef FMT_ENFORCE_COMPILE_STRING
     static_assert(
         FMT_USE_CONSTEVAL && sizeof(s) != 0,
         "FMT_ENFORCE_COMPILE_STRING requires format strings to use FMT_STRING");
 #endif
   }
   template <typename S,
             FMT_ENABLE_IF(std::is_base_of<detail::compile_string, S>::value&&
                               std::is_same<typename S::char_type, char>::value)>
   FMT_ALWAYS_INLINE fstring(const S&) : str(S()) {
     FMT_CONSTEXPR auto sv = string_view(S());
     FMT_CONSTEXPR int ignore =
         (parse_format_string(sv, checker(sv, arg_pack())), 0);
     detail::ignore_unused(ignore);
   }
@vitaut
Copy link
Contributor

vitaut commented Sep 28, 2024

Applied the patch (with a small tweak) in cacc310. Thanks!

@vitaut vitaut closed this as completed Sep 28, 2024
@phprus
Copy link
Contributor

phprus commented Sep 28, 2024

@vitaut
Why

FMT_CONSTEXPR auto sv = string_view(S());

?

Instead of

FMT_CONSTEXPR auto sv = string_view(s);

?

S() vs s variable.

@vitaut
Copy link
Contributor

vitaut commented Sep 28, 2024

I don't think it matters much but since the object is already available, I don't see why we need to construct another one.

@vitaut
Copy link
Contributor

vitaut commented Sep 28, 2024

Adding a regression test: 1c5883b.

@vitaut
Copy link
Contributor

vitaut commented Sep 28, 2024

I don't think it matters much but since the object is already available, I don't see why we need to construct another one.

Nevermind, I misinterpreted which is the current version of the code. You are right, we could use s there.

@zeroomega
Copy link
Contributor

@zygoloid

I did some local test by rolling our fmtlib to ToT and building our project with ToT clang but still getting errors:

FAILED: host_x64/obj/third_party/fmtlib/src/src/fmtlib.format.cc.o                                                                                                                                                
../../../clang/clang_fmt/bin/clang++ -MD -MF host_x64/obj/third_party/fmtlib/src/src/fmtlib.format.cc.o.d -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES -I../.. -Ihost_x64/gen -I.
./../third_party/fmtlib/src/include -fcolor-diagnostics -fcrash-diagnostics-dir=clang-crashreports -fcrash-diagnostics=all -gen-reproducer=error -ffp-contract=off --sysroot=../../prebuilt/third_party/sysroot/li
nux --target=x86_64-unknown-linux-gnu -ffile-compilation-dir=. -no-canonical-prefixes -fomit-frame-pointer -fdata-sections -ffunction-sections -O0 -Xclang -debug-info-kind=constructor -g3 -grecord-gcc-switches 
-gdwarf-5 -gz=zstd -Wall -Wextra -Wconversion -Wextra-semi -Wimplicit-fallthrough -Wnewline-eof -Wstrict-prototypes -Wwrite-strings -Wno-sign-conversion -Wno-unused-parameter -Wnonportable-system-include-path -
Wno-missing-field-initializers -Wno-extra-qualification -Wno-cast-function-type-strict -Wno-cast-function-type-mismatch -Wno-unknown-warning-option -Wno-missing-template-arg-list-after-template-kw -Wno-deprecat
ed-pragma -fvisibility=hidden -Werror -Wa,--fatal-warnings -Wno-error=deprecated-declarations --sysroot=../../prebuilt/third_party/sysroot/linux --target=x86_64-unknown-linux-gnu -fPIE -fvisibility-inlines-hidd
en -stdlib=libc++ -stdlib=libc++ -std=c++20 -Wno-deprecated-this-capture -fno-exceptions -fno-rtti -ftemplate-backtrace-limit=0 -stdlib=libc++ -c ../../third_party/fmtlib/src/src/format.cc -o host_x64/obj/third
_party/fmtlib/src/src/fmtlib.format.cc.o                                                                                                                                                                          
In file included from ../../third_party/fmtlib/src/src/format.cc:8:                                                                                                                                               
In file included from ../../third_party/fmtlib/src/include/fmt/format-inl.h:23:                                                                                                                                   
../../third_party/fmtlib/src/include/fmt/format.h:2677:4: error: extra ';' after member function definition [-Werror,-Wextra-semi]                                                                                
 2677 |   };                                                                                                                                                                                                      
      |    ^                                                                                                                                                                                                      
1 error generated.                                                                                                                                                                                                  

and

[49936/153879](31) CXX host_x64/obj/third_party/android/platform/system/tools/aidl/aidl_gen.aidl_to_cpp_common.cpp.o
FAILED: host_x64/obj/third_party/android/platform/system/tools/aidl/aidl_gen.aidl_to_cpp_common.cpp.o 
../../../clang/clang_fmt/bin/clang++ -MD -MF host_x64/obj/third_party/android/platform/system/tools/aidl/aidl_gen.aidl_to_cpp_common.cpp.o.d -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES -I../../third_party/android/platform/system/tools/aidl -I../../src/lib/android/aidl/generated-files -I../../third_party/googletest/src/googletest/include -I../../third_party/googletest/src/googletest -I../.. -Ihost_x64/gen -I../../third_party/android/platform/system/libbase/include -I../../third_party/fmtlib/src/include -I../../third_party/android/platform/system/logging/liblog/include -I../../zircon/system/ulib/zx-panic-libc/include -I../../zircon/system/public -fcolor-diagnostics -fcrash-diagnostics-dir=clang-crashreports -fcrash-diagnostics=all -gen-reproducer=error -ffp-contract=off --sysroot=../../prebuilt/third_party/sysroot/linux --target=x86_64-unknown-linux-gnu -ffile-compilation-dir=. -no-canonical-prefixes -fomit-frame-pointer -fdata-sections -ffunction-sections -O0 -Xclang -debug-info-kind=constructor -g3 -grecord-gcc-switches -gdwarf-5 -gz=zstd -Wall -Wextra -Wconversion -Wextra-semi -Wimplicit-fallthrough -Wnewline-eof -Wstrict-prototypes -Wwrite-strings -Wno-sign-conversion -Wno-unused-parameter -Wnonportable-system-include-path -Wno-missing-field-initializers -Wno-extra-qualification -Wno-cast-function-type-strict -Wno-cast-function-type-mismatch -Wno-unknown-warning-option -Wno-missing-template-arg-list-after-template-kw -Wno-deprecated-pragma -fvisibility=hidden -Werror -Wa,--fatal-warnings -Wno-error=deprecated-declarations --sysroot=../../prebuilt/third_party/sysroot/linux --target=x86_64-unknown-linux-gnu -fPIE -fvisibility-inlines-hidden -stdlib=libc++ -stdlib=libc++ -std=c++20 -Wno-deprecated-this-capture -fno-exceptions -fno-rtti -ftemplate-backtrace-limit=0 -stdlib=libc++ -Wno-c++98-compat-extra-semi -Wno-c99-designator -Wno-deprecated-declarations -Wno-extra-semi -Wno-implicit-int-conversion -Wno-inconsistent-missing-override -Wno-newline-eof -Wno-range-loop-construct -Wno-reorder-init-list -Wno-shorten-64-to-32 -Wno-sign-compare -Wno-string-conversion -Wno-unused-but-set-variable -Wno-unused-result -Wno-unknown-warning-option -Wno-vla-cxx-extension -Wno-c++98-compat-extra-semi -Wno-c99-designator -Wno-deprecated-declarations -Wno-extra-semi -Wno-implicit-int-conversion -Wno-inconsistent-missing-override -Wno-newline-eof -Wno-range-loop-construct -Wno-reorder-init-list -Wno-shorten-64-to-32 -Wno-sign-compare -Wno-string-conversion -Wno-unused-but-set-variable -Wno-unused-result -c ../../third_party/android/platform/system/tools/aidl/aidl_to_cpp_common.cpp -o host_x64/obj/third_party/android/platform/system/tools/aidl/aidl_gen.aidl_to_cpp_common.cpp.o
In file included from ../../third_party/android/platform/system/tools/aidl/aidl_to_cpp_common.cpp:16:
In file included from ../../third_party/android/platform/system/tools/aidl/aidl_to_cpp_common.h:23:
In file included from ../../third_party/android/platform/system/tools/aidl/aidl_language.h:26:
In file included from ../../third_party/android/platform/system/libbase/include/android-base/result.h:104:
In file included from ../../third_party/android/platform/system/libbase/include/android-base/format.h:23:
In file included from ../../third_party/fmtlib/src/include/fmt/chrono.h:23:
In file included from ../../third_party/fmtlib/src/include/fmt/format.h:41:
../../third_party/fmtlib/src/include/fmt/base.h:2670:24: error: constexpr variable 'sv' must be initialized by a constant expression
 2670 |     FMT_CONSTEXPR auto sv = string_view(S());
      |                        ^    ~~~~~~~~~~~~~~~~
../../third_party/android/platform/system/tools/aidl/aidl_to_cpp_common.cpp:374:24: note: in instantiation of function template specialization 'fmt::fstring<fmt::detail::named_arg<char, std::string>, fmt::detail::named_arg<char, std::string>, fmt::detail::named_arg<char, std::string>>::fstring<const char *, 0>' requested here
  374 |     out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("min_tag", min_tag),
      |                        ^
../../third_party/fmtlib/src/include/fmt/base.h:524:32: note: read of dereferenced null pointer is not allowed in a constant expression
  524 |       size_ = __builtin_strlen(detail::narrow(s));
      |                                ^
../../third_party/fmtlib/src/include/fmt/base.h:2670:29: note: in call to 'basic_string_view(nullptr)'
 2670 |     FMT_CONSTEXPR auto sv = string_view(S());
      |                             ^~~~~~~~~~~~~~~~
../../third_party/android/platform/system/tools/aidl/aidl_to_cpp_common.cpp:374:24: error: call to consteval function 'fmt::fstring<fmt::detail::named_arg<char, std::string>, fmt::detail::named_arg<char, std::string>, fmt::detail::named_arg<char, std::string>>::fstring<const char *, 0>' is not a constant expression
  374 |     out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("min_tag", min_tag),
      |                        ^
../../third_party/fmtlib/src/include/fmt/base.h:524:32: note: read of dereferenced null pointer is not allowed in a constant expression
  524 |       size_ = __builtin_strlen(detail::narrow(s));
      |                                ^
../../third_party/fmtlib/src/include/fmt/base.h:2670:29: note: in call to 'basic_string_view(nullptr)'
 2670 |     FMT_CONSTEXPR auto sv = string_view(S());
      |                             ^~~~~~~~~~~~~~~~
../../third_party/android/platform/system/tools/aidl/aidl_to_cpp_common.cpp:374:24: note: in call to 'fstring<const char *, 0>(tmpl)'
  374 |     out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("min_tag", min_tag),
      |                        ^~~~
In file included from ../../third_party/android/platform/system/tools/aidl/aidl_to_cpp_common.cpp:16:
In file included from ../../third_party/android/platform/system/tools/aidl/aidl_to_cpp_common.h:23:
In file included from ../../third_party/android/platform/system/tools/aidl/aidl_language.h:26:
In file included from ../../third_party/android/platform/system/libbase/include/android-base/result.h:104:
In file included from ../../third_party/android/platform/system/libbase/include/android-base/format.h:23:
In file included from ../../third_party/fmtlib/src/include/fmt/chrono.h:23:
In file included from ../../third_party/fmtlib/src/include/fmt/format.h:41:
../../third_party/fmtlib/src/include/fmt/base.h:2670:24: error: constexpr variable 'sv' must be initialized by a constant expression
 2670 |     FMT_CONSTEXPR auto sv = string_view(S());
      |                        ^    ~~~~~~~~~~~~~~~~
../../third_party/android/platform/system/tools/aidl/aidl_to_cpp_common.cpp:735:24: note: in instantiation of function template specialization 'fmt::fstring<fmt::detail::named_arg<char, std::string>, fmt::detail::named_arg<char, std::string>>::fstring<const char *, 0>' requested here
  735 |     out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("typelist", typelist));
      |                        ^
../../third_party/fmtlib/src/include/fmt/base.h:524:32: note: read of dereferenced null pointer is not allowed in a constant expression
  524 |       size_ = __builtin_strlen(detail::narrow(s));
      |                                ^
../../third_party/fmtlib/src/include/fmt/base.h:2670:29: note: in call to 'basic_string_view(nullptr)'
 2670 |     FMT_CONSTEXPR auto sv = string_view(S());
      |                             ^~~~~~~~~~~~~~~~
../../third_party/android/platform/system/tools/aidl/aidl_to_cpp_common.cpp:735:24: error: call to consteval function 'fmt::fstring<fmt::detail::named_arg<char, std::string>, fmt::detail::named_arg<char, std::string>>::fstring<const char *, 0>' is not a constant expression
  735 |     out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("typelist", typelist));
      |                        ^
../../third_party/fmtlib/src/include/fmt/base.h:524:32: note: read of dereferenced null pointer is not allowed in a constant expression
  524 |       size_ = __builtin_strlen(detail::narrow(s));
      |                                ^
../../third_party/fmtlib/src/include/fmt/base.h:2670:29: note: in call to 'basic_string_view(nullptr)'
 2670 |     FMT_CONSTEXPR auto sv = string_view(S());
      |                             ^~~~~~~~~~~~~~~~
../../third_party/android/platform/system/tools/aidl/aidl_to_cpp_common.cpp:735:24: note: in call to 'fstring<const char *, 0>(tmpl)'
  735 |     out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("typelist", typelist));
      |                        ^~~~
../../third_party/android/platform/system/tools/aidl/aidl_to_cpp_common.cpp:790:24: error: call to consteval function 'fmt::fstring<fmt::detail::named_arg<char, std::string>, fmt::detail::named_arg<char, std::string>, fmt::detail::named_arg<char, std::string>>::fstring<const char *, 0>' is not a constant expression
  790 |     out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("default_name", default_name),
      |                        ^
../../third_party/fmtlib/src/include/fmt/base.h:524:32: note: read of dereferenced null pointer is not allowed in a constant expression
  524 |       size_ = __builtin_strlen(detail::narrow(s));
      |                                ^
../../third_party/fmtlib/src/include/fmt/base.h:2670:29: note: in call to 'basic_string_view(nullptr)'
 2670 |     FMT_CONSTEXPR auto sv = string_view(S());
      |                             ^~~~~~~~~~~~~~~~
../../third_party/android/platform/system/tools/aidl/aidl_to_cpp_common.cpp:790:24: note: in call to 'fstring<const char *, 0>(tmpl)'
  790 |     out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("default_name", default_name),
      |                        ^~~~
5 errors generated.

@zygoloid
Copy link
Author

zygoloid commented Oct 2, 2024

I guess we should be using sv rather than S() after all.

@zeroomega
Copy link
Contributor

I guess we should be using sv rather than S() after all.

You mean FMT_CONSTEXPR auto sv = string_view(s);? It fails as well.

@zygoloid
Copy link
Author

zygoloid commented Oct 2, 2024

You would also need to remove the FMT_CONSTEXPR. If that doesn't work, you'll need to share the error messages you're seeing :)

@zeroomega
Copy link
Contributor

With diff like this:

diff --git a/include/fmt/base.h b/include/fmt/base.h
index f91f8e8..ebb8fdf 100644
--- a/include/fmt/base.h
+++ b/include/fmt/base.h
@@ -2667,7 +2667,7 @@ template <typename... T> struct fstring {
   template <typename S,
             FMT_ENABLE_IF(std::is_convertible<const S&, string_view>::value)>
   FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const S& s) : str(s) {
-    FMT_CONSTEXPR auto sv = string_view(S());
+    auto sv = string_view(s);
     if (FMT_USE_CONSTEVAL)
       detail::parse_format_string<char>(sv, checker(sv, arg_pack()));
 #ifdef FMT_ENFORCE_COMPILE_STRING
diff --git a/include/fmt/format.h b/include/fmt/format.h
index 4ad1eff..52af87b 100644
--- a/include/fmt/format.h
+++ b/include/fmt/format.h
@@ -2674,7 +2674,7 @@ class bigint {
 
   FMT_CONSTEXPR auto get_bigit(int i) const -> bigit {
     return i >= exp_ && i < num_bigits() ? bigits_[i - exp_] : 0;
-  };
+  }
 
   FMT_CONSTEXPR void subtract_bigits(int index, bigit other, bigit& borrow) {
     auto result = double_bigit(bigits_[index]) - other - borrow;

The build passed.

@zeroomega
Copy link
Contributor

Uploaded PR #4187

mtremer pushed a commit to ipfire/ipfire-2.x that referenced this issue Feb 22, 2025
- Update from version 11.0.2 to 11.1.3
- Update of rootfile
- Changelog
    11.1.3
	- Fixed compilation on GCC 9.4 (fmtlib/fmt#4313).
	- Worked around an internal compiler error when using C++20 modules with GCC
	  14.2 and earlier (fmtlib/fmt#4295).
	- Worked around a bug in GCC 6 (fmtlib/fmt#4318).
	- Fixed an issue caused by instantiating `formatter<const T>`
	  (fmtlib/fmt#4303,
	  fmtlib/fmt#4325). Thanks @timsong-cpp.
	- Fixed formatting into `std::ostreambuf_iterator` when using format string
	  compilation (fmtlib/fmt#4309,
	  fmtlib/fmt#4312). Thanks @phprus.
	- Restored a constraint on the map formatter so that it correctly reports as
	  unformattable when the element is (fmtlib/fmt#4326).
	  Thanks @timsong-cpp.
	- Reduced the size of format specs (fmtlib/fmt#4298).
	- Readded `args()` to `fmt::format_context`
	  (fmtlib/fmt#4307,
	  fmtlib/fmt#4310). Thanks @Erroneous1.
	- Fixed a bogus MSVC warning (fmtlib/fmt#4314,
	  fmtlib/fmt#4322). Thanks @ZehMatt.
	- Fixed a pedantic mode error in the CMake config
	  (fmtlib/fmt#4327). Thanks @rlalik.
    11.1.2
	- Fixed ABI compatibility with earlier 11.x versions
	  (fmtlib/fmt#4292).
	- Added `wchar_t` support to the `std::bitset` formatter
	  (fmtlib/fmt#4285,
	  fmtlib/fmt#4286,
	  fmtlib/fmt#4289,
	  fmtlib/fmt#4290). Thanks @phprus.
	- Prefixed CMake components with `fmt-` to simplify usage of {fmt} via
	  `add_subdirectory` (fmtlib/fmt#4283).
	- Updated docs for meson (fmtlib/fmt#4291).
	  Thanks @trim21.
	- Fixed a compilation error in chrono on nvcc
	  (fmtlib/fmt#4297,
	  fmtlib/fmt#4301). Thanks @breyerml.
	- Fixed various warnings
	  (fmtlib/fmt#4288,
	  fmtlib/fmt#4299). Thanks @GamesTrap and @edo9300.
    11.1.1
	- Fixed ABI compatibility with earlier 11.x versions
	  (fmtlib/fmt#4278).
	- Defined CMake components (`core` and `doc`) to allow docs to be installed
	  separately (fmtlib/fmt#4276).
	  Thanks @carlsmedstad.
    11.1.0
	- Improved C++20 module support
	  (fmtlib/fmt#4081,
	  fmtlib/fmt#4083,
	  fmtlib/fmt#4084,
	  fmtlib/fmt#4152,
	  fmtlib/fmt#4153,
	  fmtlib/fmt#4169,
	  fmtlib/fmt#4190,
	  fmtlib/fmt#4234,
	  fmtlib/fmt#4239).
	  Thanks @kamrann and @Arghnews.
	- Reduced debug (unoptimized) binary code size and the number of template
	  instantiations when passing formatting arguments. For example, unoptimized
	  binary code size for `fmt::print("{}", 42)` was reduced by ~40% on GCC and
	  ~60% on clang (x86-64).
	  GCC:
	  - Before: 161 instructions of which 105 are in reusable functions
	    ([godbolt](https://www.godbolt.org/z/s9bGoo4ze)).
	  - After: 116 instructions of which 60 are in reusable functions
	    ([godbolt](https://www.godbolt.org/z/r7GGGxMs6)).
	  Clang:
	  - Before: 310 instructions of which 251 are in reusable functions
	    ([godbolt](https://www.godbolt.org/z/Ts88b7M9o)).
	  - After: 194 instructions of which 135 are in reusable functions
	    ([godbolt](https://www.godbolt.org/z/vcrjP8ceW)).
	- Added an experimental `fmt::writer` API that can be used for writing to
	  different destinations such as files or strings
	  (fmtlib/fmt#2354).
	  For example ([godbolt](https://www.godbolt.org/z/rWoKfbP7e)):
		  ```c++
		  #include <fmt/os.h>
		  void write_text(fmt::writer w) {
		    w.print("The answer is {}.", 42);
		  }
		  int main() {
		    // Write to FILE.
		    write_text(stdout);
		    // Write to fmt::ostream.
		    auto f = fmt::output_file("myfile");
		    write_text(f);
		    // Write to std::string.
		    auto sb = fmt::string_buffer();
		    write_text(sb);
		    std::string s = sb.str();
		  }
		  ```
	- Added width and alignment support to the formatter of `std::error_code`.
	- Made `std::expected<void, E>` formattable
	  (fmtlib/fmt#4145,
	  fmtlib/fmt#4148).
	  For example ([godbolt](https://www.godbolt.org/z/hrj5c6G86)):
		  ```c++
		  fmt::print("{}", std::expected<void, int>());
		  ```
		  prints
		  ```
		  expected()
		  ```
	  Thanks @phprus.
	- Made `fmt::is_formattable<void>` SFINAE-friendly
	  (fmtlib/fmt#4147).
	- Added support for `_BitInt` formatting when using clang
	  (fmtlib/fmt#4007,
	  fmtlib/fmt#4072,
	  fmtlib/fmt#4140,
	  fmtlib/fmt#4173,
	  fmtlib/fmt#4176).
	  For example ([godbolt](https://www.godbolt.org/z/KWjbWec5z)):
		  ```c++
		  using int42 = _BitInt(42);
		  fmt::print("{}", int42(100));
		  ```
	  Thanks @Arghnews.
	- Added the `n` specifier for tuples and pairs
	  (fmtlib/fmt#4107). Thanks @someonewithpc.
	- Added support for tuple-like types to `fmt::join`
	  (fmtlib/fmt#4226,
	  fmtlib/fmt#4230). Thanks @phprus.
	- Made more types formattable at compile time
	  (fmtlib/fmt#4127). Thanks @AnthonyVH.
	- Implemented a more efficient compile-time `fmt::formatted_size`
	  (fmtlib/fmt#4102,
	  fmtlib/fmt#4103). Thanks @phprus.
	- Fixed compile-time formatting of some string types
	  (fmtlib/fmt#4065). Thanks @torshepherd.
	- Made compiled version of `fmt::format_to` work with
	  `std::back_insert_iterator<std::vector<char>>`
	  (fmtlib/fmt#4206,
	  fmtlib/fmt#4211). Thanks @phprus.
	- Added a formatter for `std::reference_wrapper`
	  (fmtlib/fmt#4163,
	  fmtlib/fmt#4164). Thanks @yfeldblum and @phprus.
	- Added experimental padding support (glibc `strftime` extension) to `%m`, `%j`
	  and `%Y` (fmtlib/fmt#4161). Thanks @KKhanhH.
	- Made microseconds formatted as `us` instead of `µs` if the Unicode support is
	  disabled (fmtlib/fmt#4088).
	- Fixed an unreleased regression in transcoding of surrogate pairs
	  (fmtlib/fmt#4094,
	  fmtlib/fmt#4095). Thanks @phprus.
	- Made `fmt::appender` satisfy `std::output_iterator` concept
	  (fmtlib/fmt#4092,
	  fmtlib/fmt#4093). Thanks @phprus.
	- Made `std::iterator_traits<fmt::appender>` standard-conforming
	  (fmtlib/fmt#4185). Thanks @CaseyCarter.
	- Made it easier to reuse `fmt::formatter<std::string_view>` for types with
	  an implicit conversion to `std::string_view`
	  (fmtlib/fmt#4036,
	  fmtlib/fmt#4055). Thanks @Arghnews.
	- Made it possible to disable `<filesystem>` use via `FMT_CPP_LIB_FILESYSTEM`
	  for compatibility with some video game console SDKs, e.g. Nintendo Switch SDK
	  (fmtlib/fmt#4257,
	  fmtlib/fmt#4258,
	  fmtlib/fmt#4259). Thanks @W4RH4WK and @phprus.
	- Fixed compatibility with platforms that use 80-bit `long double`
	  (fmtlib/fmt#4245,
	  fmtlib/fmt#4246). Thanks @jsirpoma.
	- Added support for UTF-32 code units greater than `0xFFFF` in fill
	  (fmtlib/fmt#4201).
	- Fixed handling of legacy encodings on Windows with GCC
	  (fmtlib/fmt#4162).
	- Made `fmt::to_string` take `fmt::basic_memory_buffer` by const reference
	  (fmtlib/fmt#4261,
	  fmtlib/fmt#4262). Thanks @sascha-devel.
	- Added `fmt::dynamic_format_arg_store::size`
	  (fmtlib/fmt#4270). Thanks @hannes-harnisch.
	- Removed the ability to control locale usage via an undocumented
	  `FMT_STATIC_THOUSANDS_SEPARATOR` in favor of `FMT_USE_LOCALE`.
	- Renamed `FMT_EXCEPTIONS` to `FMT_USE_EXCEPTIONS` for consistency with other
	  similar macros.
	- Improved include directory ordering to reduce the chance of including
	  incorrect headers when using multiple versions of {fmt}
	  (fmtlib/fmt#4116). Thanks @cdzhan.
	- Made it possible to compile a subset of {fmt} without the C++ runtime.
	- Improved documentation and README
	  (fmtlib/fmt#4066,
	  fmtlib/fmt#4117,
	  fmtlib/fmt#4203,
	  fmtlib/fmt#4235). Thanks @zyctree and @nikola-sh.
	- Improved the documentation generator (fmtlib/fmt#4110,
	  fmtlib/fmt#4115). Thanks @rturrado.
	- Improved CI (fmtlib/fmt#4155,
	  fmtlib/fmt#4151). Thanks @phprus.
	- Fixed various warnings and compilation issues
	  (fmtlib/fmt#2708,
	  fmtlib/fmt#4091,
	  fmtlib/fmt#4109,
	  fmtlib/fmt#4113,
	  fmtlib/fmt#4125,
	  fmtlib/fmt#4129,
	  fmtlib/fmt#4130,
	  fmtlib/fmt#4131,
	  fmtlib/fmt#4132,
	  fmtlib/fmt#4133,
	  fmtlib/fmt#4144,
	  fmtlib/fmt#4150,
	  fmtlib/fmt#4158,
	  fmtlib/fmt#4159,
	  fmtlib/fmt#4160,
	  fmtlib/fmt#4170,
	  fmtlib/fmt#4177,
	  fmtlib/fmt#4187,
	  fmtlib/fmt#4188,
	  fmtlib/fmt#4194,
	  fmtlib/fmt#4200,
	  fmtlib/fmt#4205,
	  fmtlib/fmt#4207,
	  fmtlib/fmt#4208,
	  fmtlib/fmt#4210,
	  fmtlib/fmt#4220,
	  fmtlib/fmt#4231,
	  fmtlib/fmt#4232,
	  fmtlib/fmt#4233,
	  fmtlib/fmt#4236,
	  fmtlib/fmt#4267,
	  fmtlib/fmt#4271).
	  Thanks @torsten48, @Arghnews, @tinfoilboy, @aminya, @Ottani, @zeroomega,
	  @c4v4, @kongy, @vinayyadav3016, @sergio-nsk, @phprus and @YexuanXiao.

Signed-off-by: Adolf Belka <[email protected]>
Signed-off-by: Michael Tremer <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants