[libc++][format] Implement format-string.

Implements the compile-time checking of the formatting arguments.

Completes:
- P2216 std::format improvements

Reviewed By: #libc, ldionne

Differential Revision: https://reviews.llvm.org/D121530
This commit is contained in:
Mark de Wever 2021-10-02 12:38:46 +02:00
parent 338fd211e7
commit aed5ddf8d0
21 changed files with 1152 additions and 264 deletions

View File

@ -216,17 +216,27 @@ struct FloatingPoint {
void run(benchmark::State& state) const {
std::array<F, 1000> data{Value<V::value>::template make_data<F>()};
std::array<char, 20'000> output;
std::string fmt{std::string("{:") + Alignment<A::value>::fmt + Precision<P::value>::fmt +
Localization<L::value>::fmt + DisplayType<DT::value>::fmt + "}"};
while (state.KeepRunningBatch(1000))
for (F value : data)
benchmark::DoNotOptimize(std::format_to(output.begin(), fmt, value));
benchmark::DoNotOptimize(std::format_to(output.begin(), std::string_view{fmt.data(), fmt.size()}, value));
}
std::string name() const {
return "FloatingPoint" + L::name() + DT::name() + T::name() + V::name() + A::name() + P::name();
}
static constexpr std::string make_fmt() {
return std::string("{:") + Alignment<A::value>::fmt + Precision<P::value>::fmt + Localization<L::value>::fmt +
DisplayType<DT::value>::fmt + "}";
}
static constexpr auto fmt = []() {
constexpr size_t s = make_fmt().size();
std::array<char, s> r;
std::ranges::copy(make_fmt(), r.begin());
return r;
}();
};
int main(int argc, char** argv) {

View File

@ -73,6 +73,14 @@ New Features
moved from the dylib to the header. This means the function no longer has a
minimum deployment target.
- Implemented P2216R3 (std::format improvements). The format functions
(``std::format``, ``std::format_to``, ``std::format_to_n``, and
``std::formatted_size``) now validate the format string at compile time.
When the format string is invalid this will make the code ill-formed instead
of throwing an exception at run-time. (This does not affect the ``v``
functions.)
API Changes
-----------

View File

@ -196,7 +196,7 @@
"`P2231R1 <https://wg21.link/P2231R1>`__","LWG","Missing constexpr in std::optional and std::variant","June 2021","|Partial| [#note-P2231]_","13.0"
"`P2325R3 <https://wg21.link/P2325R3>`__","LWG","Views should not be required to be default constructible","June 2021","|In progress|",""
"`P2210R2 <https://wg21.link/P2210R2>`__","LWG",Superior String Splitting,"June 2021","",""
"`P2216R3 <https://wg21.link/P2216R3>`__","LWG",std::format improvements,"June 2021","|Partial|",""
"`P2216R3 <https://wg21.link/P2216R3>`__","LWG",std::format improvements,"June 2021","|Complete|","15.0"
"`P2281R1 <https://wg21.link/P2281R1>`__","LWG",Clarifying range adaptor objects,"June 2021","|Complete|","14.0"
"`P2328R1 <https://wg21.link/P2328R1>`__","LWG",join_view should join all views of ranges,"June 2021","",""
"`P2367R0 <https://wg21.link/P2367R0>`__","LWG",Remove misuses of list-initialization from Clause 24,"June 2021","",""

1 Paper # Group Paper Name Meeting Status First released version
196 `P2231R1 <https://wg21.link/P2231R1>`__ LWG Missing constexpr in std::optional and std::variant June 2021 |Partial| [#note-P2231]_ 13.0
197 `P2325R3 <https://wg21.link/P2325R3>`__ LWG Views should not be required to be default constructible June 2021 |In progress|
198 `P2210R2 <https://wg21.link/P2210R2>`__ LWG Superior String Splitting June 2021
199 `P2216R3 <https://wg21.link/P2216R3>`__ LWG std::format improvements June 2021 |Partial| |Complete| 15.0
200 `P2281R1 <https://wg21.link/P2281R1>`__ LWG Clarifying range adaptor objects June 2021 |Complete| 14.0
201 `P2328R1 <https://wg21.link/P2328R1>`__ LWG join_view should join all views of ranges June 2021
202 `P2367R0 <https://wg21.link/P2367R0>`__ LWG Remove misuses of list-initialization from Clause 24 June 2021

View File

@ -252,6 +252,13 @@ public:
/** Determines whether the value stored is a width or an arg-id. */
uint32_t __width_as_arg : 1 {0};
/**
* Does the supplied width field contain an arg-id?
*
* If @c true the formatter needs to call @ref __substitute_width_arg_id.
*/
constexpr bool __width_needs_substitution() const noexcept { return __width_as_arg; }
protected:
/**
* Does the supplied std-format-spec contain a width field?
@ -259,18 +266,7 @@ protected:
* When the field isn't present there's no padding required. This can be used
* to optimize the formatting.
*/
constexpr bool __has_width_field() const noexcept {
return __width_as_arg || __width;
}
/**
* Does the supplied width field contain an arg-id?
*
* If @c true the formatter needs to call @ref __substitute_width_arg_id.
*/
constexpr bool __width_needs_substitution() const noexcept {
return __width_as_arg;
}
constexpr bool __has_width_field() const noexcept { return __width_as_arg || __width; }
template <class _CharT>
_LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
@ -327,6 +323,15 @@ public:
*/
uint32_t __precision_as_arg : 1 {1};
/**
* Does the supplied precision field contain an arg-id?
*
* If @c true the formatter needs to call @ref __substitute_precision_arg_id.
*/
constexpr bool __precision_needs_substitution() const noexcept {
return __precision_as_arg && __precision != __format::__number_max;
}
protected:
/**
* Does the supplied std-format-spec contain a precision field?
@ -340,15 +345,6 @@ protected:
__precision != __format::__number_max; // The arg-id is valid?
}
/**
* Does the supplied precision field contain an arg-id?
*
* If @c true the formatter needs to call @ref __substitute_precision_arg_id.
*/
constexpr bool __precision_needs_substitution() const noexcept {
return __precision_as_arg && __precision != __format::__number_max;
}
template <class _CharT>
_LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
__parse(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) {

View File

@ -23,15 +23,26 @@ 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
template<class charT, class... Args>
struct basic-format-string; // exposition only
template<class... Args>
using format-string = // exposition only
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>...>;
// [format.functions], formatting functions
template<class... Args>
string format(string_view fmt, const Args&... args);
string format(format-string<Args...> fmt, const Args&... args);
template<class... Args>
wstring format(wstring_view fmt, const Args&... args);
wstring format(wformat-string<Args...> fmt, const Args&... args);
template<class... Args>
string format(const locale& loc, string_view fmt, const Args&... args);
string format(const locale& loc, format-string<Args...> fmt, const Args&... args);
template<class... Args>
wstring format(const locale& loc, wstring_view fmt, const Args&... args);
wstring format(const locale& loc, wformat-string<Args...> fmt, const Args&... args);
string vformat(string_view fmt, format_args args);
wstring vformat(wstring_view fmt, wformat_args args);
@ -39,13 +50,13 @@ namespace std {
wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);
template<class Out, class... Args>
Out format_to(Out out, string_view fmt, const Args&... args);
Out format_to(Out out, format-string<Args...> fmt, const Args&... args);
template<class Out, class... Args>
Out format_to(Out out, wstring_view fmt, const Args&... args);
Out format_to(Out out, wformat-string<Args...> fmt, const Args&... args);
template<class Out, class... Args>
Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args);
Out format_to(Out out, const locale& loc, format-string<Args...> fmt, const Args&... args);
template<class Out, class... Args>
Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
Out format_to(Out out, const locale& loc, wformat-string<Args...> fmt, const Args&... args);
template<class Out>
Out vformat_to(Out out, string_view fmt, format_args args);
@ -64,27 +75,27 @@ namespace std {
};
template<class Out, class... Args>
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
string_view fmt, const Args&... args);
format-string<Args...> fmt, const Args&... args);
template<class Out, class... Args>
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
wstring_view fmt, const Args&... args);
wformat-string<Args...> fmt, const Args&... args);
template<class Out, class... Args>
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
const locale& loc, string_view fmt,
const locale& loc, format-string<Args...> fmt,
const Args&... args);
template<class Out, class... Args>
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
const locale& loc, wstring_view fmt,
const locale& loc, wformat-string<Args...> fmt,
const Args&... args);
template<class... Args>
size_t formatted_size(string_view fmt, const Args&... args);
size_t formatted_size(format-string<Args...> fmt, const Args&... args);
template<class... Args>
size_t formatted_size(wstring_view fmt, const Args&... args);
size_t formatted_size(wformat-string<Args...> fmt, const Args&... args);
template<class... Args>
size_t formatted_size(const locale& loc, string_view fmt, const Args&... args);
size_t formatted_size(const locale& loc, format-string<Args...> fmt, const Args&... args);
template<class... Args>
size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);
size_t formatted_size(const locale& loc, wformat-string<Args...> fmt, const Args&... args);
// [format.formatter], formatter
template<class T, class charT = char> struct formatter;
@ -203,8 +214,163 @@ _LIBCPP_HIDE_FROM_ABI auto make_wformat_args(const _Args&... __args) {
namespace __format {
/// Helper class parse and handle argument.
///
/// When parsing a handle which is not enabled the code is ill-formed.
/// This helper uses the parser of the appropriate formatter for the stored type.
template <class _CharT>
class _LIBCPP_TEMPLATE_VIS __compile_time_handle {
public:
_LIBCPP_HIDE_FROM_ABI
constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); }
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr void __enable() {
__parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) {
formatter<_Tp, _CharT> __f;
__parse_ctx.advance_to(__f.parse(__parse_ctx));
};
}
// Before calling __parse the proper handler needs to be set with __enable.
// The default handler isn't a core constant expression.
_LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle()
: __parse_([](basic_format_parse_context<_CharT>&) { __throw_format_error("Not a handle"); }) {}
private:
void (*__parse_)(basic_format_parse_context<_CharT>&);
};
// Dummy format_context only providing the parts used during constant
// validation of the basic-format-string.
template <class _CharT>
struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context {
public:
using char_type = _CharT;
_LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context(
const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size)
: __args_(__args), __handles_(__handles), __size_(__size) {}
// During the compile-time validation nothing needs to be written.
// Therefore all operations of this iterator are a NOP.
struct iterator {
_LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; }
_LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; }
_LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; }
};
_LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const {
if (__id >= __size_)
__throw_format_error("Argument index out of bounds");
return __args_[__id];
}
_LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const {
if (__id >= __size_)
__throw_format_error("Argument index out of bounds");
return __handles_[__id];
}
_LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; }
_LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {}
private:
const __arg_t* __args_;
const __compile_time_handle<_CharT>* __handles_;
size_t __size_;
};
_LIBCPP_HIDE_FROM_ABI
constexpr void __compile_time_validate_integral(__arg_t __type) {
switch (__type) {
case __arg_t::__int:
case __arg_t::__long_long:
case __arg_t::__i128:
case __arg_t::__unsigned:
case __arg_t::__unsigned_long_long:
case __arg_t::__u128:
return;
default:
__throw_format_error("Argument isn't an integral type");
}
}
// _HasPrecision does the formatter have a precision?
template <class _CharT, class _Tp, bool _HasPrecision = false>
_LIBCPP_HIDE_FROM_ABI constexpr void
__compile_time_validate_argument(basic_format_parse_context<_CharT>& __parse_ctx,
__compile_time_basic_format_context<_CharT>& __ctx) {
formatter<_Tp, _CharT> __formatter;
__parse_ctx.advance_to(__formatter.parse(__parse_ctx));
// [format.string.std]/7
// ... If the corresponding formatting argument is not of integral type, or
// its value is negative for precision or non-positive for width, an
// exception of type format_error is thrown.
//
// Validate whether the arguments are integrals.
if (__formatter.__width_needs_substitution())
__format::__compile_time_validate_integral(__ctx.arg(__formatter.__width));
if constexpr (_HasPrecision)
if (__formatter.__precision_needs_substitution())
__format::__compile_time_validate_integral(__ctx.arg(__formatter.__precision));
}
template <class _CharT>
_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_format_parse_context<_CharT>& __parse_ctx,
__compile_time_basic_format_context<_CharT>& __ctx,
__arg_t __type) {
switch (__type) {
case __arg_t::__none:
__throw_format_error("Invalid argument");
case __arg_t::__boolean:
return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx);
case __arg_t::__char_type:
return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx);
case __arg_t::__int:
return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx);
case __arg_t::__long_long:
return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx);
case __arg_t::__i128:
# ifndef _LIBCPP_HAS_NO_INT128
return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx);
# else
__throw_format_error("Invalid argument");
# endif
return;
case __arg_t::__unsigned:
return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx);
case __arg_t::__unsigned_long_long:
return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx);
case __arg_t::__u128:
# ifndef _LIBCPP_HAS_NO_INT128
return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx);
# else
__throw_format_error("Invalid argument");
# endif
return;
case __arg_t::__float:
return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx);
case __arg_t::__double:
return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx);
case __arg_t::__long_double:
return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx);
case __arg_t::__const_char_type_ptr:
return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx);
case __arg_t::__string_view:
return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx);
case __arg_t::__ptr:
return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx);
case __arg_t::__handle:
__throw_format_error("Handle should use __compile_time_validate_handle_argument");
}
__throw_format_error("Invalid argument");
}
template <class _CharT, class _ParseCtx, class _Ctx>
_LIBCPP_HIDE_FROM_ABI const _CharT*
_LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
_ParseCtx& __parse_ctx, _Ctx& __ctx) {
__format::__parse_number_result __r =
@ -224,19 +390,26 @@ __handle_replacement_field(const _CharT* __begin, const _CharT* __end,
"The replacement field arg-id should terminate at a ':' or '}'");
}
_VSTD::visit_format_arg(
[&](auto __arg) {
if constexpr (same_as<decltype(__arg), monostate>)
__throw_format_error("Argument index out of bounds");
else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)
__arg.format(__parse_ctx, __ctx);
else {
formatter<decltype(__arg), _CharT> __formatter;
__parse_ctx.advance_to(__formatter.parse(__parse_ctx));
__ctx.advance_to(__formatter.format(__arg, __ctx));
}
},
__ctx.arg(__r.__value));
if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) {
__arg_t __type = __ctx.arg(__r.__value);
if (__type == __arg_t::__handle)
__ctx.__handle(__r.__value).__parse(__parse_ctx);
else
__format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type);
} else
_VSTD::visit_format_arg(
[&](auto __arg) {
if constexpr (same_as<decltype(__arg), monostate>)
__throw_format_error("Argument index out of bounds");
else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)
__arg.format(__parse_ctx, __ctx);
else {
formatter<decltype(__arg), _CharT> __formatter;
__parse_ctx.advance_to(__formatter.parse(__parse_ctx));
__ctx.advance_to(__formatter.format(__arg, __ctx));
}
},
__ctx.arg(__r.__value));
__begin = __parse_ctx.begin();
if (__begin == __end || *__begin != _CharT('}'))
@ -246,7 +419,7 @@ __handle_replacement_field(const _CharT* __begin, const _CharT* __end,
}
template <class _ParseCtx, class _Ctx>
_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
_LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator
__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
using _CharT = typename _ParseCtx::char_type;
static_assert(same_as<typename _Ctx::char_type, _CharT>);
@ -291,6 +464,56 @@ __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_;
template <class _Tp>
requires convertible_to<const _Tp&, basic_string_view<_CharT>>
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)});
}
private:
using _Context = __format::__compile_time_basic_format_context<_CharT>;
static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{
__format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...};
// TODO FMT remove this work-around when the AIX ICE has been resolved.
# if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400
template <class _Tp>
static constexpr __format::__compile_time_handle<_CharT> __get_handle() {
__format::__compile_time_handle<_CharT> __handle;
if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle)
__handle.template __enable<_Tp>();
return __handle;
}
static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{
__get_handle<_Args>()...};
# else
static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] {
using _Tp = remove_cvref_t<_Args>;
__format::__compile_time_handle<_CharT> __handle;
if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle)
__handle.template __enable<_Tp>();
return __handle;
}()...};
# endif
};
template <class... _Args>
using __format_string_t = __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>...>;
#endif
template <class _OutIt, class _CharT, class _FormatOutIt>
requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
__vformat_to(
@ -329,16 +552,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, string_view __fmt, const _Args&... __args) {
return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
format_to(_OutIt __out_it, __format_string_t<_Args...> __fmt, const _Args&... __args) {
return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_,
_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, wstring_view __fmt, const _Args&... __args) {
return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
format_to(_OutIt __out_it, __wformat_string_t<_Args...> __fmt, const _Args&... __args) {
return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_,
_VSTD::make_wformat_args(__args...));
}
#endif
@ -360,16 +583,16 @@ vformat(wstring_view __fmt, wformat_args __args) {
#endif
template <class... _Args>
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
format(string_view __fmt, const _Args&... __args) {
return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(__format_string_t<_Args...> __fmt,
const _Args&... __args) {
return _VSTD::vformat(__fmt.__str_, _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(wstring_view __fmt, const _Args&... __args) {
return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
format(__wformat_string_t<_Args...> __fmt, const _Args&... __args) {
return _VSTD::vformat(__fmt.__str_, _VSTD::make_wformat_args(__args...));
}
#endif
@ -385,15 +608,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_difference_t<_OutIt> __n, string_view __fmt, const _Args&... __args) {
return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt, _VSTD::make_format_args(__args...));
format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __format_string_t<_Args...> __fmt, const _Args&... __args) {
return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _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_difference_t<_OutIt> __n, wstring_view __fmt, const _Args&... __args) {
return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt, _VSTD::make_wformat_args(__args...));
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __wformat_string_t<_Args...> __fmt,
const _Args&... __args) {
return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_wformat_args(__args...));
}
#endif
@ -406,16 +630,16 @@ _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(string_view __fmt,
const _Args&... __args) {
return _VSTD::__vformatted_size(__fmt, basic_format_args{_VSTD::make_format_args(__args...)});
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
formatted_size(__format_string_t<_Args...> __fmt, const _Args&... __args) {
return _VSTD::__vformatted_size(__fmt.__str_, 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(wstring_view __fmt,
const _Args&... __args) {
return _VSTD::__vformatted_size(__fmt, basic_format_args{_VSTD::make_wformat_args(__args...)});
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
formatted_size(__wformat_string_t<_Args...> __fmt, const _Args&... __args) {
return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)});
}
#endif
@ -458,17 +682,17 @@ _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt v
#endif
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, string_view __fmt, const _Args&... __args) {
return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
format_to(_OutIt __out_it, locale __loc, __format_string_t<_Args...> __fmt, const _Args&... __args) {
return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_,
_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, wstring_view __fmt, const _Args&... __args) {
return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
format_to(_OutIt __out_it, locale __loc, __wformat_string_t<_Args...> __fmt, const _Args&... __args) {
return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_,
_VSTD::make_wformat_args(__args...));
}
#endif
@ -492,17 +716,18 @@ vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
#endif
template <class... _Args>
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
format(locale __loc, string_view __fmt, const _Args&... __args) {
return _VSTD::vformat(_VSTD::move(__loc), __fmt,
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc,
__format_string_t<_Args...> __fmt,
const _Args&... __args) {
return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_,
_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, wstring_view __fmt, const _Args&... __args) {
return _VSTD::vformat(_VSTD::move(__loc), __fmt,
format(locale __loc, __wformat_string_t<_Args...> __fmt, const _Args&... __args) {
return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_,
_VSTD::make_wformat_args(__args...));
}
#endif
@ -520,16 +745,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_difference_t<_OutIt> __n, locale __loc, string_view __fmt, const _Args&... __args) {
return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt,
format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __format_string_t<_Args...> __fmt,
const _Args&... __args) {
return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_,
_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_difference_t<_OutIt> __n, locale __loc, wstring_view __fmt, const _Args&... __args) {
return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt,
format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __wformat_string_t<_Args...> __fmt,
const _Args&... __args) {
return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_,
_VSTD::make_wformat_args(__args...));
}
#endif
@ -544,18 +771,16 @@ _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,
string_view __fmt,
const _Args&... __args) {
return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt, basic_format_args{_VSTD::make_format_args(__args...)});
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
formatted_size(locale __loc, __format_string_t<_Args...> __fmt, const _Args&... __args) {
return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, 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,
wstring_view __fmt,
const _Args&... __args) {
return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt, basic_format_args{_VSTD::make_wformat_args(__args...)});
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
formatted_size(locale __loc, __wformat_string_t<_Args...> __fmt, const _Args&... __args) {
return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)});
}
#endif

