forked from OSchip/llvm-project
[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:
parent
338fd211e7
commit
aed5ddf8d0
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
-----------
|
||||
|
||||
|
|
|
@ -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","",""
|
||||
|
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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**) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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**) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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**) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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**) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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**) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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**) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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**) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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**) {
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue