Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libcxx/docs/ReleaseNotes/23.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Implemented Papers

- P2440R1: ``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right`` (`Github <https://llvm.org/PR105184>`__)
- P3936R1: Safer ``atomic_ref::address`` (`Github <https://llvm.org/PR189594>`__)
- P3953R3: Rename ``std::runtime_format`` (`Github <https://llvm.org/PR189624>`__)

Improvements and New Features
-----------------------------
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2cPapers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
"`P3826R5 <https://wg21.link/P3826R5>`__","Fix Sender Algorithm Customization","2026-03 (Croydon)","","","`#189620 <https://github.com/llvm/llvm-project/issues/189620>`__",""
"`P3980R1 <https://wg21.link/P3980R1>`__","Task's Allocator Use","2026-03 (Croydon)","","","`#189621 <https://github.com/llvm/llvm-project/issues/189621>`__",""
"`P4156R0 <https://wg21.link/P4156R0>`__","Rename meta::has_ellipsis_parameter to meta::is_vararg_function","2026-03 (Croydon)","","","`#189622 <https://github.com/llvm/llvm-project/issues/189622>`__",""
"`P3953R3 <https://wg21.link/P3953R3>`__","Rename ``std::runtime_format``","2026-03 (Croydon)","","","`#189624 <https://github.com/llvm/llvm-project/issues/189624>`__",""
"`P3953R3 <https://wg21.link/P3953R3>`__","Rename ``std::runtime_format``","2026-03 (Croydon)","|Complete|","23","`#189624 <https://github.com/llvm/llvm-project/issues/189624>`__",""
"`P4052R0 <https://wg21.link/P4052R0>`__","Renaming saturation arithmetic functions","2026-03 (Croydon)","","","`#189589 <https://github.com/llvm/llvm-project/issues/189589>`__",""
"`P3941R4 <https://wg21.link/P3941R4>`__","Scheduler Affinity","2026-03 (Croydon)","","","`#189627 <https://github.com/llvm/llvm-project/issues/189627>`__",""
"`P3856R8 <https://wg21.link/P3856R8>`__","New reflection metafunction - is_structural_type (US NB comment 49)","2026-03 (Croydon)","","","`#189625 <https://github.com/llvm/llvm-project/issues/189625>`__",""
Expand Down
14 changes: 7 additions & 7 deletions libcxx/include/__format/format_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,23 +342,23 @@ _LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator __vformat_to(_ParseCtx&&

# if _LIBCPP_STD_VER >= 26
template <class _CharT>
struct __runtime_format_string {
struct __dynamic_format_string {
private:
basic_string_view<_CharT> __str_;

template <class _Cp, class... _Args>
friend struct basic_format_string;

public:
_LIBCPP_HIDE_FROM_ABI __runtime_format_string(basic_string_view<_CharT> __s) noexcept : __str_(__s) {}
_LIBCPP_HIDE_FROM_ABI __dynamic_format_string(basic_string_view<_CharT> __s) noexcept : __str_(__s) {}

__runtime_format_string(const __runtime_format_string&) = delete;
__runtime_format_string& operator=(const __runtime_format_string&) = delete;
__dynamic_format_string(const __dynamic_format_string&) = delete;
__dynamic_format_string& operator=(const __dynamic_format_string&) = delete;
};

_LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<char> runtime_format(string_view __fmt) noexcept { return __fmt; }
_LIBCPP_HIDE_FROM_ABI inline __dynamic_format_string<char> dynamic_format(string_view __fmt) noexcept { return __fmt; }
# if _LIBCPP_HAS_WIDE_CHARACTERS
_LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<wchar_t> runtime_format(wstring_view __fmt) noexcept {
_LIBCPP_HIDE_FROM_ABI inline __dynamic_format_string<wchar_t> dynamic_format(wstring_view __fmt) noexcept {
return __fmt;
}
# endif
Expand All @@ -375,7 +375,7 @@ struct basic_format_string {

_LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<_CharT> get() const noexcept { return __str_; }
# if _LIBCPP_STD_VER >= 26
_LIBCPP_HIDE_FROM_ABI basic_format_string(__runtime_format_string<_CharT> __s) noexcept : __str_(__s.__str_) {}
_LIBCPP_HIDE_FROM_ABI basic_format_string(__dynamic_format_string<_CharT> __s) noexcept : __str_(__s.__str_) {}
# endif

private:
Expand Down
14 changes: 7 additions & 7 deletions libcxx/include/format
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace std {

public:
template<class T> consteval basic_format_string(const T& s);
basic_format_string(runtime-format-string<charT> s) noexcept : str(s.str) {} // since C++26
basic_format_string(dynamic-format-string<charT> s) noexcept : str(s.str) {} // since C++26

constexpr basic_string_view<charT> get() const noexcept { return str; }
};
Expand All @@ -42,21 +42,21 @@ namespace std {
using wformat_string = // since C++23, exposition only before C++23
basic_format_string<wchar_t, type_identity_t<Args>...>;

template<class charT> struct runtime-format-string { // since C++26, exposition-only
template<class charT> struct dynamic-format-string { // since C++26, exposition-only
private:
basic_string_view<charT> str; // exposition-only

public:
runtime-format-string(basic_string_view<charT> s) noexcept : str(s) {}
dynamic-format-string(basic_string_view<charT> s) noexcept : str(s) {}

runtime-format-string(const runtime-format-string&) = delete;
runtime-format-string& operator=(const runtime-format-string&) = delete;
dynamic-format-string(const dynamic-format-string&) = delete;
dynamic-format-string& operator=(const dynamic-format-string&) = delete;
};

runtime-format-string<char> runtime_format(string_view fmt) noexcept {
dynamic-format-string<char> dynamic_format(string_view fmt) noexcept {
return fmt;
}
runtime-format-string<wchar_t> runtime_format(wstring_view fmt) noexcept {
dynamic-format-string<wchar_t> dynamic_format(wstring_view fmt) noexcept {
return fmt;
}

Expand Down
2 changes: 1 addition & 1 deletion libcxx/modules/std/format.inc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export namespace std {
using std::wformat_string;
#endif
#if _LIBCPP_STD_VER >= 26
using std::runtime_format;
using std::dynamic_format;
#endif // _LIBCPP_STD_VER >= 26

// [format.functions], formatting functions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,28 @@
// template<class charT, class... Args>
// class basic_format_string<charT, type_identity_t<Args>...>
//
// basic_format_string(runtime-format-string<charT> s) noexcept : str(s.str) {}
// basic_format_string(dynamic-format-string<charT> s) noexcept : str(s.str) {}
//
// Additional testing is done in
// - libcxx/test/std/utilities/format/format.functions/format.runtime_format.pass.cpp
// - libcxx/test/std/utilities/format/format.functions/format.locale.runtime_format.pass.cpp
// - libcxx/test/std/utilities/format/format.functions/format.dynamic_format.pass.cpp
// - libcxx/test/std/utilities/format/format.functions/format.locale.dynamic_format.pass.cpp

#include <format>
#include <cassert>

#include "test_macros.h"

int main(int, char**) {
static_assert(noexcept(std::format_string<>{std::runtime_format(std::string_view{})}));
static_assert(noexcept(std::format_string<>{std::dynamic_format(std::string_view{})}));
{
std::format_string<> s = std::runtime_format("}{invalid format string}{");
std::format_string<> s = std::dynamic_format("}{invalid format string}{");
assert(s.get() == "}{invalid format string}{");
}

#ifndef TEST_HAS_NO_WIDE_CHARACTERS
static_assert(noexcept(std::wformat_string<>{std::runtime_format(std::wstring_view{})}));
static_assert(noexcept(std::wformat_string<>{std::dynamic_format(std::wstring_view{})}));
{
std::wformat_string<> s = std::runtime_format(L"}{invalid format string}{");
std::wformat_string<> s = std::dynamic_format(L"}{invalid format string}{");
assert(s.get() == L"}{invalid format string}{");
}
#endif // TEST_HAS_NO_WIDE_CHARACTERS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@

// Tests the behavior of
//
// runtime-format-string<char> runtime_format(string_view fmt) noexcept;
// runtime-format-string<wchar_t> runtime_format(wstring_view fmt) noexcept;
// dynamic-format-string<char> dynamic_format(string_view fmt) noexcept;
// dynamic-format-string<wchar_t> dynamic_format(wstring_view fmt) noexcept;
//
// and
//
// template<class charT, class... Args>
// struct basic_format_string {
// ...
// basic_format_string(runtime-format-string<charT> s) noexcept : str(s.str) {}
// basic_format_string(dynamic-format-string<charT> s) noexcept : str(s.str) {}
// ...
// }
//
Expand All @@ -34,9 +34,9 @@
// template<class... Args>
// wstring format(wformat_string<Args...> fmt, Args&&... args);
//
// The basics of runtime_format and basic_format_string's constructor are tested in
// - libcxx/test/std/utilities/format/format.syn/runtime_format_string.pass.cpp
// - libcxx/test/std/utilities/format/format.fmt.string/ctor.runtime-format-string.pass.cpp
// The basics of dynamic_format and basic_format_string's constructor are tested in
// - libcxx/test/std/utilities/format/format.syn/dynamic_format_string.pass.cpp
// - libcxx/test/std/utilities/format/format.fmt.string/ctor.dynamic-format-string.pass.cpp

#include <format>
#include <cassert>
Expand All @@ -50,7 +50,7 @@

auto test = []<class CharT, class... Args>(
std::basic_string_view<CharT> expected, std::basic_string_view<CharT> fmt, Args&&... args) constexpr {
std::basic_string<CharT> out = std::format(std::runtime_format(fmt), std::forward<Args>(args)...);
std::basic_string<CharT> out = std::format(std::dynamic_format(fmt), std::forward<Args>(args)...);
TEST_REQUIRE(out == expected,
TEST_WRITE_CONCATENATED(
"\nFormat string ", fmt, "\nExpected output ", expected, "\nActual output ", out, '\n'));
Expand All @@ -69,7 +69,7 @@ auto test_exception =
TEST_WRITE_CONCATENATED(
"\nFormat string ", fmt, "\nExpected exception ", what, "\nActual exception ", e.what(), '\n'));
},
TEST_IGNORE_NODISCARD std::format(std::runtime_format(fmt), std::forward<Args>(args)...));
TEST_IGNORE_NODISCARD std::format(std::dynamic_format(fmt), std::forward<Args>(args)...));
};

int main(int, char**) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@

// Tests the behavior of
//
// runtime-format-string<char> runtime_format(string_view fmt) noexcept;
// runtime-format-string<wchar_t> runtime_format(wstring_view fmt) noexcept;
// dynamic-format-string<char> dynamic_format(string_view fmt) noexcept;
// dynamic-format-string<wchar_t> dynamic_format(wstring_view fmt) noexcept;
//
// and
//
// template<class charT, class... Args>
// struct basic_format_string {
// ...
// basic_format_string(runtime-format-string<charT> s) noexcept : str(s.str) {}
// basic_format_string(dynamic-format-string<charT> s) noexcept : str(s.str) {}
// ...
// }
//
Expand All @@ -35,9 +35,9 @@
// template<class... Args>
// wstring format(const locale& loc, wformat_string<Args...> fmt, Args&&... args);
//
// The basics of runtime_format and basic_format_string's constructor are tested in
// - libcxx/test/std/utilities/format/format.syn/runtime_format_string.pass.cpp
// - libcxx/test/std/utilities/format/format.fmt.string/ctor.runtime-format-string.pass.cpp
// The basics of dynamic_format and basic_format_string's constructor are tested in
// - libcxx/test/std/utilities/format/format.syn/dynamic_format_string.pass.cpp
// - libcxx/test/std/utilities/format/format.fmt.string/ctor.dynamic-format-string.pass.cpp

#include <format>
#include <cassert>
Expand All @@ -52,7 +52,7 @@

auto test = []<class CharT, class... Args>(
std::basic_string_view<CharT> expected, std::basic_string_view<CharT> fmt, Args&&... args) constexpr {
std::basic_string<CharT> out = std::format(std::locale(), std::runtime_format(fmt), std::forward<Args>(args)...);
std::basic_string<CharT> out = std::format(std::locale(), std::dynamic_format(fmt), std::forward<Args>(args)...);
TEST_REQUIRE(out == expected,
TEST_WRITE_CONCATENATED(
"\nFormat string ", fmt, "\nExpected output ", expected, "\nActual output ", out, '\n'));
Expand All @@ -71,7 +71,7 @@ auto test_exception =
TEST_WRITE_CONCATENATED(
"\nFormat string ", fmt, "\nExpected exception ", what, "\nActual exception ", e.what(), '\n'));
},
TEST_IGNORE_NODISCARD std::format(std::locale(), std::runtime_format(fmt), std::forward<Args>(args)...));
TEST_IGNORE_NODISCARD std::format(std::locale(), std::dynamic_format(fmt), std::forward<Args>(args)...));
};

int main(int, char**) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@

// <format>

// template<class charT> struct runtime-format-string { // exposition-only
// template<class charT> struct dynamic-format-string { // exposition-only
// private:
// basic_string_view<charT> str; // exposition-only
//
// public:
// runtime-format-string(basic_string_view<charT> s) noexcept : str(s) {}
// dynamic-format-string(basic_string_view<charT> s) noexcept : str(s) {}
//
// runtime-format-string(const runtime-format-string&) = delete;
// runtime-format-string& operator=(const runtime-format-string&) = delete;
// dynamic-format-string(const dynamic-format-string&) = delete;
// dynamic-format-string& operator=(const dynamic-format-string&) = delete;
// };
//
// runtime-format-string<char> runtime_format(string_view fmt) noexcept;
// runtime-format-string<wchar_t> runtime_format(wstring_view fmt) noexcept;
// dynamic-format-string<char> dynamic_format(string_view fmt) noexcept;
// dynamic-format-string<wchar_t> dynamic_format(wstring_view fmt) noexcept;
//
// Additional testing is done in
// - libcxx/test/std/utilities/format/format.functions/format.runtime_format.pass.cpp
// - libcxx/test/std/utilities/format/format.functions/format.locale.runtime_format.pass.cpp
// - libcxx/test/std/utilities/format/format.functions/format.dynamic_format.pass.cpp
// - libcxx/test/std/utilities/format/format.functions/format.locale.dynamic_format.pass.cpp

#include <format>

Expand All @@ -50,19 +50,19 @@ static void test_properties() {
}

int main(int, char**) {
static_assert(noexcept(std::runtime_format(std::string_view{})));
auto format_string = std::runtime_format(std::string_view{});
static_assert(noexcept(std::dynamic_format(std::string_view{})));
auto format_string = std::dynamic_format(std::string_view{});

using FormatString = decltype(format_string);
LIBCPP_ASSERT((std::same_as<FormatString, std::__runtime_format_string<char>>));
LIBCPP_ASSERT((std::same_as<FormatString, std::__dynamic_format_string<char>>));
test_properties<FormatString, char>();

#ifndef TEST_HAS_NO_WIDE_CHARACTERS
static_assert(noexcept(std::runtime_format(std::wstring_view{})));
auto wformat_string = std::runtime_format(std::wstring_view{});
static_assert(noexcept(std::dynamic_format(std::wstring_view{})));
auto wformat_string = std::dynamic_format(std::wstring_view{});

using WFormatString = decltype(wformat_string);
LIBCPP_ASSERT((std::same_as<WFormatString, std::__runtime_format_string<wchar_t>>));
LIBCPP_ASSERT((std::same_as<WFormatString, std::__dynamic_format_string<wchar_t>>));
test_properties<WFormatString, wchar_t>();
#endif // TEST_HAS_NO_WIDE_CHARACTERS

Expand Down
1 change: 1 addition & 0 deletions libcxx/utils/generate_feature_test_macro_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ def add_version_header(tc):
# "c++23": 202207, Not implemented P2419R2 Clarify handling of encodings in localized formatting of chrono types
# "c++26": 202306, P2637R3 Member Visit (implemented)
# "c++26": 202311, P2918R2 Runtime format strings II (implemented)
# "c++26": 202603, P3953R3 Rename std::runtime_format (implemented)
},
# Note these three papers are adopted at the June 2023 meeting and have sequential numbering
# 202304 P2510R3 Formatting pointers (Implemented)
Expand Down
Loading