View File

@ -16,9 +16,9 @@
// <format>
// template<class... Args>
// string format(const locale& loc, string_view fmt, const Args&... args);
// string format(const locale& loc, format-string<Args...> fmt, const Args&... args);
// template<class... Args>
// wstring format(const locale& loc, wstring_view fmt, const Args&... args);
// wstring format(const locale& loc, wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include <cassert>
@ -39,30 +39,11 @@ auto test = []<string_literal fmt, class CharT, class... Args>(std::basic_string
assert(out == expected);
};
auto test_exception = []<class CharT, class... Args>(std::string_view what, std::basic_string_view<CharT> fmt,
const Args&... args) {
#ifndef TEST_HAS_NO_EXCEPTIONS
try {
std::format(std::locale(), fmt, args...);
if constexpr (std::same_as<CharT, char>)
std::cerr << "\nFormat string " << fmt << "\nDidn't throw an exception.\n";
assert(false);
} catch (const std::format_error& e) {
# ifdef _LIBCPP_VERSION
if constexpr (std::same_as<CharT, char>)
if (e.what() != what)
std::cerr << "\nFormat string " << fmt << "\nExpected exception " << what << "\nActual exception "
<< e.what() << '\n';
# endif
LIBCPP_ASSERT(e.what() == what);
return;
}
assert(false);
#else
(void)what;
(void)fmt;
(void)sizeof...(args);
#endif
auto test_exception = []<class CharT, class... Args>(std::string_view, std::basic_string_view<CharT>, const Args&...) {
// After P2216 most exceptions thrown by std::format become ill-formed.
// Therefore this tests does nothing.
// A basic ill-formed test is done in format.locale.verify.cpp
// The exceptions are tested by other functions that don't use the basic-format-string as fmt argument.
};
int main(int, char**) {

View File

@ -0,0 +1,92 @@
//===----------------------------------------------------------------------===//
// 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: no-localization
// UNSUPPORTED: libcpp-has-no-incomplete-format
// TODO FMT Evaluate gcc-11 status
// UNSUPPORTED: gcc-11
// Basic test to validate ill-formed code is properly detected.
// <format>
// template<class... Args>
// string format(const locale& loc, format-string<Args...> fmt, const Args&... args);
// template<class... Args>
// wstring format(const locale& loc, wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include <locale>
#include "test_macros.h"
// clang-format off
void f() {
std::format(std::locale(), "{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), "}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), "{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), "{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), "{:-}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), "{:#}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), "{:L}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), "{0:{0}}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), "{:.42d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), "{:d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
std::format(std::locale(), L"{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), L"}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), L"{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), L"{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), L"{:-}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), L"{:#}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), L"{:L}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), L"{0:{0}}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), L"{:.42d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(std::locale(), L"{:d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#endif
}

View File

@ -19,9 +19,9 @@
// <format>
// template<class... Args>
// string format(string_view fmt, const Args&... args);
// string format(format-string<Args...> fmt, const Args&... args);
// template<class... Args>
// wstring format(wstring_view fmt, const Args&... args);
// wstring format(wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include <cassert>
@ -48,31 +48,11 @@ auto test = []<string_literal fmt, class CharT, class... Args>(std::basic_string
assert(out == expected);
};
auto test_exception = []<class CharT, class... Args>(std::string_view what, std::basic_string_view<CharT> fmt,
const Args&... args) {
#ifndef TEST_HAS_NO_EXCEPTIONS
try {
std::format(fmt, args...);
# ifndef TEST_HAS_NO_LOCALIZATION
if constexpr (std::same_as<CharT, char>)
std::cerr << "\nFormat string " << fmt << "\nDidn't throw an exception.\n";
# endif
assert(false);
} catch (const std::format_error& e) {
if constexpr (std::same_as<CharT, char>)
# if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_LOCALIZATION)
if (e.what() != what)
std::cerr << "\nFormat string " << fmt << "\nExpected exception " << what << "\nActual exception "
<< e.what() << '\n';
# endif
LIBCPP_ASSERT(e.what() == what);
return;
}
assert(false);
#endif
(void)what;
(void)fmt;
(void)sizeof...(args);
auto test_exception = []<class CharT, class... Args>(std::string_view, std::basic_string_view<CharT>, const Args&...) {
// After P2216 most exceptions thrown by std::format become ill-formed.
// Therefore this tests does nothing.
// A basic ill-formed test is done in format.verify.cpp
// The exceptions are tested by other functions that don't use the basic-format-string as fmt argument.
};
int main(int, char**) {

View File

@ -0,0 +1,90 @@
//===----------------------------------------------------------------------===//
// 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
// TODO FMT Evaluate gcc-11 status
// UNSUPPORTED: gcc-11
// Basic test to validate ill-formed code is properly detected.
// <format>
// template<class... Args>
// string format(format-string<Args...> fmt, const Args&... args);
// template<class... Args>
// wstring format(wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include "test_macros.h"
// clang-format off
void f() {
std::format("{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format("}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format("{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format("{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format("{:-}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format("{:#}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format("{:L}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format("{0:{0}}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format("{:.42d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format("{:d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
std::format(L"{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(L"}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(L"{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(L"{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(L"{:-}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(L"{:#}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(L"{:L}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(L"{0:{0}}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(L"{:.42d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format(L"{:d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#endif
}

View File

@ -17,10 +17,10 @@
// template<class Out, class... Args>
// Out format_to(Out out, const locale& loc,
// string_view fmt, const Args&... args);
// format-string<Args...> fmt, const Args&... args);
// template<class Out, class... Args>
// Out format_to(Out out, const locale& loc,
// wstring_view fmt, const Args&... args);
// wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include <algorithm>
@ -60,23 +60,11 @@ auto test = []<string_literal fmt, class CharT, class... Args>(std::basic_string
}
};
auto test_exception = []<class CharT, class... Args>(std::string_view what, std::basic_string_view<CharT> fmt,
const Args&... args) {
#ifndef TEST_HAS_NO_EXCEPTIONS
try {
std::basic_string<CharT> out;
std::format_to(std::back_inserter(out), std::locale(), fmt, args...);
assert(false);
} catch (const std::format_error& e) {
LIBCPP_ASSERT(e.what() == what);
return;
}
assert(false);
#else
(void)what;
(void)fmt;
(void)sizeof...(args);
#endif
auto test_exception = []<class CharT, class... Args>(std::string_view, std::basic_string_view<CharT>, const Args&...) {
// After P2216 most exceptions thrown by std::format_to become ill-formed.
// Therefore this tests does nothing.
// A basic ill-formed test is done in format_to.locale.verify.cpp
// The exceptions are tested by other functions that don't use the basic-format-string as fmt argument.
};
int main(int, char**) {

View File

@ -0,0 +1,99 @@
//===----------------------------------------------------------------------===//
// 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: no-localization
// UNSUPPORTED: libcpp-has-no-incomplete-format
// TODO FMT Evaluate gcc-11 status
// UNSUPPORTED: gcc-11
// Basic test to validate ill-formed code is properly detected.
// <format>
// template<class Out, class... Args>
// Out format_to(Out out, const locale& loc,
// format-string<Args...> fmt, const Args&... args);
// template<class Out, class... Args>
// Out format_to(Out out, const locale& loc,
// wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include <locale>
#include "test_macros.h"
extern char* out;
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
extern wchar_t* wout;
#endif
// clang-format off
void f() {
std::format_to(out, std::locale(), "{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, std::locale(), "}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, std::locale(), "{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, std::locale(), "{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, std::locale(), "{:-}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, std::locale(), "{:#}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, std::locale(), "{:L}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, std::locale(), "{0:{0}}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, std::locale(), "{:.42d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, std::locale(), "{:d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
std::format_to(wout, std::locale(), L"{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, std::locale(), L"}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, std::locale(), L"{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, std::locale(), L"{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, std::locale(), L"{:-}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, std::locale(), L"{:#}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, std::locale(), L"{:L}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, std::locale(), L"{0:{0}}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, std::locale(), L"{:.42d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, std::locale(), L"{:d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#endif
}

View File

@ -15,9 +15,9 @@
// <format>
// template<class Out, class... Args>
// Out format_to(Out out, string_view fmt, const Args&... args);
// Out format_to(Out out, format-string<Args...> fmt, const Args&... args);
// template<class Out, class... Args>
// Out format_to(Out out, wstring_view fmt, const Args&... args);
// Out format_to(Out out, wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include <algorithm>
@ -57,23 +57,11 @@ auto test = []<string_literal fmt, class CharT, class... Args>(std::basic_string
}
};
auto test_exception = []<class CharT, class... Args>(std::string_view what, std::basic_string_view<CharT> fmt,
const Args&... args) {
#ifndef TEST_HAS_NO_EXCEPTIONS
try {
std::basic_string<CharT> out;
std::format_to(std::back_inserter(out), fmt, args...);
assert(false);
} catch (const std::format_error& e) {
LIBCPP_ASSERT(e.what() == what);
return;
}
assert(false);
#else
(void)what;
(void)fmt;
(void)sizeof...(args);
#endif
auto test_exception = []<class CharT, class... Args>(std::string_view, std::basic_string_view<CharT>, const Args&...) {
// After P2216 most exceptions thrown by std::format become ill-formed.
// Therefore this tests does nothing.
// A basic ill-formed test is done in format.verify.cpp
// The exceptions are tested by other functions that don't use the basic-format-string as fmt argument.
};
int main(int, char**) {

View File

@ -0,0 +1,95 @@
//===----------------------------------------------------------------------===//
// 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
// TODO FMT Evaluate gcc-11 status
// UNSUPPORTED: gcc-11
// <format>
// Basic test to validate ill-formed code is properly detected.
// template<class Out, class... Args>
// Out format_to(Out out, format-string<Args...> fmt, const Args&... args);
// template<class Out, class... Args>
// Out format_to(Out out, wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include "test_macros.h"
extern char* out;
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
extern wchar_t* wout;
#endif
// clang-format off
void f() {
std::format_to(out, "{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, "}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, "{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, "{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, "{:-}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, "{:#}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, "{:L}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, "{0:{0}}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, "{:.42d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(out, "{:d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
std::format_to(wout, L"{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, L"}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, L"{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, L"{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, L"{:-}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, L"{:#}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, L"{:L}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, L"{0:{0}}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, L"{:.42d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to(wout, L"{:d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#endif
}

View File

@ -17,11 +17,11 @@
// template<class Out, class... Args>
// format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
// const locale& loc, string_view fmt,
// const locale& loc, format-string<Args...> fmt,
// const Args&... args);
// template<class Out, class... Args>
// format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
// const locale& loc, wstring_view fmt,
// const locale& loc, wformat-string<Args...> fmt,
// const Args&... args);
#include <format>
@ -98,23 +98,11 @@ auto test = []<string_literal fmt, class CharT, class... Args>(std::basic_string
}
};
auto test_exception = []<class CharT, class... Args>(std::string_view what, std::basic_string_view<CharT> fmt,
const Args&... args) {
#ifndef TEST_HAS_NO_EXCEPTIONS
try {
std::basic_string<CharT> out;
std::format_to_n(std::back_inserter(out), 0, std::locale(), fmt, args...);
assert(false);
} catch (const std::format_error& e) {
LIBCPP_ASSERT(e.what() == what);
return;
}
assert(false);
#else
(void)what;
(void)fmt;
(void)sizeof...(args);
#endif
auto test_exception = []<class CharT, class... Args>(std::string_view, std::basic_string_view<CharT>, const Args&...) {
// After P2216 most exceptions thrown by std::format_to_n become ill-formed.
// Therefore this tests does nothing.
// A basic ill-formed test is done in format_to_n.locale.verify.cpp
// The exceptions are tested by other functions that don't use the basic-format-string as fmt argument.
};
int main(int, char**) {

View File

@ -0,0 +1,101 @@
//===----------------------------------------------------------------------===//
// 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: no-localization
// UNSUPPORTED: libcpp-has-no-incomplete-format
// TODO FMT Evaluate gcc-11 status
// UNSUPPORTED: gcc-11
// Basic test to validate ill-formed code is properly detected.
// <format>
// template<class Out, class... Args>
// format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
// const locale& loc, format-string<Args...> fmt,
// const Args&... args);
// template<class Out, class... Args>
// format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
// const locale& loc, wformat-string<Args...> fmt,
// const Args&... args);
#include <format>
#include <locale>
#include "test_macros.h"
extern char* out;
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
extern wchar_t* wout;
#endif
// clang-format off
void f() {
std::format_to_n(out, 42, std::locale(), "{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, std::locale(), "}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, std::locale(), "{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, std::locale(), "{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, std::locale(), "{:-}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, std::locale(), "{:#}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, std::locale(), "{:L}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, std::locale(), "{0:{0}}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, std::locale(), "{:.42d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, std::locale(), "{:d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
std::format_to_n(wout, 42, std::locale(), L"{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, std::locale(), L"}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, std::locale(), L"{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, std::locale(), L"{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, std::locale(), L"{:-}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, std::locale(), L"{:#}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, std::locale(), L"{:L}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, std::locale(), L"{0:{0}}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, std::locale(), L"{:.42d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, std::locale(), L"{:d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#endif
}

View File

@ -16,10 +16,10 @@
// template<class Out, class... Args>
// format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
// string_view fmt, const Args&... args);
// format-string<Args...> fmt, const Args&... args);
// template<class Out, class... Args>
// format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
// wstring_view fmt, const Args&... args);
// wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include <algorithm>
@ -91,23 +91,11 @@ auto test = []<string_literal fmt, class CharT, class... Args>(std::basic_string
}
};
auto test_exception = []<class CharT, class... Args>(std::string_view what, std::basic_string_view<CharT> fmt,
const Args&... args) {
#ifndef TEST_HAS_NO_EXCEPTIONS
try {
std::basic_string<CharT> out;
std::format_to_n(std::back_inserter(out), 0, fmt, args...);
assert(false);
} catch (const std::format_error& e) {
LIBCPP_ASSERT(e.what() == what);
return;
}
assert(false);
#else
(void)what;
(void)fmt;
(void)sizeof...(args);
#endif
auto test_exception = []<class CharT, class... Args>(std::string_view, std::basic_string_view<CharT>, const Args&...) {
// After P2216 most exceptions thrown by std::format_to_n become ill-formed.
// Therefore this tests does nothing.
// A basic ill-formed test is done in format_to_n.verify.cpp
// The exceptions are tested by other functions that don't use the basic-format-string as fmt argument.
};
int main(int, char**) {

View File

@ -0,0 +1,97 @@
//===----------------------------------------------------------------------===//
// 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
// TODO FMT Evaluate gcc-11 status
// UNSUPPORTED: gcc-11
// Basic test to validate ill-formed code is properly detected.
// <format>
// template<class Out, class... Args>
// format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
// format-string<Args...> fmt, const Args&... args);
// template<class Out, class... Args>
// format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
// wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include "test_macros.h"
extern char* out;
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
extern wchar_t* wout;
#endif
// clang-format off
void f() {
std::format_to_n(out, 42, "{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, "}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, "{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, "{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, "{:-}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, "{:#}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, "{:L}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, "{0:{0}}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, "{:.42d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(out, 42, "{:d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
std::format_to_n(wout, 42, L"{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, L"}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, L"{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, L"{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, L"{:-}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, L"{:#}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, L"{:L}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, L"{0:{0}}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, L"{:.42d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::format_to_n(wout, 42, L"{:d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#endif
}

View File

@ -17,10 +17,10 @@
// template<class... Args>
// size_t formatted_size(const locale& loc,
// string_view fmt, const Args&... args);
// format-string<Args...> fmt, const Args&... args);
// template<class... Args>
// size_t formatted_size(const locale& loc,
// wstring_view fmt, const Args&... args);
// wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include <cassert>
@ -36,22 +36,11 @@ auto test = []<string_literal fmt, class CharT, class... Args>(std::basic_string
assert(size == expected.size());
};
auto test_exception = []<class CharT, class... Args>(std::string_view what, std::basic_string_view<CharT> fmt,
const Args&... args) {
#ifndef TEST_HAS_NO_EXCEPTIONS
try {
std::formatted_size(std::locale(), fmt, args...);
assert(false);
} catch (const std::format_error& e) {
LIBCPP_ASSERT(e.what() == what);
return;
}
assert(false);
#else
(void)what;
(void)fmt;
(void)sizeof...(args);
#endif
auto test_exception = []<class CharT, class... Args>(std::string_view, std::basic_string_view<CharT>, const Args&...) {
// After P2216 most exceptions thrown by std::formatted_siz3 become ill-formed.
// Therefore this tests does nothing.
// A basic ill-formed test is done in formatted_size.locale.verify.cpp
// The exceptions are tested by other functions that don't use the basic-format-string as fmt argument.
};
int main(int, char**) {

View File

@ -0,0 +1,94 @@
//===----------------------------------------------------------------------===//
// 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: no-localization
// UNSUPPORTED: libcpp-has-no-incomplete-format
// TODO FMT Evaluate gcc-11 status
// UNSUPPORTED: gcc-11
// Basic test to validate ill-formed code is properly detected.
// <format>
// template<class... Args>
// size_t formatted_size(const locale& loc,
// format-string<Args...> fmt, const Args&... args);
// template<class... Args>
// size_t formatted_size(const locale& loc,
// wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include <locale>
#include "test_macros.h"
// clang-format off
void f() {
std::formatted_size(std::locale(), "{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), "}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), "{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), "{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), "{:-}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), "{:#}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), "{:L}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), "{0:{0}}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), "{:.42d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), "{:d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
std::formatted_size(std::locale(), L"{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), L"}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), L"{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), L"{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), L"{:-}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), L"{:#}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), L"{:L}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), L"{0:{0}}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), L"{:.42d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(std::locale(), L"{:d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#endif
}

View File

@ -15,9 +15,9 @@
// <format>
// template<class... Args>
// size_t formatted_size(string_view fmt, const Args&... args);
// size_t formatted_size(format-string<Args...> fmt, const Args&... args);
// template<class... Args>
// size_t formatted_size(wstring_view fmt, const Args&... args);
// size_t formatted_size(wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include <cassert>
@ -33,22 +33,11 @@ auto test = []<string_literal fmt, class CharT, class... Args>(std::basic_string
assert(size == expected.size());
};
auto test_exception = []<class CharT, class... Args>(std::string_view what, std::basic_string_view<CharT> fmt,
const Args&... args) {
#ifndef TEST_HAS_NO_EXCEPTIONS
try {
std::formatted_size(fmt, args...);
assert(false);
} catch (const std::format_error& e) {
LIBCPP_ASSERT(e.what() == what);
return;
}
assert(false);
#else
(void)what;
(void)fmt;
(void)sizeof...(args);
#endif
auto test_exception = []<class CharT, class... Args>(std::string_view, std::basic_string_view<CharT>, const Args&...) {
// After P2216 most exceptions thrown by std::formatted_siz3 become ill-formed.
// Therefore this tests does nothing.
// A basic ill-formed test is done in formatted_size.verify.cpp
// The exceptions are tested by other functions that don't use the basic-format-string as fmt argument.
};
int main(int, char**) {

View File

@ -0,0 +1,90 @@
//===----------------------------------------------------------------------===//
// 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
// TODO FMT Evaluate gcc-11 status
// UNSUPPORTED: gcc-11
// Basic test to validate ill-formed code is properly detected.
// <format>
// template<class... Args>
// size_t formatted_size(format-string<Args...> fmt, const Args&... args);
// template<class... Args>
// size_t formatted_size(wformat-string<Args...> fmt, const Args&... args);
#include <format>
#include "test_macros.h"
// clang-format off
void f() {
std::formatted_size("{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size("}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size("{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size("{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size("{:-}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size("{:#}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size("{:L}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size("{0:{0}}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size("{:.42d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size("{:d}", "Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
std::formatted_size(L"{"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(L"}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(L"{}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(L"{0}"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(L"{:-}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(L"{:#}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(L"{:L}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(L"{0:{0}}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(L"{:.42d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
std::formatted_size(L"{:d}", L"Forty-two"); // expected-error-re{{call to consteval function '{{.*}}' is not a constant expression}}
// expected-note@*:* {{non-constexpr function '__throw_format_error' cannot be used in a constant expression}}
#endif
}