Author: Mark de Wever Date: 2022-08-10T17:52:20-07:00 New Revision: 13249036b774e4e5dc346d1f1a348f4ba201537a
URL: https://github.com/llvm/llvm-project/commit/13249036b774e4e5dc346d1f1a348f4ba201537a DIFF: https://github.com/llvm/llvm-project/commit/13249036b774e4e5dc346d1f1a348f4ba201537a.diff LOG: [libc++][format] Exposes basic-format-string This paper was accepted during the last plenary and is intended to be backported to LLVM 15. When backporting the release notes in the branch should be updated too. Note the feature-test macro isn't updated since this will change; three papers have updated the same macro in the same plenary. Implements: - P2508R1 Exposing std::basic-format-string Reviewed By: ldionne, #libc Differential Revision: https://reviews.llvm.org/D130643 (cherry picked from commit f712775dafdb221fdf73f38819fa9e618aec6b67) Added: libcxx/test/std/utilities/format/format.fmt.string/ctor.verify.cpp libcxx/test/std/utilities/format/format.fmt.string/get.pass.cpp libcxx/test/std/utilities/format/format.fmt.string/types.compile.pass.cpp Modified: libcxx/docs/ReleaseNotes.rst libcxx/docs/Status/Cxx2bPapers.csv libcxx/docs/Status/FormatIssues.csv libcxx/include/format libcxx/utils/generate_feature_test_macro_components.py Removed: ################################################################################ diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst index c717ea2682b54..6acde0db864bf 100644 --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -63,6 +63,7 @@ Implemented Papers - P2418R2 - Add support for ``std::generator``-like types to ``std::format`` - LWG3659 - Consider ``ATOMIC_FLAG_INIT`` undeprecation - P1423R3 - ``char8_t`` backward compatibility remediation +- P2508R1 - Exposing ``std::basic-format-string`` - Marked the following papers as "Complete" (note that some of those might have been implemented in a previous release but not marked as such): diff --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv index 4c5dd10db0684..27ff57c92150f 100644 --- a/libcxx/docs/Status/Cxx2bPapers.csv +++ b/libcxx/docs/Status/Cxx2bPapers.csv @@ -81,7 +81,7 @@ "`P2494R2 <https://wg21.link/P2494R2>`__","LWG","Relaxing range adaptors to allow for move only types","July 2022","","" "`P2499R0 <https://wg21.link/P2499R0>`__","LWG","``string_view`` range constructor should be ``explicit``","July 2022","","" "`P2502R2 <https://wg21.link/P2502R2>`__","LWG","``std::generator``: Synchronous Coroutine Generator for Ranges","July 2022","","" -"`P2508R1 <https://wg21.link/P2508R1>`__","LWG","Exposing ``std::basic-format-string``","July 2022","","" +"`P2508R1 <https://wg21.link/P2508R1>`__","LWG","Exposing ``std::basic-format-string``","July 2022","|Complete|","15.0" "`P2513R4 <https://wg21.link/P2513R4>`__","LWG","``char8_t`` Compatibility and Portability Fixes","July 2022","","" "`P2517R1 <https://wg21.link/P2517R1>`__","LWG","Add a conditional ``noexcept`` specification to ``std::apply``","July 2022","","" "`P2520R0 <https://wg21.link/P2520R0>`__","LWG","``move_iterator`` should be a random access iterator","July 2022","","" diff --git a/libcxx/docs/Status/FormatIssues.csv b/libcxx/docs/Status/FormatIssues.csv index 3f7304520c9e9..c3bdf169e82b1 100644 --- a/libcxx/docs/Status/FormatIssues.csv +++ b/libcxx/docs/Status/FormatIssues.csv @@ -5,6 +5,7 @@ Number,Name,Assignee,Patch,Status,First released version `P1868 <https://wg21.link/P1868>`_,"width: clarifying units of width and precision in std::format (Implements the unicode support.)",Mark de Wever,"`D103413 <https://reviews.llvm.org/D103413>`__ `D103425 <https://reviews.llvm.org/D103425>`__ `D103670 <https://reviews.llvm.org/D103670>`__",|Complete|,Clang 14 `P2216 <https://wg21.link/P2216>`_,"std::format improvements",Mark de Wever,,|Complete|,Clang 15 `P2418 <https://wg21.link/P2418>`__,"Add support for ``std::generator``-like types to ``std::format``",Mark de Wever,`D127570 <https://reviews.llvm.org/D127570>`__,|Complete|, Clang 15 +`P2508R1 <https://wg21.link/P2508R1>`__,"Exposing ``std::basic-format-string``","C++23","Mark de Wever","|Complete|",Clang 15 `P1361 <https://wg21.link/P1361>`_,"Integration of chrono with text formatting",Mark de Wever,,|In Progress|, `P2372 <https://wg21.link/P2372>`__,"Fixing locale handling in chrono formatters",Mark de Wever,,|In Progress|, diff --git a/libcxx/include/format b/libcxx/include/format index d2ec8fc233634..6b14570bc6272 100644 --- a/libcxx/include/format +++ b/libcxx/include/format @@ -23,16 +23,23 @@ namespace std { using format_args = basic_format_args<format_context>; using wformat_args = basic_format_args<wformat_context>; - // [format.fmt.string], class template basic-format-string + // [format.fmt.string], class template basic_format_string template<class charT, class... Args> - struct basic-format-string; // exposition only + struct basic_format_string { // since C++23, exposition only before C++23 + private: + basic_string_view<charT> str; // exposition only + public: + template<class T> consteval basic_format_string(const T& s); + + constexpr basic_string_view<charT> get() const noexcept { return str; } + }; template<class... Args> - using format-string = // exposition only - basic-format-string<char, type_identity_t<Args>...>; + using format_string = // since C++23, exposition only before C++23 + basic_format_string<char, type_identity_t<Args>...>; template<class... Args> - using wformat-string = // exposition only - basic-format-string<wchar_t, type_identity_t<Args>...>; + using wformat_string = // since C++23, exposition only before C++23 + basic_format_string<wchar_t, type_identity_t<Args>...>; // [format.functions], formatting functions template<class... Args> @@ -233,7 +240,7 @@ private: }; // Dummy format_context only providing the parts used during constant -// validation of the basic-format-string. +// validation of the basic_format_string. template <class _CharT> struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context { public: @@ -468,17 +475,21 @@ __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { } // namespace __format template <class _CharT, class... _Args> -struct _LIBCPP_TEMPLATE_VIS __basic_format_string { - basic_string_view<_CharT> __str_; - +struct _LIBCPP_TEMPLATE_VIS basic_format_string { template <class _Tp> requires convertible_to<const _Tp&, basic_string_view<_CharT>> - consteval __basic_format_string(const _Tp& __str) : __str_{__str} { + consteval basic_format_string(const _Tp& __str) : __str_{__str} { __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)}, _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT constexpr basic_string_view<_CharT> get() const noexcept { + return __str_; + } + private: + basic_string_view<_CharT> __str_; + using _Context = __format::__compile_time_basic_format_context<_CharT>; static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ @@ -510,11 +521,11 @@ private: }; template <class... _Args> -using __format_string_t = __basic_format_string<char, type_identity_t<_Args>...>; +using format_string = basic_format_string<char, type_identity_t<_Args>...>; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class... _Args> -using __wformat_string_t = __basic_format_string<wchar_t, type_identity_t<_Args>...>; +using wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>; #endif template <class _OutIt, class _CharT, class _FormatOutIt> @@ -555,16 +566,16 @@ vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { template <output_iterator<const char&> _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, __format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_, +format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_, +format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -586,16 +597,16 @@ vformat(wstring_view __fmt, wformat_args __args) { #endif template <class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(__format_string_t<_Args...> __fmt, +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(__fmt.__str_, _VSTD::make_format_args(__args...)); + return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring -format(__wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(__fmt.__str_, _VSTD::make_wformat_args(__args...)); +format(wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat(__fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -611,16 +622,16 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, template <output_iterator<const char&> _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_ diff erence_t<_OutIt> __n, __format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_format_args(__args...)); +format_to_n(_OutIt __out_it, iter_ diff erence_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt, class... _Args> _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_ diff erence_t<_OutIt> __n, __wformat_string_t<_Args...> __fmt, +format_to_n(_OutIt __out_it, iter_ diff erence_t<_OutIt> __n, wformat_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_wformat_args(__args...)); + return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -634,15 +645,15 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, template <class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(__format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)}); +formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(__wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)}); +formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); } #endif @@ -686,16 +697,16 @@ _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt v template <output_iterator<const char&> _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_, +format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_, +format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -720,17 +731,17 @@ vformat(locale __loc, wstring_view __fmt, wformat_args __args) { template <class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc, - __format_string_t<_Args...> __fmt, + format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_, + return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring -format(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_, +format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -748,18 +759,18 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, template <output_iterator<const char&> _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_ diff erence_t<_OutIt> __n, locale __loc, __format_string_t<_Args...> __fmt, +format_to_n(_OutIt __out_it, iter_ diff erence_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_, + return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_ diff erence_t<_OutIt> __n, locale __loc, __wformat_string_t<_Args...> __fmt, +format_to_n(_OutIt __out_it, iter_ diff erence_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_, + return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -775,15 +786,15 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_ template <class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)}); +formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)}); +formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); } #endif diff --git a/libcxx/test/std/utilities/format/format.fmt.string/ctor.verify.cpp b/libcxx/test/std/utilities/format/format.fmt.string/ctor.verify.cpp new file mode 100644 index 0000000000000..8f5404daaf396 --- /dev/null +++ b/libcxx/test/std/utilities/format/format.fmt.string/ctor.verify.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-has-no-incomplete-format + +// libc++ supports basic_format_string in C++20 as an extension +// UNSUPPORTED: !stdlib=libc++ && c++20 + +// <format> + +// template<class charT, class... Args> +// class basic_format_string<charT, type_identity_t<Args>...> +// +// template<class T> consteval basic_format_string(const T& s); +// +// This constructor does the compile-time format string validation for the +// std::format* functions. + +#include <format> + +#include <string_view> + +#include "test_macros.h" + +void run() { + (void)std::basic_format_string<char>{"foo"}; + (void)std::basic_format_string<char>{"{}"}; // expected-error-re {{call to consteval function{{.*}}is not a constant expression}} + (void)std::basic_format_string<char, int>{"{0:{0}P}"}; // expected-error-re {{call to consteval function{{.*}}is not a constant expression}} + (void)std::basic_format_string<char, int>{"{0:{0}}"}; + (void)std::basic_format_string<char, float>{"{0:{0}}"}; // expected-error-re {{call to consteval function{{.*}}is not a constant expression}} + (void)std::basic_format_string<char, int>{"{.3}"}; // expected-error-re {{call to consteval function{{.*}}is not a constant expression}} +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + (void)std::basic_format_string<wchar_t>{L"foo"}; + (void)std::basic_format_string<wchar_t>{L"{}"}; // expected-error-re {{call to consteval function{{.*}}is not a constant expression}} + (void)std::basic_format_string<wchar_t, int>{L"{0:{0}P}"}; // expected-error-re {{call to consteval function{{.*}}is not a constant expression}} + (void)std::basic_format_string<wchar_t, int>{L"{0:{0}}"}; + (void)std::basic_format_string<wchar_t, float>{L"{0:{0}}"}; // expected-error-re {{call to consteval function{{.*}}is not a constant expression}} + (void)std::basic_format_string<wchar_t, int>{L"{.3}"}; // expected-error-re {{call to consteval function{{.*}}is not a constant expression}} +#endif +} diff --git a/libcxx/test/std/utilities/format/format.fmt.string/get.pass.cpp b/libcxx/test/std/utilities/format/format.fmt.string/get.pass.cpp new file mode 100644 index 0000000000000..bf7e2add0e8f5 --- /dev/null +++ b/libcxx/test/std/utilities/format/format.fmt.string/get.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-has-no-incomplete-format + +// libc++ supports basic_format_string in C++20 as an extension +// UNSUPPORTED: !stdlib=libc++ && c++20 + +// <format> + +// template<class charT, class... Args> +// class basic_format_string<charT, type_identity_t<Args>...> +// +// constexpr basic_string_view<charT> get() const noexcept { return str; } + +#include <format> + +#include <cassert> +#include <concepts> +#include <string_view> + +#include "test_macros.h" +#include "make_string.h" + +#define CSTR(S) MAKE_CSTRING(CharT, S) +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template <class CharT> +constexpr bool test() { + assert((std::basic_format_string<CharT>{CSTR("foo")}.get() == SV("foo"))); + assert((std::basic_format_string<CharT, int>{CSTR("{}")}.get() == SV("{}"))); + assert((std::basic_format_string<CharT, int, float>{CSTR("{} {:01.23L}")}.get() == SV("{} {:01.23L}"))); + + // Embedded NUL character + assert((std::basic_format_string<CharT, void*, double>{SV("{}\0{}")}.get() == SV("{}\0{}"))); + return true; +} + +int main(int, char**) { + test<char>(); + static_assert(test<char>()); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test<wchar_t>(); + static_assert(test<wchar_t>()); +#endif + return 0; +} diff --git a/libcxx/test/std/utilities/format/format.fmt.string/types.compile.pass.cpp b/libcxx/test/std/utilities/format/format.fmt.string/types.compile.pass.cpp new file mode 100644 index 0000000000000..3ebd2bfc4fbd5 --- /dev/null +++ b/libcxx/test/std/utilities/format/format.fmt.string/types.compile.pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-has-no-incomplete-format + +// libc++ supports basic_format_string in C++20 as an extension +// UNSUPPORTED: !stdlib=libc++ && c++20 + +// <format> + +// template<class... Args> +// using format_string = +// basic_format_string<char, type_identity_t<Args>...>; +// template<class... Args> +// using wformat_string = +// basic_format_string<wchar_t, type_identity_t<Args>...>; + +#include <format> + +#include <concepts> + +#include "test_macros.h" + +static_assert(std::same_as<std::format_string<>, std::basic_format_string<char>>); +static_assert(std::same_as<std::format_string<int>, std::basic_format_string<char, int>>); +static_assert(std::same_as<std::format_string<int, float>, std::basic_format_string<char, int, float>>); +static_assert(std::same_as<std::format_string<int, float, void*>, std::basic_format_string<char, int, float, void*>>); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS +static_assert(std::same_as<std::wformat_string<>, std::basic_format_string<wchar_t>>); +static_assert(std::same_as<std::wformat_string<int>, std::basic_format_string<wchar_t, int>>); +static_assert(std::same_as<std::wformat_string<int, float>, std::basic_format_string<wchar_t, int, float>>); +static_assert( + std::same_as<std::wformat_string<int, float, void*>, std::basic_format_string<wchar_t, int, float, void*>>); +#endif diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index 6b8db98242f29..f9bfa13cc2991 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -309,6 +309,11 @@ def add_version_header(tc): "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem)" }, { "name": "__cpp_lib_format", + # P2508, P2286, and P2419 were accepted in the same plenary and modify this + # feature-test macro. We expect to see an LWG issue soon. For now keep the + # value as is. + # TODO FMT Set P2508's feature-test macro. + #"values": { "c++20": 202106, "c++23": 202207" }, "values": { "c++20": 202106 }, "headers": ["format"], "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)", _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits