[libc++][format] Add __format_arg_store.
This implements the struct `__format_arg_store` and its dependencies: * the class basic_format_arg, * the class basic_format_args, * the class basic_format_context, * the function make_format_args, * the function wmake_format_args, * the function visit_format_arg, * several Standard required typedefs. The following parts will be implemented in a later patch: * the child class `basic_format_arg::handle`, * the function `basic_format_arg::basic_format_arg(const T* p)`. The following extension has been implemented: * the class basic_format_arg supports `__[u]int128_t` on platform where libc++ supports 128 bit integrals. Implements parts of: * P0645 Text Formatting Completes: * LWG3371 visit_format_arg and make_format_args are not hidden friends * LWG3542 basic_format_arg mishandles basic_string_view with custom traits Note https://mordante.github.io/blog/2021/06/05/format.html gives a bit more information about the goals and non-goals of this initial patch series. Reviewed By: #libc, ldionne, vitaut Differential Revision: https://reviews.llvm.org/D103357
This commit is contained in:
@@ -275,7 +275,7 @@
|
||||
"`3364 <https://wg21.link/LWG3364>`__","Initialize data members of ranges and their iterators","Prague","",""
|
||||
"`3367 <https://wg21.link/LWG3367>`__","Integer-class conversions should not throw","Prague","",""
|
||||
"`3369 <https://wg21.link/LWG3369>`__","``span``\ 's deduction-guide for built-in arrays doesn't work","Prague","",""
|
||||
"`3371 <https://wg21.link/LWG3371>`__","``visit_format_arg``\ and ``make_format_args``\ are not hidden friends","Prague","",""
|
||||
"`3371 <https://wg21.link/LWG3371>`__","``visit_format_arg``\ and ``make_format_args``\ are not hidden friends","Prague","|Complete|","14.0"
|
||||
"`3372 <https://wg21.link/LWG3372>`__","``vformat_to``\ should not try to deduce ``Out``\ twice","Prague","",""
|
||||
"`3373 <https://wg21.link/LWG3373>`__","``{to,from}_chars_result``\ and ``format_to_n_result``\ need the ""we really mean what we say"" wording","Prague","",""
|
||||
"`3374 <https://wg21.link/LWG3374>`__","P0653 + P1006 should have made the other ``std::to_address``\ overload ``constexpr``\ ","Prague","|Complete|","12.0"
|
||||
|
||||
|
@@ -39,10 +39,6 @@ Misc. Items and TODOs
|
||||
(Please mark all Format-related TODO comments with the string ``TODO FMT``, so we
|
||||
can find them easily.)
|
||||
|
||||
* C++23 may break the ABI with `P2216 <https://wg21.link/P2216>`_.
|
||||
This ABI break may be backported to C++20. Therefore the library will not
|
||||
be available on platforms where the ABI break is an issue.
|
||||
|
||||
|
||||
Paper and Issue Status
|
||||
======================
|
||||
|
||||
@@ -128,7 +128,11 @@ set(files
|
||||
__config
|
||||
__debug
|
||||
__errc
|
||||
__format/format_arg.h
|
||||
__format/format_args.h
|
||||
__format/format_context.h
|
||||
__format/format_error.h
|
||||
__format/format_fwd.h
|
||||
__format/format_parse_context.h
|
||||
__function_like.h
|
||||
__functional_base
|
||||
|
||||
@@ -139,9 +139,9 @@
|
||||
// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore
|
||||
|
||||
// This controls the availability of the C++20 format library.
|
||||
// The library is in development and not ABI stable yet. Currently
|
||||
// P2216 is aiming to be retroactively accepted in C++20. This paper
|
||||
// contains ABI breaking changes.
|
||||
// The library is in development and not ABI stable yet. P2216 is
|
||||
// retroactively accepted in C++20. This paper contains ABI breaking
|
||||
// changes.
|
||||
# define _LIBCPP_AVAILABILITY_FORMAT
|
||||
// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format
|
||||
|
||||
@@ -238,9 +238,9 @@
|
||||
# endif
|
||||
|
||||
// This controls the availability of the C++20 format library.
|
||||
// The library is in development and not ABI stable yet. Currently
|
||||
// P2216 is aiming to be retroactively accepted in C++20. This paper
|
||||
// contains ABI breaking changes.
|
||||
// The library is in development and not ABI stable yet. P2216 is
|
||||
// retroactively accepted in C++20. This paper contains ABI breaking
|
||||
// changes.
|
||||
# define _LIBCPP_AVAILABILITY_FORMAT \
|
||||
__attribute__((unavailable))
|
||||
# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format
|
||||
|
||||
256
libcxx/include/__format/format_arg.h
Normal file
256
libcxx/include/__format/format_arg.h
Normal file
@@ -0,0 +1,256 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___FORMAT_FORMAT_ARG_H
|
||||
#define _LIBCPP___FORMAT_FORMAT_ARG_H
|
||||
|
||||
#include <__config>
|
||||
#include <__format/format_error.h>
|
||||
#include <__format/format_fwd.h>
|
||||
#include <__functional_base>
|
||||
#include <__variant/monostate.h>
|
||||
#include <concepts>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
|
||||
// TODO FMT Remove this once we require compilers with proper C++20 support.
|
||||
// If the compiler has no concepts support, the format header will be disabled.
|
||||
// Without concepts support enable_if needs to be used and that too much effort
|
||||
// to support compilers with partial C++20 support.
|
||||
#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
namespace __format {
|
||||
/** The type stored in @ref basic_format_arg. */
|
||||
enum class _LIBCPP_ENUM_VIS __arg_t : uint8_t {
|
||||
__none,
|
||||
__bool,
|
||||
__char_type,
|
||||
__int,
|
||||
__long_long,
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
__i128,
|
||||
#endif
|
||||
__unsigned,
|
||||
__unsigned_long_long,
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
__u128,
|
||||
#endif
|
||||
__float,
|
||||
__double,
|
||||
__long_double,
|
||||
__const_char_type_ptr,
|
||||
__string_view,
|
||||
__ptr
|
||||
};
|
||||
} // namespace __format
|
||||
|
||||
template <class _Visitor, class _Context>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT decltype(auto)
|
||||
visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
|
||||
switch (__arg.__type_) {
|
||||
case __format::__arg_t::__none:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), monostate{});
|
||||
case __format::__arg_t::__bool:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__bool);
|
||||
case __format::__arg_t::__char_type:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__char_type);
|
||||
case __format::__arg_t::__int:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__int);
|
||||
case __format::__arg_t::__long_long:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__long_long);
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
case __format::__arg_t::__i128:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__i128);
|
||||
#endif
|
||||
case __format::__arg_t::__unsigned:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__unsigned);
|
||||
case __format::__arg_t::__unsigned_long_long:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis),
|
||||
__arg.__unsigned_long_long);
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
case __format::__arg_t::__u128:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__u128);
|
||||
#endif
|
||||
case __format::__arg_t::__float:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__float);
|
||||
case __format::__arg_t::__double:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__double);
|
||||
case __format::__arg_t::__long_double:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__long_double);
|
||||
case __format::__arg_t::__const_char_type_ptr:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis),
|
||||
__arg.__const_char_type_ptr);
|
||||
case __format::__arg_t::__string_view:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__string_view);
|
||||
case __format::__arg_t::__ptr:
|
||||
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__ptr);
|
||||
}
|
||||
_LIBCPP_UNREACHABLE();
|
||||
}
|
||||
|
||||
template <class _Context>
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_arg {
|
||||
public:
|
||||
// TODO FMT Define the handle class.
|
||||
class handle;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI basic_format_arg() noexcept
|
||||
: __type_{__format::__arg_t::__none} {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI explicit operator bool() const noexcept {
|
||||
return __type_ != __format::__arg_t::__none;
|
||||
}
|
||||
|
||||
private:
|
||||
using char_type = typename _Context::char_type;
|
||||
|
||||
// TODO FMT Implement constrain [format.arg]/4
|
||||
// Constraints: The template specialization
|
||||
// typename Context::template formatter_type<T>
|
||||
// meets the Formatter requirements ([formatter.requirements]). The extent
|
||||
// to which an implementation determines that the specialization meets the
|
||||
// Formatter requirements is unspecified, except that as a minimum the
|
||||
// expression
|
||||
// typename Context::template formatter_type<T>()
|
||||
// .format(declval<const T&>(), declval<Context&>())
|
||||
// shall be well-formed when treated as an unevaluated operand.
|
||||
|
||||
template <class _Ctx, class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
_LIBCPP_AVAILABILITY_FORMAT friend __format_arg_store<_Ctx, _Args...>
|
||||
_VSTD::make_format_args(const _Args&...);
|
||||
|
||||
template <class _Visitor, class _Ctx>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT friend decltype(auto)
|
||||
_VSTD::visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx> __arg);
|
||||
|
||||
union {
|
||||
bool __bool;
|
||||
char_type __char_type;
|
||||
int __int;
|
||||
unsigned __unsigned;
|
||||
long long __long_long;
|
||||
unsigned long long __unsigned_long_long;
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
__int128_t __i128;
|
||||
__uint128_t __u128;
|
||||
#endif
|
||||
float __float;
|
||||
double __double;
|
||||
long double __long_double;
|
||||
const char_type* __const_char_type_ptr;
|
||||
basic_string_view<char_type> __string_view;
|
||||
const void* __ptr;
|
||||
// TODO FMT Add the handle.
|
||||
};
|
||||
__format::__arg_t __type_;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(bool __v) noexcept
|
||||
: __bool(__v), __type_(__format::__arg_t::__bool) {}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(_Tp __v) noexcept
|
||||
requires(same_as<_Tp, char_type> ||
|
||||
(same_as<_Tp, char> && same_as<char_type, wchar_t>))
|
||||
: __char_type(__v), __type_(__format::__arg_t::__char_type) {}
|
||||
|
||||
template <__libcpp_signed_integer _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(_Tp __v) noexcept {
|
||||
if constexpr (sizeof(_Tp) <= sizeof(int)) {
|
||||
__int = static_cast<int>(__v);
|
||||
__type_ = __format::__arg_t::__int;
|
||||
} else if constexpr (sizeof(_Tp) <= sizeof(long long)) {
|
||||
__long_long = static_cast<long long>(__v);
|
||||
__type_ = __format::__arg_t::__long_long;
|
||||
}
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
else if constexpr (sizeof(_Tp) == sizeof(__int128_t)) {
|
||||
__i128 = __v;
|
||||
__type_ = __format::__arg_t::__i128;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
static_assert(sizeof(_Tp) == 0, "An unsupported signed integer was used");
|
||||
}
|
||||
|
||||
template <__libcpp_unsigned_integer _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(_Tp __v) noexcept {
|
||||
if constexpr (sizeof(_Tp) <= sizeof(unsigned)) {
|
||||
__unsigned = static_cast<unsigned>(__v);
|
||||
__type_ = __format::__arg_t::__unsigned;
|
||||
} else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long)) {
|
||||
__unsigned_long_long = static_cast<unsigned long long>(__v);
|
||||
__type_ = __format::__arg_t::__unsigned_long_long;
|
||||
}
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
else if constexpr (sizeof(_Tp) == sizeof(__int128_t)) {
|
||||
__u128 = __v;
|
||||
__type_ = __format::__arg_t::__u128;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
static_assert(sizeof(_Tp) == 0,
|
||||
"An unsupported unsigned integer was used");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(float __v) noexcept
|
||||
: __float(__v), __type_(__format::__arg_t::__float) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(double __v) noexcept
|
||||
: __double(__v), __type_(__format::__arg_t::__double) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(long double __v) noexcept
|
||||
: __long_double(__v), __type_(__format::__arg_t::__long_double) {}
|
||||
|
||||
// Note not a 'noexcept' function.
|
||||
_LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(const char_type* __s)
|
||||
: __const_char_type_ptr(__s),
|
||||
__type_(__format::__arg_t::__const_char_type_ptr) {
|
||||
_LIBCPP_ASSERT(__s, "Used a nullptr argument to initialize a C-string");
|
||||
}
|
||||
|
||||
template <class _Traits>
|
||||
_LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(
|
||||
basic_string_view<char_type, _Traits> __s) noexcept
|
||||
: __string_view{__s.data(), __s.size()},
|
||||
__type_(__format::__arg_t::__string_view) {}
|
||||
|
||||
template <class _Traits, class _Allocator>
|
||||
_LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(
|
||||
const basic_string<char_type, _Traits, _Allocator>& __s) noexcept
|
||||
: __string_view{__s.data(), __s.size()},
|
||||
__type_(__format::__arg_t::__string_view) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
explicit basic_format_arg(nullptr_t) noexcept
|
||||
: __ptr(nullptr), __type_(__format::__arg_t::__ptr) {}
|
||||
|
||||
// TODO FMT Implement the _Tp* constructor.
|
||||
};
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
#endif //_LIBCPP_STD_VER > 17
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___FORMAT_FORMAT_ARG_H
|
||||
71
libcxx/include/__format/format_args.h
Normal file
71
libcxx/include/__format/format_args.h
Normal file
@@ -0,0 +1,71 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___FORMAT_FORMAT_ARGS_H
|
||||
#define _LIBCPP___FORMAT_FORMAT_ARGS_H
|
||||
|
||||
#include <__availability>
|
||||
#include <__config>
|
||||
#include <__format/format_fwd.h>
|
||||
#include <cstddef>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
|
||||
// TODO FMT Remove this once we require compilers with proper C++20 support.
|
||||
// If the compiler has no concepts support, the format header will be disabled.
|
||||
// Without concepts support enable_if needs to be used and that too much effort
|
||||
// to support compilers with partial C++20 support.
|
||||
#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
template <class _Context>
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_args {
|
||||
public:
|
||||
// TODO FMT Implement [format.args]/5
|
||||
// [Note 1: Implementations are encouraged to optimize the representation of
|
||||
// basic_format_args for small number of formatting arguments by storing
|
||||
// indices of type alternatives separately from values and packing the
|
||||
// former. - end note]
|
||||
// Note: Change __format_arg_store to use a built-in array.
|
||||
_LIBCPP_HIDE_FROM_ABI basic_format_args() noexcept = default;
|
||||
|
||||
template <class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI basic_format_args(
|
||||
const __format_arg_store<_Context, _Args...>& __store) noexcept
|
||||
: __size_(sizeof...(_Args)), __data_(__store.__args.data()) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
basic_format_arg<_Context> get(size_t __id) const noexcept {
|
||||
return __id < __size_ ? __data_[__id] : basic_format_arg<_Context>{};
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI size_t __size() const noexcept { return __size_; }
|
||||
|
||||
private:
|
||||
size_t __size_{0};
|
||||
const basic_format_arg<_Context>* __data_{nullptr};
|
||||
};
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
#endif //_LIBCPP_STD_VER > 17
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___FORMAT_FORMAT_ARGS_H
|
||||
160
libcxx/include/__format/format_context.h
Normal file
160
libcxx/include/__format/format_context.h
Normal file
@@ -0,0 +1,160 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___FORMAT_FORMAT_CONTEXT_H
|
||||
#define _LIBCPP___FORMAT_FORMAT_CONTEXT_H
|
||||
|
||||
#include <__availability>
|
||||
#include <__config>
|
||||
#include <__format/format_args.h>
|
||||
#include <__format/format_fwd.h>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <concepts>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
||||
#include <locale>
|
||||
#include <optional>
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
|
||||
// TODO FMT Remove this once we require compilers with proper C++20 support.
|
||||
// If the compiler has no concepts support, the format header will be disabled.
|
||||
// Without concepts support enable_if needs to be used and that too much effort
|
||||
// to support compilers with partial C++20 support.
|
||||
#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
template <class _OutIt, class _CharT>
|
||||
requires output_iterator<_OutIt, const _CharT&>
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context;
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
||||
/**
|
||||
* Helper to create a basic_format_context.
|
||||
*
|
||||
* This is needed since the constructor is private.
|
||||
*/
|
||||
template <class _OutIt, class _CharT>
|
||||
_LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT>
|
||||
__format_context_create(
|
||||
_OutIt __out_it,
|
||||
basic_format_args<basic_format_context<_OutIt, _CharT>> __args,
|
||||
optional<_VSTD::locale>&& __loc = nullopt) {
|
||||
return _VSTD::basic_format_context(_VSTD::move(__out_it), __args,
|
||||
_VSTD::move(__loc));
|
||||
}
|
||||
#else
|
||||
template <class _OutIt, class _CharT>
|
||||
_LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT>
|
||||
__format_context_create(
|
||||
_OutIt __out_it,
|
||||
basic_format_args<basic_format_context<_OutIt, _CharT>> __args) {
|
||||
return _VSTD::basic_format_context(_VSTD::move(__out_it), __args);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class _OutIt, class _CharT>
|
||||
requires output_iterator<_OutIt, const _CharT&>
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context {
|
||||
public:
|
||||
using iterator = _OutIt;
|
||||
using char_type = _CharT;
|
||||
template <class _Tp>
|
||||
using formatter_type = formatter<_Tp, _CharT>;
|
||||
|
||||
basic_format_context(const basic_format_context&) = delete;
|
||||
basic_format_context& operator=(const basic_format_context&) = delete;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context>
|
||||
arg(size_t __id) const {
|
||||
return __args_.get(__id);
|
||||
}
|
||||
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
||||
_LIBCPP_HIDE_FROM_ABI _VSTD::locale locale() {
|
||||
if (!__loc_)
|
||||
__loc_ = _VSTD::locale{};
|
||||
return *__loc_;
|
||||
}
|
||||
#endif
|
||||
_LIBCPP_HIDE_FROM_ABI iterator out() { return __out_it_; }
|
||||
_LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = __it; }
|
||||
|
||||
private:
|
||||
iterator __out_it_;
|
||||
basic_format_args<basic_format_context> __args_;
|
||||
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
||||
|
||||
// The Standard doesn't specify how the locale is stored.
|
||||
// [format.context]/6
|
||||
// std::locale locale();
|
||||
// Returns: The locale passed to the formatting function if the latter
|
||||
// takes one, and std::locale() otherwise.
|
||||
// This is done by storing the locale of the constructor in this optional. If
|
||||
// locale() is called and the optional has no value the value will be created.
|
||||
// This allows the implementation to lazily create the locale.
|
||||
// TODO FMT Validate whether lazy creation is the best solution.
|
||||
optional<_VSTD::locale> __loc_;
|
||||
|
||||
template <class __OutIt, class __CharT>
|
||||
friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT>
|
||||
_VSTD::__format_context_create(
|
||||
__OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>,
|
||||
optional<_VSTD::locale>&&);
|
||||
|
||||
// Note: the Standard doesn't specify the required constructors.
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
explicit basic_format_context(_OutIt __out_it,
|
||||
basic_format_args<basic_format_context> __args,
|
||||
optional<_VSTD::locale>&& __loc)
|
||||
: __out_it_(_VSTD::move(__out_it)), __args_(__args),
|
||||
__loc_(_VSTD::move(__loc)) {}
|
||||
#else
|
||||
template <class __OutIt, class __CharT>
|
||||
friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT>
|
||||
_VSTD::__format_context_create(
|
||||
__OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>);
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
explicit basic_format_context(_OutIt __out_it,
|
||||
basic_format_args<basic_format_context> __args)
|
||||
: __out_it_(_VSTD::move(__out_it)), __args_(__args) {}
|
||||
#endif
|
||||
};
|
||||
|
||||
// TODO FMT Implement [format.context]/4
|
||||
// [Note 1: For a given type charT, implementations are encouraged to provide a
|
||||
// single instantiation of basic_format_context for appending to
|
||||
// basic_string<charT>, vector<charT>, or any other container with contiguous
|
||||
// storage by wrapping those in temporary objects with a uniform interface
|
||||
// (such as a span<charT>) and polymorphic reallocation. - end note]
|
||||
|
||||
using format_context = basic_format_context<back_insert_iterator<string>, char>;
|
||||
using wformat_context =
|
||||
basic_format_context<back_insert_iterator<wstring>, wchar_t>;
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
#endif //_LIBCPP_STD_VER > 17
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___FORMAT_FORMAT_CONTEXT_H
|
||||
56
libcxx/include/__format/format_fwd.h
Normal file
56
libcxx/include/__format/format_fwd.h
Normal file
@@ -0,0 +1,56 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___FORMAT_FORMAT_FWD_H
|
||||
#define _LIBCPP___FORMAT_FORMAT_FWD_H
|
||||
|
||||
#include <__availability>
|
||||
#include <__config>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__utility/forward.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
|
||||
// TODO FMT Remove this once we require compilers with proper C++20 support.
|
||||
// If the compiler has no concepts support, the format header will be disabled.
|
||||
// Without concepts support enable_if needs to be used and that too much effort
|
||||
// to support compilers with partial C++20 support.
|
||||
#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
template <class _Context>
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_arg;
|
||||
|
||||
template <class _Context, class... _Args>
|
||||
struct _LIBCPP_TEMPLATE_VIS __format_arg_store;
|
||||
|
||||
template <class _Ctx, class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Ctx, _Args...>
|
||||
make_format_args(const _Args&...);
|
||||
|
||||
template <class _Tp, class _CharT = char>
|
||||
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter;
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
#endif //_LIBCPP_STD_VER > 17
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___FORMAT_FORMAT_FWD_H
|
||||
@@ -152,10 +152,28 @@ namespace std {
|
||||
#include <__concepts/swappable.h>
|
||||
#include <__concepts/totally_ordered.h>
|
||||
#include <__config>
|
||||
#include <type_traits>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
// Concept helpers for the internal type traits for the fundamental types.
|
||||
|
||||
template <class _Tp>
|
||||
concept __libcpp_unsigned_integer = __libcpp_is_unsigned_integer<_Tp>::value;
|
||||
template <class _Tp>
|
||||
concept __libcpp_signed_integer = __libcpp_is_signed_integer<_Tp>::value;
|
||||
template <class _Tp>
|
||||
concept __libcpp_floating_point = __libcpp_is_floating_point<_Tp>::value;
|
||||
|
||||
#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_CONCEPTS
|
||||
|
||||
@@ -13,6 +13,136 @@
|
||||
/*
|
||||
|
||||
namespace std {
|
||||
// [format.context], class template basic_format_context
|
||||
template<class Out, class charT>
|
||||
class basic_format_context {
|
||||
basic_format_args<basic_format_context> args_; // exposition only
|
||||
Out out_; // exposition only
|
||||
|
||||
public:
|
||||
using iterator = Out;
|
||||
using char_type = charT;
|
||||
template<class T> using formatter_type = formatter<T, charT>;
|
||||
|
||||
basic_format_arg<basic_format_context> arg(size_t id) const;
|
||||
std::locale locale();
|
||||
|
||||
iterator out();
|
||||
void advance_to(iterator it);
|
||||
};
|
||||
using format_context = basic_format_context<unspecified, char>;
|
||||
using wformat_context = basic_format_context<unspecified, wchar_t>;
|
||||
|
||||
// [format.args], class template basic_format_args
|
||||
template<class Context>
|
||||
class basic_format_args {
|
||||
size_t size_; // exposition only
|
||||
const basic_format_arg<Context>* data_; // exposition only
|
||||
|
||||
public:
|
||||
basic_format_args() noexcept;
|
||||
|
||||
template<class... Args>
|
||||
basic_format_args(const format-arg-store<Context, Args...>& store) noexcept;
|
||||
|
||||
basic_format_arg<Context> get(size_t i) const noexcept;
|
||||
};
|
||||
using format_args = basic_format_args<format_context>;
|
||||
using wformat_args = basic_format_args<wformat_context>;
|
||||
|
||||
|
||||
template<class Out, class charT>
|
||||
using format_args_t = basic_format_args<basic_format_context<Out, charT>>;
|
||||
|
||||
// [format.parse.ctx], class template basic_format_parse_context
|
||||
template<class charT>
|
||||
class basic_format_parse_context {
|
||||
public:
|
||||
using char_type = charT;
|
||||
using const_iterator = typename basic_string_view<charT>::const_iterator;
|
||||
using iterator = const_iterator;
|
||||
|
||||
private:
|
||||
iterator begin_; // exposition only
|
||||
iterator end_; // exposition only
|
||||
enum indexing { unknown, manual, automatic }; // exposition only
|
||||
indexing indexing_; // exposition only
|
||||
size_t next_arg_id_; // exposition only
|
||||
size_t num_args_; // exposition only
|
||||
|
||||
public:
|
||||
constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
|
||||
size_t num_args = 0) noexcept;
|
||||
basic_format_parse_context(const basic_format_parse_context&) = delete;
|
||||
basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
|
||||
|
||||
constexpr const_iterator begin() const noexcept;
|
||||
constexpr const_iterator end() const noexcept;
|
||||
constexpr void advance_to(const_iterator it);
|
||||
|
||||
constexpr size_t next_arg_id();
|
||||
constexpr void check_arg_id(size_t id);
|
||||
};
|
||||
using format_parse_context = basic_format_parse_context<char>;
|
||||
using wformat_parse_context = basic_format_parse_context<wchar_t>;
|
||||
|
||||
// [format.arguments], arguments
|
||||
// [format.arg], class template basic_format_arg
|
||||
template<class Context>
|
||||
class basic_format_arg {
|
||||
public:
|
||||
class handle;
|
||||
|
||||
private:
|
||||
using char_type = typename Context::char_type; // exposition only
|
||||
|
||||
variant<monostate, bool, char_type,
|
||||
int, unsigned int, long long int, unsigned long long int,
|
||||
float, double, long double,
|
||||
const char_type*, basic_string_view<char_type>,
|
||||
const void*, handle> value; // exposition only
|
||||
|
||||
template<class T> explicit basic_format_arg(const T& v) noexcept; // exposition only
|
||||
explicit basic_format_arg(float n) noexcept; // exposition only
|
||||
explicit basic_format_arg(double n) noexcept; // exposition only
|
||||
explicit basic_format_arg(long double n) noexcept; // exposition only
|
||||
explicit basic_format_arg(const char_type* s); // exposition only
|
||||
|
||||
template<class traits>
|
||||
explicit basic_format_arg(
|
||||
basic_string_view<char_type, traits> s) noexcept; // exposition only
|
||||
|
||||
template<class traits, class Allocator>
|
||||
explicit basic_format_arg(
|
||||
const basic_string<char_type, traits, Allocator>& s) noexcept; // exposition only
|
||||
|
||||
explicit basic_format_arg(nullptr_t) noexcept; // exposition only
|
||||
|
||||
template<class T>
|
||||
explicit basic_format_arg(const T* p) noexcept; // exposition only
|
||||
|
||||
public:
|
||||
basic_format_arg() noexcept;
|
||||
|
||||
explicit operator bool() const noexcept;
|
||||
};
|
||||
|
||||
template<class Visitor, class Context>
|
||||
see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
|
||||
|
||||
// [format.arg.store], class template format-arg-store
|
||||
template<class Context, class... Args>
|
||||
struct format-arg-store { // exposition only
|
||||
array<basic_format_arg<Context>, sizeof...(Args)> args;
|
||||
};
|
||||
|
||||
template<class Context = format_context, class... Args>
|
||||
format-arg-store<Context, Args...>
|
||||
make_format_args(const Args&... args);
|
||||
template<class... Args>
|
||||
format-arg-store<wformat_context, Args...>
|
||||
make_wformat_args(const Args&... args);
|
||||
|
||||
// [format.error], class format_error
|
||||
class format_error : public runtime_error {
|
||||
public:
|
||||
@@ -61,13 +191,61 @@ namespace std {
|
||||
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
|
||||
|
||||
#include <__config>
|
||||
#include <__format/format_arg.h>
|
||||
#include <__format/format_args.h>
|
||||
#include <__format/format_context.h>
|
||||
#include <__format/format_error.h>
|
||||
#include <__format/format_parse_context.h>
|
||||
#include <array>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
|
||||
// TODO FMT Remove this once we require compilers with proper C++20 support.
|
||||
// If the compiler has no concepts support, the format header will be disabled.
|
||||
// Without concepts support enable_if needs to be used and that too much effort
|
||||
// to support compilers with partial C++20 support.
|
||||
#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
// TODO FMT Evaluate which templates should be external templates. This
|
||||
// improves the efficiency of the header. However since the header is still
|
||||
// under heavy development and not all classes are stable it makes no sense
|
||||
// to do this optimization now.
|
||||
|
||||
using format_args = basic_format_args<format_context>;
|
||||
using wformat_args = basic_format_args<wformat_context>;
|
||||
|
||||
template <class _OutIt, class _CharT>
|
||||
using format_args_t = basic_format_args<basic_format_context<_OutIt, _CharT>>;
|
||||
|
||||
template <class _Context, class... _Args>
|
||||
struct _LIBCPP_TEMPLATE_VIS __format_arg_store {
|
||||
// TODO FMT Use a built-in array.
|
||||
array<basic_format_arg<_Context>, sizeof...(_Args)> __args;
|
||||
};
|
||||
|
||||
template <class _Context = format_context, class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
|
||||
make_format_args(const _Args&... __args) {
|
||||
return {basic_format_arg<_Context>(__args)...};
|
||||
}
|
||||
|
||||
template <class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...>
|
||||
make_wformat_args(const _Args&... __args) {
|
||||
return _VSTD::make_format_args<wformat_context>(__args...);
|
||||
}
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
#endif //_LIBCPP_STD_VER > 17
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
|
||||
|
||||
#endif // _LIBCPP_FORMAT
|
||||
|
||||
@@ -431,7 +431,15 @@ module std [system] {
|
||||
export *
|
||||
|
||||
module __format {
|
||||
module format_arg { private header "__format/format_arg.h" }
|
||||
module format_args { private header "__format/format_args.h" }
|
||||
module format_context {
|
||||
private header "__format/format_context.h"
|
||||
export optional
|
||||
export locale
|
||||
}
|
||||
module format_error { private header "__format/format_error.h" }
|
||||
module format_fwd { private header "__format/format_fwd.h" }
|
||||
module format_parse_context { private header "__format/format_parse_context.h" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -790,6 +790,7 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_integral_v
|
||||
#endif // __has_keyword(__is_integral)
|
||||
|
||||
// __libcpp_is_signed_integer, __libcpp_is_unsigned_integer
|
||||
// <concepts> implements __libcpp_signed_integer, __libcpp_unsigned_integer
|
||||
|
||||
// [basic.fundamental] defines five standard signed integer types;
|
||||
// __int128_t is an extended signed integer type.
|
||||
@@ -817,6 +818,7 @@ template <> struct __libcpp_is_unsigned_integer<__uint128_t> : public tru
|
||||
#endif
|
||||
|
||||
// is_floating_point
|
||||
// <concepts> implements __libcpp_floating_point
|
||||
|
||||
template <class _Tp> struct __libcpp_is_floating_point : public false_type {};
|
||||
template <> struct __libcpp_is_floating_point<float> : public true_type {};
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: modules-build
|
||||
|
||||
// WARNING: This test was generated by 'generate_private_header_tests.py'
|
||||
// and should not be edited manually.
|
||||
|
||||
// expected-error@*:* {{use of private header from outside its module: '__format/format_arg.h'}}
|
||||
#include <__format/format_arg.h>
|
||||
@@ -0,0 +1,16 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: modules-build
|
||||
|
||||
// WARNING: This test was generated by 'generate_private_header_tests.py'
|
||||
// and should not be edited manually.
|
||||
|
||||
// expected-error@*:* {{use of private header from outside its module: '__format/format_args.h'}}
|
||||
#include <__format/format_args.h>
|
||||
@@ -0,0 +1,16 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: modules-build
|
||||
|
||||
// WARNING: This test was generated by 'generate_private_header_tests.py'
|
||||
// and should not be edited manually.
|
||||
|
||||
// expected-error@*:* {{use of private header from outside its module: '__format/format_context.h'}}
|
||||
#include <__format/format_context.h>
|
||||
@@ -0,0 +1,16 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: modules-build
|
||||
|
||||
// WARNING: This test was generated by 'generate_private_header_tests.py'
|
||||
// and should not be edited manually.
|
||||
|
||||
// expected-error@*:* {{use of private header from outside its module: '__format/format_fwd.h'}}
|
||||
#include <__format/format_fwd.h>
|
||||
@@ -0,0 +1,81 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// <format>
|
||||
|
||||
// template<class Context, class... Args>
|
||||
// struct format-arg-store { // exposition only
|
||||
// array<basic_format_arg<Context>, sizeof...(Args)> args;
|
||||
// };
|
||||
//
|
||||
// Note more testing is done in the unit test for:
|
||||
// template<class Visitor, class Context>
|
||||
// see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
|
||||
|
||||
#include <format>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class CharT>
|
||||
void test() {
|
||||
using Context = std::basic_format_context<CharT*, CharT>;
|
||||
{
|
||||
auto store = std::make_format_args<Context>();
|
||||
LIBCPP_STATIC_ASSERT(
|
||||
std::is_same_v<decltype(store), std::__format_arg_store<Context>>);
|
||||
LIBCPP_STATIC_ASSERT(
|
||||
std::is_same_v<decltype(store.__args),
|
||||
std::array<std::basic_format_arg<Context>, 0>>);
|
||||
LIBCPP_ASSERT(store.__args.size() == 0);
|
||||
}
|
||||
{
|
||||
auto store = std::make_format_args<Context>(1);
|
||||
LIBCPP_STATIC_ASSERT(
|
||||
std::is_same_v<decltype(store), std::__format_arg_store<Context, int>>);
|
||||
LIBCPP_STATIC_ASSERT(
|
||||
std::is_same_v<decltype(store.__args),
|
||||
std::array<std::basic_format_arg<Context>, 1>>);
|
||||
LIBCPP_ASSERT(store.__args.size() == 1);
|
||||
}
|
||||
{
|
||||
auto store = std::make_format_args<Context>(1, 'c');
|
||||
LIBCPP_STATIC_ASSERT(
|
||||
std::is_same_v<decltype(store),
|
||||
std::__format_arg_store<Context, int, char>>);
|
||||
LIBCPP_STATIC_ASSERT(
|
||||
std::is_same_v<decltype(store.__args),
|
||||
std::array<std::basic_format_arg<Context>, 2>>);
|
||||
LIBCPP_ASSERT(store.__args.size() == 2);
|
||||
}
|
||||
{
|
||||
auto store = std::make_format_args<Context>(1, 'c', nullptr);
|
||||
LIBCPP_STATIC_ASSERT(
|
||||
std::is_same_v<decltype(store),
|
||||
std::__format_arg_store<Context, int, char, nullptr_t>>);
|
||||
LIBCPP_STATIC_ASSERT(
|
||||
std::is_same_v<decltype(store.__args),
|
||||
std::array<std::basic_format_arg<Context>, 3>>);
|
||||
LIBCPP_ASSERT(store.__args.size() == 3);
|
||||
}
|
||||
}
|
||||
|
||||
void test() {
|
||||
test<char>();
|
||||
test<wchar_t>();
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
// TODO FMT Evaluate gcc-11 status
|
||||
// UNSUPPORTED: gcc-11
|
||||
|
||||
// <format>
|
||||
|
||||
// template<class Context = format_context, class... Args>
|
||||
// format-arg-store<Context, Args...> make_format_args(const Args&... args);
|
||||
|
||||
#include <cassert>
|
||||
#include <format>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
#include "test_basic_format_arg.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
int main(int, char**) {
|
||||
using Context = std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<char>>, char>;
|
||||
|
||||
auto value = std::make_format_args(42, nullptr, false, 1.0);
|
||||
|
||||
LIBCPP_ASSERT(value.__args.size() == 4);
|
||||
LIBCPP_ASSERT(test_basic_format_arg(value.__args[0], 42));
|
||||
// Note [format.arg]/11 specifies a nullptr is stored as a const void*.
|
||||
LIBCPP_ASSERT(test_basic_format_arg(value.__args[1],
|
||||
static_cast<const void*>(nullptr)));
|
||||
LIBCPP_ASSERT(test_basic_format_arg(value.__args[2], false));
|
||||
LIBCPP_ASSERT(test_basic_format_arg(value.__args[3], 1.0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// Validate it works regardless of the signedness of `char`.
|
||||
// RUN: %{cxx} %{flags} %{compile_flags} -fsigned-char -fsyntax-only %s
|
||||
// RUN: %{cxx} %{flags} %{compile_flags} -funsigned-char -fsyntax-only %s
|
||||
|
||||
// <format>
|
||||
|
||||
// [format.arg]/5.2
|
||||
// - otherwise, if T is char and char_type is wchar_t, initializes value with static_cast<wchar_t>(v);
|
||||
|
||||
#include <format>
|
||||
|
||||
void test() {
|
||||
std::make_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<wchar_t>>, wchar_t>>('c');
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
// TODO FMT Evaluate gcc-11 status
|
||||
// UNSUPPORTED: gcc-11
|
||||
|
||||
// <format>
|
||||
|
||||
// template<class... Args>
|
||||
// format-arg-store<wformat_context, Args...>
|
||||
// make_wformat_args(const Args&... args);
|
||||
|
||||
#include <cassert>
|
||||
#include <format>
|
||||
|
||||
#include "test_basic_format_arg.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
int main(int, char**) {
|
||||
using Context = std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<wchar_t>>, wchar_t>;
|
||||
|
||||
auto value = std::make_wformat_args(42, nullptr, false, 1.0);
|
||||
|
||||
LIBCPP_ASSERT(value.__args.size() == 4);
|
||||
LIBCPP_ASSERT(test_basic_format_arg(value.__args[0], 42));
|
||||
// Note [format.arg]/11 specifies a nullptr is stored as a const void*.
|
||||
LIBCPP_ASSERT(test_basic_format_arg(value.__args[1],
|
||||
static_cast<const void*>(nullptr)));
|
||||
LIBCPP_ASSERT(test_basic_format_arg(value.__args[2], false));
|
||||
LIBCPP_ASSERT(test_basic_format_arg(value.__args[3], 1.0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// <format>
|
||||
|
||||
// basic_format_arg() noexcept;
|
||||
|
||||
// The class has several exposition only private constructors. These are tested
|
||||
// in visit_format_arg.pass.cpp
|
||||
|
||||
#include <format>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class CharT>
|
||||
void test() {
|
||||
using Context = std::basic_format_context<CharT*, CharT>;
|
||||
|
||||
ASSERT_NOEXCEPT(std::basic_format_arg<Context>{});
|
||||
|
||||
std::basic_format_arg<Context> format_arg{};
|
||||
assert(!format_arg);
|
||||
}
|
||||
|
||||
void test() {
|
||||
test<char>();
|
||||
test<wchar_t>();
|
||||
#ifndef _LIBCPP_HAS_NO_CHAR8_T
|
||||
test<char8_t>();
|
||||
#endif
|
||||
#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
test<char16_t>();
|
||||
test<char32_t>();
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// <format>
|
||||
|
||||
// explicit operator bool() const noexcept
|
||||
//
|
||||
// Note more testing is done in the unit test for:
|
||||
// template<class Visitor, class Context>
|
||||
// see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
|
||||
|
||||
#include <format>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
void test(const auto& store) {
|
||||
for (const auto& arg : store.__args) {
|
||||
assert(arg);
|
||||
assert(static_cast<bool>(arg));
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void test() {
|
||||
using Context = std::basic_format_context<CharT*, CharT>;
|
||||
{
|
||||
std::basic_format_arg<Context> format_arg{};
|
||||
ASSERT_NOEXCEPT(!format_arg);
|
||||
assert(!format_arg);
|
||||
ASSERT_NOEXCEPT(static_cast<bool>(format_arg));
|
||||
assert(!static_cast<bool>(format_arg));
|
||||
}
|
||||
test(std::make_format_args<Context>());
|
||||
test(std::make_format_args<Context>(1));
|
||||
test(std::make_format_args<Context>(1, 'c'));
|
||||
test(std::make_format_args<Context>(1, 'c', nullptr));
|
||||
}
|
||||
|
||||
void test() {
|
||||
test<char>();
|
||||
test<wchar_t>();
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// This test requires the dylib support introduced in D92214.
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}}
|
||||
|
||||
// <format>
|
||||
|
||||
// template<class Visitor, class Context>
|
||||
// see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
|
||||
|
||||
#include <format>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "constexpr_char_traits.h"
|
||||
#include "test_macros.h"
|
||||
#include "make_string.h"
|
||||
#include "min_allocator.h"
|
||||
|
||||
template <class Context, class To, class From>
|
||||
void test(From value) {
|
||||
auto format_args = std::make_format_args<Context>(value);
|
||||
assert(format_args.__args.size() == 1);
|
||||
assert(format_args.__args[0]);
|
||||
|
||||
auto result = std::visit_format_arg(
|
||||
[v = To(value)](auto a) -> To {
|
||||
if constexpr (std::is_same_v<To, decltype(a)>) {
|
||||
assert(v == a);
|
||||
return a;
|
||||
} else {
|
||||
assert(false);
|
||||
return {};
|
||||
}
|
||||
},
|
||||
format_args.__args[0]);
|
||||
|
||||
using ct = std::common_type_t<From, To>;
|
||||
assert(static_cast<ct>(result) == static_cast<ct>(value));
|
||||
}
|
||||
|
||||
// Test specific for string and string_view.
|
||||
//
|
||||
// Since both result in a string_view there's no need to pass this as a
|
||||
// template argument.
|
||||
template <class Context, class From>
|
||||
void test_string_view(From value) {
|
||||
auto format_args = std::make_format_args<Context>(value);
|
||||
assert(format_args.__args.size() == 1);
|
||||
assert(format_args.__args[0]);
|
||||
|
||||
using CharT = typename Context::char_type;
|
||||
using To = std::basic_string_view<CharT>;
|
||||
using V = std::basic_string<CharT>;
|
||||
auto result = std::visit_format_arg(
|
||||
[v = V(value.begin(), value.end())](auto a) -> To {
|
||||
if constexpr (std::is_same_v<To, decltype(a)>) {
|
||||
assert(v == a);
|
||||
return a;
|
||||
} else {
|
||||
assert(false);
|
||||
return {};
|
||||
}
|
||||
},
|
||||
format_args.__args[0]);
|
||||
|
||||
assert(std::equal(value.begin(), value.end(), result.begin(), result.end()));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void test() {
|
||||
using Context = std::basic_format_context<CharT*, CharT>;
|
||||
std::basic_string<CharT> empty;
|
||||
std::basic_string<CharT> str = MAKE_STRING(CharT, "abc");
|
||||
|
||||
// Test boolean types.
|
||||
|
||||
test<Context, bool>(true);
|
||||
test<Context, bool>(false);
|
||||
|
||||
// Test CharT types.
|
||||
|
||||
test<Context, CharT, CharT>('a');
|
||||
test<Context, CharT, CharT>('z');
|
||||
test<Context, CharT, CharT>('0');
|
||||
test<Context, CharT, CharT>('9');
|
||||
|
||||
// Test char types.
|
||||
|
||||
if (std::is_same_v<CharT, char>) {
|
||||
// char to char -> char
|
||||
test<Context, CharT, char>('a');
|
||||
test<Context, CharT, char>('z');
|
||||
test<Context, CharT, char>('0');
|
||||
test<Context, CharT, char>('9');
|
||||
} else {
|
||||
if (std::is_same_v<CharT, wchar_t>) {
|
||||
// char to wchar_t -> wchar_t
|
||||
test<Context, wchar_t, char>('a');
|
||||
test<Context, wchar_t, char>('z');
|
||||
test<Context, wchar_t, char>('0');
|
||||
test<Context, wchar_t, char>('9');
|
||||
} else if (std::is_signed_v<char>) {
|
||||
// char to CharT -> int
|
||||
// This happens when CharT is a char8_t, char16_t, or char32_t and char
|
||||
// is a signed type.
|
||||
// Note if sizeof(CharT) > sizeof(int) this test fails. If there are
|
||||
// platforms where that occurs extra tests need to be added for char32_t
|
||||
// testing it against a long long.
|
||||
test<Context, int, char>('a');
|
||||
test<Context, int, char>('z');
|
||||
test<Context, int, char>('0');
|
||||
test<Context, int, char>('9');
|
||||
} else {
|
||||
// char to CharT -> unsigned
|
||||
// This happens when CharT is a char8_t, char16_t, or char32_t and char
|
||||
// is an unsigned type.
|
||||
// Note if sizeof(CharT) > sizeof(unsigned) this test fails. If there are
|
||||
// platforms where that occurs extra tests need to be added for char32_t
|
||||
// testing it against an unsigned long long.
|
||||
test<Context, unsigned, char>('a');
|
||||
test<Context, unsigned, char>('z');
|
||||
test<Context, unsigned, char>('0');
|
||||
test<Context, unsigned, char>('9');
|
||||
}
|
||||
}
|
||||
|
||||
// Test signed integer types.
|
||||
|
||||
test<Context, int, signed char>(std::numeric_limits<signed char>::min());
|
||||
test<Context, int, signed char>(0);
|
||||
test<Context, int, signed char>(std::numeric_limits<signed char>::max());
|
||||
|
||||
test<Context, int, short>(std::numeric_limits<short>::min());
|
||||
test<Context, int, short>(std::numeric_limits<signed char>::min());
|
||||
test<Context, int, short>(0);
|
||||
test<Context, int, short>(std::numeric_limits<signed char>::max());
|
||||
test<Context, int, short>(std::numeric_limits<short>::max());
|
||||
|
||||
test<Context, int, int>(std::numeric_limits<int>::min());
|
||||
test<Context, int, int>(std::numeric_limits<short>::min());
|
||||
test<Context, int, int>(std::numeric_limits<signed char>::min());
|
||||
test<Context, int, int>(0);
|
||||
test<Context, int, int>(std::numeric_limits<signed char>::max());
|
||||
test<Context, int, int>(std::numeric_limits<short>::max());
|
||||
test<Context, int, int>(std::numeric_limits<int>::max());
|
||||
|
||||
using LongToType =
|
||||
std::conditional_t<sizeof(long) == sizeof(int), int, long long>;
|
||||
|
||||
test<Context, LongToType, long>(std::numeric_limits<long>::min());
|
||||
test<Context, LongToType, long>(std::numeric_limits<int>::min());
|
||||
test<Context, LongToType, long>(std::numeric_limits<short>::min());
|
||||
test<Context, LongToType, long>(std::numeric_limits<signed char>::min());
|
||||
test<Context, LongToType, long>(0);
|
||||
test<Context, LongToType, long>(std::numeric_limits<signed char>::max());
|
||||
test<Context, LongToType, long>(std::numeric_limits<short>::max());
|
||||
test<Context, LongToType, long>(std::numeric_limits<int>::max());
|
||||
test<Context, LongToType, long>(std::numeric_limits<long>::max());
|
||||
|
||||
test<Context, long long, long long>(std::numeric_limits<long long>::min());
|
||||
test<Context, long long, long long>(std::numeric_limits<long>::min());
|
||||
test<Context, long long, long long>(std::numeric_limits<int>::min());
|
||||
test<Context, long long, long long>(std::numeric_limits<short>::min());
|
||||
test<Context, long long, long long>(std::numeric_limits<signed char>::min());
|
||||
test<Context, long long, long long>(0);
|
||||
test<Context, long long, long long>(std::numeric_limits<signed char>::max());
|
||||
test<Context, long long, long long>(std::numeric_limits<short>::max());
|
||||
test<Context, long long, long long>(std::numeric_limits<int>::max());
|
||||
test<Context, long long, long long>(std::numeric_limits<long>::max());
|
||||
test<Context, long long, long long>(std::numeric_limits<long long>::max());
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<__int128_t>::min());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<long long>::min());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<long>::min());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<int>::min());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<short>::min());
|
||||
test<Context, __int128_t, __int128_t>(
|
||||
std::numeric_limits<signed char>::min());
|
||||
test<Context, __int128_t, __int128_t>(0);
|
||||
test<Context, __int128_t, __int128_t>(
|
||||
std::numeric_limits<signed char>::max());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<short>::max());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<int>::max());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<long>::max());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<long long>::max());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<__int128_t>::max());
|
||||
#endif
|
||||
|
||||
// Test unsigned integer types.
|
||||
|
||||
test<Context, unsigned, unsigned char>(0);
|
||||
test<Context, unsigned, unsigned char>(
|
||||
std::numeric_limits<unsigned char>::max());
|
||||
|
||||
test<Context, unsigned, unsigned short>(0);
|
||||
test<Context, unsigned, unsigned short>(
|
||||
std::numeric_limits<unsigned char>::max());
|
||||
test<Context, unsigned, unsigned short>(
|
||||
std::numeric_limits<unsigned short>::max());
|
||||
|
||||
test<Context, unsigned, unsigned>(0);
|
||||
test<Context, unsigned, unsigned>(std::numeric_limits<unsigned char>::max());
|
||||
test<Context, unsigned, unsigned>(std::numeric_limits<unsigned short>::max());
|
||||
test<Context, unsigned, unsigned>(std::numeric_limits<unsigned>::max());
|
||||
|
||||
using UnsignedLongToType =
|
||||
std::conditional_t<sizeof(unsigned long) == sizeof(unsigned), unsigned,
|
||||
unsigned long long>;
|
||||
|
||||
test<Context, UnsignedLongToType, unsigned long>(0);
|
||||
test<Context, UnsignedLongToType, unsigned long>(
|
||||
std::numeric_limits<unsigned char>::max());
|
||||
test<Context, UnsignedLongToType, unsigned long>(
|
||||
std::numeric_limits<unsigned short>::max());
|
||||
test<Context, UnsignedLongToType, unsigned long>(
|
||||
std::numeric_limits<unsigned>::max());
|
||||
test<Context, UnsignedLongToType, unsigned long>(
|
||||
std::numeric_limits<unsigned long>::max());
|
||||
|
||||
test<Context, unsigned long long, unsigned long long>(0);
|
||||
test<Context, unsigned long long, unsigned long long>(
|
||||
std::numeric_limits<unsigned char>::max());
|
||||
test<Context, unsigned long long, unsigned long long>(
|
||||
std::numeric_limits<unsigned short>::max());
|
||||
test<Context, unsigned long long, unsigned long long>(
|
||||
std::numeric_limits<unsigned>::max());
|
||||
test<Context, unsigned long long, unsigned long long>(
|
||||
std::numeric_limits<unsigned long>::max());
|
||||
test<Context, unsigned long long, unsigned long long>(
|
||||
std::numeric_limits<unsigned long long>::max());
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
test<Context, __uint128_t, __uint128_t>(0);
|
||||
test<Context, __uint128_t, __uint128_t>(
|
||||
std::numeric_limits<unsigned char>::max());
|
||||
test<Context, __uint128_t, __uint128_t>(
|
||||
std::numeric_limits<unsigned short>::max());
|
||||
test<Context, __uint128_t, __uint128_t>(
|
||||
std::numeric_limits<unsigned int>::max());
|
||||
test<Context, __uint128_t, __uint128_t>(
|
||||
std::numeric_limits<unsigned long>::max());
|
||||
test<Context, __uint128_t, __uint128_t>(
|
||||
std::numeric_limits<unsigned long long>::max());
|
||||
test<Context, __uint128_t, __uint128_t>(
|
||||
std::numeric_limits<__uint128_t>::max());
|
||||
#endif
|
||||
|
||||
// Test floating point types.
|
||||
|
||||
test<Context, float, float>(-std::numeric_limits<float>::max());
|
||||
test<Context, float, float>(-std::numeric_limits<float>::min());
|
||||
test<Context, float, float>(-0.0);
|
||||
test<Context, float, float>(0.0);
|
||||
test<Context, float, float>(std::numeric_limits<float>::min());
|
||||
test<Context, float, float>(std::numeric_limits<float>::max());
|
||||
|
||||
test<Context, double, double>(-std::numeric_limits<double>::max());
|
||||
test<Context, double, double>(-std::numeric_limits<double>::min());
|
||||
test<Context, double, double>(-0.0);
|
||||
test<Context, double, double>(0.0);
|
||||
test<Context, double, double>(std::numeric_limits<double>::min());
|
||||
test<Context, double, double>(std::numeric_limits<double>::max());
|
||||
|
||||
test<Context, long double, long double>(
|
||||
-std::numeric_limits<long double>::max());
|
||||
test<Context, long double, long double>(
|
||||
-std::numeric_limits<long double>::min());
|
||||
test<Context, long double, long double>(-0.0);
|
||||
test<Context, long double, long double>(0.0);
|
||||
test<Context, long double, long double>(
|
||||
std::numeric_limits<long double>::min());
|
||||
test<Context, long double, long double>(
|
||||
std::numeric_limits<long double>::max());
|
||||
|
||||
// Test const CharT pointer types.
|
||||
|
||||
test<Context, const CharT*, const CharT*>(empty.c_str());
|
||||
test<Context, const CharT*, const CharT*>(str.c_str());
|
||||
|
||||
// Test string_view types.
|
||||
|
||||
{
|
||||
using From = std::basic_string_view<CharT>;
|
||||
|
||||
test_string_view<Context>(From());
|
||||
test_string_view<Context>(From(empty.c_str()));
|
||||
test_string_view<Context>(From(str.c_str()));
|
||||
}
|
||||
|
||||
{
|
||||
using From = std::basic_string_view<CharT, constexpr_char_traits<CharT>>;
|
||||
|
||||
test_string_view<Context>(From());
|
||||
test_string_view<Context>(From(empty.c_str()));
|
||||
test_string_view<Context>(From(str.c_str()));
|
||||
}
|
||||
|
||||
// Test string types.
|
||||
|
||||
{
|
||||
using From = std::basic_string<CharT>;
|
||||
|
||||
test_string_view<Context>(From());
|
||||
test_string_view<Context>(From(empty.c_str()));
|
||||
test_string_view<Context>(From(str.c_str()));
|
||||
}
|
||||
|
||||
{
|
||||
using From = std::basic_string<CharT, constexpr_char_traits<CharT>,
|
||||
std::allocator<CharT>>;
|
||||
|
||||
test_string_view<Context>(From());
|
||||
test_string_view<Context>(From(empty.c_str()));
|
||||
test_string_view<Context>(From(str.c_str()));
|
||||
}
|
||||
|
||||
{
|
||||
using From =
|
||||
std::basic_string<CharT, std::char_traits<CharT>, min_allocator<CharT>>;
|
||||
|
||||
test_string_view<Context>(From());
|
||||
test_string_view<Context>(From(empty.c_str()));
|
||||
test_string_view<Context>(From(str.c_str()));
|
||||
}
|
||||
|
||||
{
|
||||
using From = std::basic_string<CharT, constexpr_char_traits<CharT>,
|
||||
min_allocator<CharT>>;
|
||||
|
||||
test_string_view<Context>(From());
|
||||
test_string_view<Context>(From(empty.c_str()));
|
||||
test_string_view<Context>(From(str.c_str()));
|
||||
}
|
||||
|
||||
// Test pointer types.
|
||||
|
||||
test<Context, const void*>(nullptr);
|
||||
}
|
||||
|
||||
void test() {
|
||||
test<char>();
|
||||
test<wchar_t>();
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// <format>
|
||||
|
||||
// basic_format_args() noexcept;
|
||||
// template<class... Args>
|
||||
// basic_format_args(const format-arg-store<Context, Args...>& store) noexcept;
|
||||
|
||||
#include <format>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class CharT>
|
||||
void test() {
|
||||
using Context = std::basic_format_context<CharT*, CharT>;
|
||||
{
|
||||
ASSERT_NOEXCEPT(std::basic_format_args<Context>{});
|
||||
|
||||
std::basic_format_args<Context> format_args{};
|
||||
assert(!format_args.get(0));
|
||||
}
|
||||
{
|
||||
auto store = std::make_format_args<Context>(1);
|
||||
ASSERT_NOEXCEPT(std::basic_format_args<Context>{store});
|
||||
std::basic_format_args<Context> format_args{store};
|
||||
assert(format_args.get(0));
|
||||
assert(!format_args.get(1));
|
||||
}
|
||||
{
|
||||
auto store = std::make_format_args<Context>(1, 'c');
|
||||
ASSERT_NOEXCEPT(std::basic_format_args<Context>{store});
|
||||
std::basic_format_args<Context> format_args{store};
|
||||
assert(format_args.get(0));
|
||||
assert(format_args.get(1));
|
||||
assert(!format_args.get(2));
|
||||
}
|
||||
{
|
||||
auto store = std::make_format_args<Context>(1, 'c', nullptr);
|
||||
ASSERT_NOEXCEPT(std::basic_format_args<Context>{store});
|
||||
std::basic_format_args<Context> format_args{store};
|
||||
assert(format_args.get(0));
|
||||
assert(format_args.get(1));
|
||||
assert(format_args.get(2));
|
||||
assert(!format_args.get(3));
|
||||
}
|
||||
}
|
||||
|
||||
void test() {
|
||||
test<char>();
|
||||
test<wchar_t>();
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// This test requires the dylib support introduced in D92214.
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}}
|
||||
|
||||
// <format>
|
||||
|
||||
// basic_format_arg<Context> get(size_t i) const noexcept;
|
||||
|
||||
#include <format>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "make_string.h"
|
||||
|
||||
template <class Context, class To, class From>
|
||||
void test(From value) {
|
||||
auto store = std::make_format_args<Context>(value);
|
||||
const std::basic_format_args<Context> format_args{store};
|
||||
|
||||
std::visit_format_arg(
|
||||
[v = To(value)](auto a) {
|
||||
if constexpr (std::is_same_v<To, decltype(a)>)
|
||||
assert(v == a);
|
||||
else
|
||||
assert(false);
|
||||
},
|
||||
format_args.get(0));
|
||||
}
|
||||
|
||||
// Test specific for string and string_view.
|
||||
//
|
||||
// Since both result in a string_view there's no need to pass this as a
|
||||
// template argument.
|
||||
template <class Context, class From>
|
||||
void test_string_view(From value) {
|
||||
auto store = std::make_format_args<Context>(value);
|
||||
const std::basic_format_args<Context> format_args{store};
|
||||
|
||||
using CharT = typename Context::char_type;
|
||||
using To = std::basic_string_view<CharT>;
|
||||
using V = std::basic_string<CharT>;
|
||||
std::visit_format_arg(
|
||||
[v = V(value.begin(), value.end())](auto a) {
|
||||
if constexpr (std::is_same_v<To, decltype(a)>)
|
||||
assert(v == a);
|
||||
else
|
||||
assert(false);
|
||||
},
|
||||
format_args.get(0));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void test() {
|
||||
using Context = std::basic_format_context<CharT*, CharT>;
|
||||
{
|
||||
const std::basic_format_args<Context> format_args{};
|
||||
ASSERT_NOEXCEPT(format_args.get(0));
|
||||
assert(!format_args.get(0));
|
||||
}
|
||||
|
||||
using char_type = typename Context::char_type;
|
||||
std::basic_string<char_type> empty;
|
||||
std::basic_string<char_type> str = MAKE_STRING(char_type, "abc");
|
||||
|
||||
// Test boolean types.
|
||||
|
||||
test<Context, bool>(true);
|
||||
test<Context, bool>(false);
|
||||
|
||||
// Test char_type types.
|
||||
|
||||
test<Context, char_type, char_type>('a');
|
||||
test<Context, char_type, char_type>('z');
|
||||
test<Context, char_type, char_type>('0');
|
||||
test<Context, char_type, char_type>('9');
|
||||
|
||||
// Test char types.
|
||||
|
||||
if (std::is_same_v<char_type, char>) {
|
||||
// char to char -> char
|
||||
test<Context, char_type, char>('a');
|
||||
test<Context, char_type, char>('z');
|
||||
test<Context, char_type, char>('0');
|
||||
test<Context, char_type, char>('9');
|
||||
} else {
|
||||
if (std::is_same_v<char_type, wchar_t>) {
|
||||
// char to wchar_t -> wchar_t
|
||||
test<Context, wchar_t, char>('a');
|
||||
test<Context, wchar_t, char>('z');
|
||||
test<Context, wchar_t, char>('0');
|
||||
test<Context, wchar_t, char>('9');
|
||||
} else if (std::is_signed_v<char>) {
|
||||
// char to char_type -> int
|
||||
// This happens when Context::char_type is a char8_t, char16_t, or
|
||||
// char32_t and char is a signed type.
|
||||
// Note if sizeof(char_type) > sizeof(int) this test fails. If there are
|
||||
// platforms where that occurs extra tests need to be added for char32_t
|
||||
// testing it against a long long.
|
||||
test<Context, int, char>('a');
|
||||
test<Context, int, char>('z');
|
||||
test<Context, int, char>('0');
|
||||
test<Context, int, char>('9');
|
||||
} else {
|
||||
// char to char_type -> unsigned
|
||||
// This happens when Context::char_type is a char8_t, char16_t, or
|
||||
// char32_t and char is an unsigned type.
|
||||
// Note if sizeof(char_type) > sizeof(unsigned) this test fails. If there
|
||||
// are platforms where that occurs extra tests need to be added for
|
||||
// char32_t testing it against an unsigned long long.
|
||||
test<Context, unsigned, char>('a');
|
||||
test<Context, unsigned, char>('z');
|
||||
test<Context, unsigned, char>('0');
|
||||
test<Context, unsigned, char>('9');
|
||||
}
|
||||
}
|
||||
|
||||
// Test signed integer types.
|
||||
|
||||
test<Context, int, signed char>(std::numeric_limits<signed char>::min());
|
||||
test<Context, int, signed char>(0);
|
||||
test<Context, int, signed char>(std::numeric_limits<signed char>::max());
|
||||
|
||||
test<Context, int, short>(std::numeric_limits<short>::min());
|
||||
test<Context, int, short>(std::numeric_limits<signed char>::min());
|
||||
test<Context, int, short>(0);
|
||||
test<Context, int, short>(std::numeric_limits<signed char>::max());
|
||||
test<Context, int, short>(std::numeric_limits<short>::max());
|
||||
|
||||
test<Context, int, int>(std::numeric_limits<int>::min());
|
||||
test<Context, int, int>(std::numeric_limits<short>::min());
|
||||
test<Context, int, int>(std::numeric_limits<signed char>::min());
|
||||
test<Context, int, int>(0);
|
||||
test<Context, int, int>(std::numeric_limits<signed char>::max());
|
||||
test<Context, int, int>(std::numeric_limits<short>::max());
|
||||
test<Context, int, int>(std::numeric_limits<int>::max());
|
||||
|
||||
using LongToType =
|
||||
std::conditional_t<sizeof(long) == sizeof(int), int, long long>;
|
||||
|
||||
test<Context, LongToType, long>(std::numeric_limits<long>::min());
|
||||
test<Context, LongToType, long>(std::numeric_limits<int>::min());
|
||||
test<Context, LongToType, long>(std::numeric_limits<short>::min());
|
||||
test<Context, LongToType, long>(std::numeric_limits<signed char>::min());
|
||||
test<Context, LongToType, long>(0);
|
||||
test<Context, LongToType, long>(std::numeric_limits<signed char>::max());
|
||||
test<Context, LongToType, long>(std::numeric_limits<short>::max());
|
||||
test<Context, LongToType, long>(std::numeric_limits<int>::max());
|
||||
test<Context, LongToType, long>(std::numeric_limits<long>::max());
|
||||
|
||||
test<Context, long long, long long>(std::numeric_limits<long long>::min());
|
||||
test<Context, long long, long long>(std::numeric_limits<long>::min());
|
||||
test<Context, long long, long long>(std::numeric_limits<int>::min());
|
||||
test<Context, long long, long long>(std::numeric_limits<short>::min());
|
||||
test<Context, long long, long long>(std::numeric_limits<signed char>::min());
|
||||
test<Context, long long, long long>(0);
|
||||
test<Context, long long, long long>(std::numeric_limits<signed char>::max());
|
||||
test<Context, long long, long long>(std::numeric_limits<short>::max());
|
||||
test<Context, long long, long long>(std::numeric_limits<int>::max());
|
||||
test<Context, long long, long long>(std::numeric_limits<long>::max());
|
||||
test<Context, long long, long long>(std::numeric_limits<long long>::max());
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<__int128_t>::min());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<long long>::min());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<long>::min());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<int>::min());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<short>::min());
|
||||
test<Context, __int128_t, __int128_t>(
|
||||
std::numeric_limits<signed char>::min());
|
||||
test<Context, __int128_t, __int128_t>(0);
|
||||
test<Context, __int128_t, __int128_t>(
|
||||
std::numeric_limits<signed char>::max());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<short>::max());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<int>::max());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<long>::max());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<long long>::max());
|
||||
test<Context, __int128_t, __int128_t>(std::numeric_limits<__int128_t>::max());
|
||||
#endif
|
||||
|
||||
// Test unsigned integer types.
|
||||
|
||||
test<Context, unsigned, unsigned char>(0);
|
||||
test<Context, unsigned, unsigned char>(
|
||||
std::numeric_limits<unsigned char>::max());
|
||||
|
||||
test<Context, unsigned, unsigned short>(0);
|
||||
test<Context, unsigned, unsigned short>(
|
||||
std::numeric_limits<unsigned char>::max());
|
||||
test<Context, unsigned, unsigned short>(
|
||||
std::numeric_limits<unsigned short>::max());
|
||||
|
||||
test<Context, unsigned, unsigned>(0);
|
||||
test<Context, unsigned, unsigned>(std::numeric_limits<unsigned char>::max());
|
||||
test<Context, unsigned, unsigned>(std::numeric_limits<unsigned short>::max());
|
||||
test<Context, unsigned, unsigned>(std::numeric_limits<unsigned>::max());
|
||||
|
||||
using UnsignedLongToType =
|
||||
std::conditional_t<sizeof(unsigned long) == sizeof(unsigned), unsigned,
|
||||
unsigned long long>;
|
||||
|
||||
test<Context, UnsignedLongToType, unsigned long>(0);
|
||||
test<Context, UnsignedLongToType, unsigned long>(
|
||||
std::numeric_limits<unsigned char>::max());
|
||||
test<Context, UnsignedLongToType, unsigned long>(
|
||||
std::numeric_limits<unsigned short>::max());
|
||||
test<Context, UnsignedLongToType, unsigned long>(
|
||||
std::numeric_limits<unsigned>::max());
|
||||
test<Context, UnsignedLongToType, unsigned long>(
|
||||
std::numeric_limits<unsigned long>::max());
|
||||
|
||||
test<Context, unsigned long long, unsigned long long>(0);
|
||||
test<Context, unsigned long long, unsigned long long>(
|
||||
std::numeric_limits<unsigned char>::max());
|
||||
test<Context, unsigned long long, unsigned long long>(
|
||||
std::numeric_limits<unsigned short>::max());
|
||||
test<Context, unsigned long long, unsigned long long>(
|
||||
std::numeric_limits<unsigned>::max());
|
||||
test<Context, unsigned long long, unsigned long long>(
|
||||
std::numeric_limits<unsigned long>::max());
|
||||
test<Context, unsigned long long, unsigned long long>(
|
||||
std::numeric_limits<unsigned long long>::max());
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
test<Context, __uint128_t, __uint128_t>(0);
|
||||
test<Context, __uint128_t, __uint128_t>(
|
||||
std::numeric_limits<unsigned char>::max());
|
||||
test<Context, __uint128_t, __uint128_t>(
|
||||
std::numeric_limits<unsigned short>::max());
|
||||
test<Context, __uint128_t, __uint128_t>(
|
||||
std::numeric_limits<unsigned int>::max());
|
||||
test<Context, __uint128_t, __uint128_t>(
|
||||
std::numeric_limits<unsigned long>::max());
|
||||
test<Context, __uint128_t, __uint128_t>(
|
||||
std::numeric_limits<unsigned long long>::max());
|
||||
test<Context, __uint128_t, __uint128_t>(
|
||||
std::numeric_limits<__uint128_t>::max());
|
||||
#endif
|
||||
|
||||
// Test floating point types.
|
||||
|
||||
test<Context, float, float>(-std::numeric_limits<float>::max());
|
||||
test<Context, float, float>(-std::numeric_limits<float>::min());
|
||||
test<Context, float, float>(-0.0);
|
||||
test<Context, float, float>(0.0);
|
||||
test<Context, float, float>(std::numeric_limits<float>::min());
|
||||
test<Context, float, float>(std::numeric_limits<float>::max());
|
||||
|
||||
test<Context, double, double>(-std::numeric_limits<double>::max());
|
||||
test<Context, double, double>(-std::numeric_limits<double>::min());
|
||||
test<Context, double, double>(-0.0);
|
||||
test<Context, double, double>(0.0);
|
||||
test<Context, double, double>(std::numeric_limits<double>::min());
|
||||
test<Context, double, double>(std::numeric_limits<double>::max());
|
||||
|
||||
test<Context, long double, long double>(
|
||||
-std::numeric_limits<long double>::max());
|
||||
test<Context, long double, long double>(
|
||||
-std::numeric_limits<long double>::min());
|
||||
test<Context, long double, long double>(-0.0);
|
||||
test<Context, long double, long double>(0.0);
|
||||
test<Context, long double, long double>(
|
||||
std::numeric_limits<long double>::min());
|
||||
test<Context, long double, long double>(
|
||||
std::numeric_limits<long double>::max());
|
||||
|
||||
// Test const char_type pointer types.
|
||||
|
||||
test<Context, const char_type*, const char_type*>(empty.c_str());
|
||||
test<Context, const char_type*, const char_type*>(str.c_str());
|
||||
|
||||
// Test string_view types.
|
||||
|
||||
test<Context, std::basic_string_view<char_type>>(
|
||||
std::basic_string_view<char_type>());
|
||||
test<Context, std::basic_string_view<char_type>,
|
||||
std::basic_string_view<char_type>>(empty);
|
||||
test<Context, std::basic_string_view<char_type>,
|
||||
std::basic_string_view<char_type>>(str);
|
||||
|
||||
// Test string types.
|
||||
|
||||
test<Context, std::basic_string_view<char_type>>(
|
||||
std::basic_string<char_type>());
|
||||
test<Context, std::basic_string_view<char_type>,
|
||||
std::basic_string<char_type>>(empty);
|
||||
test<Context, std::basic_string_view<char_type>,
|
||||
std::basic_string<char_type>>(str);
|
||||
|
||||
// Test pointer types.
|
||||
|
||||
test<Context, const void*>(nullptr);
|
||||
}
|
||||
|
||||
void test() {
|
||||
test<char>();
|
||||
test<wchar_t>();
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// <format>
|
||||
|
||||
// Namespace std typedefs:
|
||||
// using format_args = basic_format_args<format_context>;
|
||||
// using wformat_args = basic_format_args<wformat_context>;
|
||||
// template<class Out, class charT>
|
||||
// using format_args_t = basic_format_args<basic_format_context<Out, charT>>;
|
||||
|
||||
#include <format>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
static_assert(std::is_same_v<std::format_args,
|
||||
std::basic_format_args<std::format_context>>);
|
||||
static_assert(std::is_same_v<std::wformat_args,
|
||||
std::basic_format_args<std::wformat_context>>);
|
||||
|
||||
static_assert(std::is_same_v<
|
||||
std::format_args_t<std::back_insert_iterator<std::string>, char>,
|
||||
std::basic_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::string>, char>>>);
|
||||
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
std::format_args_t<std::back_insert_iterator<std::wstring>, wchar_t>,
|
||||
std::basic_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::wstring>, wchar_t>>>);
|
||||
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
std::format_args_t<std::back_insert_iterator<std::vector<char>>, char>,
|
||||
std::basic_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::vector<char>>, char>>>);
|
||||
|
||||
// Required for MSVC internal test runner compatibility.
|
||||
int main(int, char**) { return 0; }
|
||||
@@ -0,0 +1,74 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// <format>
|
||||
|
||||
// void advance_to(iterator it);
|
||||
|
||||
#include <format>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_format_context.h"
|
||||
|
||||
template <class OutIt, class CharT>
|
||||
void test(
|
||||
std::basic_format_args<std::basic_format_context<OutIt, CharT>> args) {
|
||||
{
|
||||
std::basic_string<CharT> str[3];
|
||||
std::basic_format_context context =
|
||||
test_format_context_create(OutIt{str[0]}, args);
|
||||
context.out() = CharT('a');
|
||||
context.advance_to(OutIt{str[1]});
|
||||
context.out() = CharT('b');
|
||||
context.advance_to(OutIt{str[2]});
|
||||
context.out() = CharT('c');
|
||||
|
||||
assert(str[0].size() == 1);
|
||||
assert(str[0].front() == CharT('a'));
|
||||
assert(str[1].size() == 1);
|
||||
assert(str[1].front() == CharT('b'));
|
||||
assert(str[2].size() == 1);
|
||||
assert(str[2].front() == CharT('c'));
|
||||
}
|
||||
}
|
||||
|
||||
void test() {
|
||||
test(std::basic_format_args(
|
||||
std::make_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<char>>, char>>()));
|
||||
|
||||
test(std::basic_format_args(
|
||||
std::make_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<wchar_t>>, wchar_t>>()));
|
||||
#ifndef _LIBCPP_HAS_NO_CHAR8_T
|
||||
test(std::basic_format_args(
|
||||
std::make_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<char8_t>>, char8_t>>()));
|
||||
#endif
|
||||
#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
test(std::basic_format_args(
|
||||
std::make_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<char16_t>>,
|
||||
char16_t>>()));
|
||||
test(std::basic_format_args(
|
||||
std::make_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<char32_t>>,
|
||||
char32_t>>()));
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// <format>
|
||||
|
||||
// basic_format_arg<basic_format_context> arg(size_t id) const;
|
||||
|
||||
#include <format>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_basic_format_arg.h"
|
||||
#include "test_format_context.h"
|
||||
#include "test_macros.h"
|
||||
#include "make_string.h"
|
||||
|
||||
template <class OutIt, class CharT>
|
||||
void test() {
|
||||
std::basic_string<CharT> string = MAKE_STRING(CharT, "string");
|
||||
auto store = std::make_format_args<std::basic_format_context<OutIt, CharT>>(
|
||||
true, CharT('a'), 42, string);
|
||||
std::basic_format_args args = store;
|
||||
|
||||
std::basic_string<CharT> output;
|
||||
const std::basic_format_context context =
|
||||
test_format_context_create(OutIt{output}, args);
|
||||
LIBCPP_ASSERT(args.__size() == 4);
|
||||
for (size_t i = 0, e = args.__size(); i != e; ++i) {
|
||||
assert(context.arg(i));
|
||||
}
|
||||
assert(!context.arg(args.__size()));
|
||||
|
||||
assert(test_basic_format_arg(context.arg(0), true));
|
||||
assert(test_basic_format_arg(context.arg(1), CharT('a')));
|
||||
assert(test_basic_format_arg(context.arg(2), 42));
|
||||
assert(test_basic_format_arg(context.arg(3),
|
||||
std::basic_string_view<CharT>(string)));
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<std::back_insert_iterator<std::basic_string<char>>, char>();
|
||||
test<std::back_insert_iterator<std::basic_string<wchar_t>>, wchar_t>();
|
||||
#ifndef _LIBCPP_HAS_NO_CHAR8_T
|
||||
test<std::back_insert_iterator<std::basic_string<char8_t>>, char8_t>();
|
||||
#endif
|
||||
#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
test<std::back_insert_iterator<std::basic_string<char16_t>>, char16_t>();
|
||||
test<std::back_insert_iterator<std::basic_string<char32_t>>, char32_t>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-localization
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// REQUIRES: locale.en_US.UTF-8
|
||||
// REQUIRES: locale.fr_FR.UTF-8
|
||||
|
||||
// <format>
|
||||
|
||||
// The Standard does not specifiy a constructor
|
||||
// basic_format_context(Out out,
|
||||
// basic_format_args<basic_format_context> args,
|
||||
// std::optional<std::::locale>&& loc = std::nullopt);
|
||||
// If compliled with -D_LIBCPP_HAS_NO_LOCALIZATION
|
||||
// basic_format_context(Out out,
|
||||
// basic_format_args<basic_format_context> args);
|
||||
|
||||
#include <format>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_basic_format_arg.h"
|
||||
#include "test_format_context.h"
|
||||
#include "make_string.h"
|
||||
#include "platform_support.h" // locale name macros
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class OutIt, class CharT>
|
||||
void test() {
|
||||
static_assert(
|
||||
!std::is_copy_constructible_v<std::basic_format_context<OutIt, CharT>>);
|
||||
static_assert(
|
||||
!std::is_copy_assignable_v<std::basic_format_context<OutIt, CharT>>);
|
||||
// The move operations are implicitly deleted due to the
|
||||
// deleted copy operations.
|
||||
static_assert(
|
||||
!std::is_move_constructible_v<std::basic_format_context<OutIt, CharT>>);
|
||||
static_assert(
|
||||
!std::is_move_assignable_v<std::basic_format_context<OutIt, CharT>>);
|
||||
|
||||
std::basic_string<CharT> string = MAKE_STRING(CharT, "string");
|
||||
std::basic_format_args args =
|
||||
std::make_format_args<std::basic_format_context<OutIt, CharT>>(
|
||||
true, CharT('a'), 42, string);
|
||||
|
||||
{
|
||||
std::basic_string<CharT> output;
|
||||
OutIt out_it{output};
|
||||
std::basic_format_context context =
|
||||
test_format_context_create(out_it, args);
|
||||
LIBCPP_ASSERT(args.__size() == 4);
|
||||
|
||||
assert(test_basic_format_arg(context.arg(0), true));
|
||||
assert(test_basic_format_arg(context.arg(1), CharT('a')));
|
||||
assert(test_basic_format_arg(context.arg(2), 42));
|
||||
assert(test_basic_format_arg(context.arg(3),
|
||||
std::basic_string_view<CharT>(string)));
|
||||
|
||||
context.out() = CharT('a');
|
||||
assert(output.size() == 1);
|
||||
assert(output.front() == CharT('a'));
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
||||
assert(context.locale() == std::locale());
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
||||
std::locale en_US{LOCALE_en_US_UTF_8};
|
||||
std::locale fr_FR{LOCALE_fr_FR_UTF_8};
|
||||
{
|
||||
std::basic_string<CharT> output;
|
||||
OutIt out_it{output};
|
||||
std::basic_format_context context =
|
||||
test_format_context_create(out_it, args, en_US);
|
||||
|
||||
LIBCPP_ASSERT(args.__size() == 4);
|
||||
assert(test_basic_format_arg(context.arg(0), true));
|
||||
assert(test_basic_format_arg(context.arg(1), CharT('a')));
|
||||
assert(test_basic_format_arg(context.arg(2), 42));
|
||||
assert(test_basic_format_arg(context.arg(3),
|
||||
std::basic_string_view<CharT>(string)));
|
||||
|
||||
context.out() = CharT('a');
|
||||
assert(output.size() == 1);
|
||||
assert(output.front() == CharT('a'));
|
||||
|
||||
assert(context.locale() != fr_FR);
|
||||
assert(context.locale() == en_US);
|
||||
}
|
||||
|
||||
{
|
||||
std::basic_string<CharT> output;
|
||||
OutIt out_it{output};
|
||||
std::basic_format_context context =
|
||||
test_format_context_create(out_it, args, fr_FR);
|
||||
|
||||
LIBCPP_ASSERT(args.__size() == 4);
|
||||
assert(test_basic_format_arg(context.arg(0), true));
|
||||
assert(test_basic_format_arg(context.arg(1), CharT('a')));
|
||||
assert(test_basic_format_arg(context.arg(2), 42));
|
||||
assert(test_basic_format_arg(context.arg(3),
|
||||
std::basic_string_view<CharT>(string)));
|
||||
|
||||
context.out() = CharT('a');
|
||||
assert(output.size() == 1);
|
||||
assert(output.front() == CharT('a'));
|
||||
|
||||
assert(context.locale() == fr_FR);
|
||||
assert(context.locale() != en_US);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void test() {
|
||||
test<std::back_insert_iterator<std::basic_string<char>>, char>();
|
||||
test<std::back_insert_iterator<std::basic_string<wchar_t>>, wchar_t>();
|
||||
#ifndef _LIBCPP_HAS_NO_CHAR8_T
|
||||
test<std::back_insert_iterator<std::basic_string<char8_t>>, char8_t>();
|
||||
#endif
|
||||
#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
test<std::back_insert_iterator<std::basic_string<char16_t>>, char16_t>();
|
||||
test<std::back_insert_iterator<std::basic_string<char32_t>>, char32_t>();
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -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: libcpp-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-localization
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// REQUIRES: locale.en_US.UTF-8
|
||||
// REQUIRES: locale.fr_FR.UTF-8
|
||||
|
||||
// <format>
|
||||
|
||||
// std::locale locale();
|
||||
|
||||
#include <format>
|
||||
#include <cassert>
|
||||
|
||||
#include "make_string.h"
|
||||
#include "platform_support.h" // locale name macros
|
||||
#include "test_basic_format_arg.h"
|
||||
#include "test_format_context.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class OutIt, class CharT>
|
||||
void test() {
|
||||
std::locale en_US{LOCALE_en_US_UTF_8};
|
||||
std::locale fr_FR{LOCALE_fr_FR_UTF_8};
|
||||
std::basic_string<CharT> string = MAKE_STRING(CharT, "string");
|
||||
std::basic_format_args args =
|
||||
std::make_format_args<std::basic_format_context<OutIt, CharT>>(
|
||||
true, CharT('a'), 42, string);
|
||||
|
||||
{
|
||||
std::basic_string<CharT> output;
|
||||
OutIt out_it{output};
|
||||
std::basic_format_context context =
|
||||
test_format_context_create(out_it, args, en_US);
|
||||
assert(args.__size() == 4);
|
||||
assert(test_basic_format_arg(context.arg(0), true));
|
||||
assert(test_basic_format_arg(context.arg(1), CharT('a')));
|
||||
assert(test_basic_format_arg(context.arg(2), 42));
|
||||
assert(test_basic_format_arg(context.arg(3),
|
||||
std::basic_string_view<CharT>(string)));
|
||||
|
||||
context.out() = CharT('a');
|
||||
assert(output.size() == 1);
|
||||
assert(output.front() == CharT('a'));
|
||||
|
||||
assert(context.locale() != fr_FR);
|
||||
assert(context.locale() == en_US);
|
||||
}
|
||||
|
||||
{
|
||||
std::basic_string<CharT> output;
|
||||
OutIt out_it{output};
|
||||
std::basic_format_context context =
|
||||
test_format_context_create(out_it, args, fr_FR);
|
||||
assert(args.__size() == 4);
|
||||
assert(test_basic_format_arg(context.arg(0), true));
|
||||
assert(test_basic_format_arg(context.arg(1), CharT('a')));
|
||||
assert(test_basic_format_arg(context.arg(2), 42));
|
||||
assert(test_basic_format_arg(context.arg(3),
|
||||
std::basic_string_view<CharT>(string)));
|
||||
|
||||
context.out() = CharT('a');
|
||||
assert(output.size() == 1);
|
||||
assert(output.front() == CharT('a'));
|
||||
|
||||
assert(context.locale() == fr_FR);
|
||||
assert(context.locale() != en_US);
|
||||
}
|
||||
}
|
||||
|
||||
void test() {
|
||||
test<std::back_insert_iterator<std::basic_string<char>>, char>();
|
||||
test<std::back_insert_iterator<std::basic_string<wchar_t>>, wchar_t>();
|
||||
#ifndef _LIBCPP_HAS_NO_CHAR8_T
|
||||
test<std::back_insert_iterator<std::basic_string<char8_t>>, char8_t>();
|
||||
#endif
|
||||
#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
test<std::back_insert_iterator<std::basic_string<char16_t>>, char16_t>();
|
||||
test<std::back_insert_iterator<std::basic_string<char32_t>>, char32_t>();
|
||||
#endif
|
||||
}
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// <format>
|
||||
|
||||
// iterator out();
|
||||
|
||||
#include <format>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_format_context.h"
|
||||
|
||||
template <class OutIt, class CharT>
|
||||
void test(
|
||||
std::basic_format_args<std::basic_format_context<OutIt, CharT>> args) {
|
||||
{
|
||||
std::basic_string<CharT> str;
|
||||
OutIt out_it{str};
|
||||
std::basic_format_context context =
|
||||
test_format_context_create(out_it, args);
|
||||
context.out() = CharT('a');
|
||||
context.out() = CharT('b');
|
||||
context.out() = CharT('c');
|
||||
|
||||
assert(str.size() == 3);
|
||||
assert(str[0] == CharT('a'));
|
||||
assert(str[1] == CharT('b'));
|
||||
assert(str[2] == CharT('c'));
|
||||
}
|
||||
}
|
||||
|
||||
void test() {
|
||||
test(std::basic_format_args(
|
||||
std::make_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<char>>, char>>()));
|
||||
test(std::basic_format_args(
|
||||
std::make_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<wchar_t>>, wchar_t>>()));
|
||||
#ifndef _LIBCPP_HAS_NO_CHAR8_T
|
||||
test(std::basic_format_args(
|
||||
std::make_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<char8_t>>, char8_t>>()));
|
||||
#endif
|
||||
#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
test(std::basic_format_args(
|
||||
std::make_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<char16_t>>,
|
||||
char16_t>>()));
|
||||
test(std::basic_format_args(
|
||||
std::make_format_args<std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<char32_t>>,
|
||||
char32_t>>()));
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// <format>
|
||||
|
||||
// Class typedefs:
|
||||
// template<class Out, class charT>
|
||||
// class basic_format_context {
|
||||
// public:
|
||||
// using iterator = Out
|
||||
// using char_type = charT;
|
||||
// template<class T> using formatter_type = formatter<T, charT>;
|
||||
// }
|
||||
//
|
||||
// Namespace std typedefs:
|
||||
// using format_context = basic_format_context<unspecified, char>;
|
||||
// using wformat_context = basic_format_context<unspecified, wchar_t>;
|
||||
|
||||
#include <format>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class OutIt, class CharT>
|
||||
constexpr void test() {
|
||||
static_assert(
|
||||
std::is_same_v<typename std::basic_format_context<OutIt, CharT>::iterator,
|
||||
OutIt>);
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
typename std::basic_format_context<OutIt, CharT>::char_type, CharT>);
|
||||
static_assert(std::is_same_v<typename std::basic_format_context<
|
||||
OutIt, CharT>::template formatter_type<bool>,
|
||||
std::formatter<bool, CharT>>);
|
||||
static_assert(
|
||||
std::is_same_v<typename std::basic_format_context<
|
||||
OutIt, CharT>::template formatter_type<CharT>,
|
||||
std::formatter<CharT, CharT>>);
|
||||
static_assert(std::is_same_v<typename std::basic_format_context<
|
||||
OutIt, CharT>::template formatter_type<int>,
|
||||
std::formatter<int, CharT>>);
|
||||
static_assert(
|
||||
std::is_same_v<typename std::basic_format_context<
|
||||
OutIt, CharT>::template formatter_type<unsigned>,
|
||||
std::formatter<unsigned, CharT>>);
|
||||
static_assert(
|
||||
std::is_same_v<typename std::basic_format_context<
|
||||
OutIt, CharT>::template formatter_type<long long>,
|
||||
std::formatter<long long, CharT>>);
|
||||
static_assert(
|
||||
std::is_same_v<typename std::basic_format_context<OutIt, CharT>::
|
||||
template formatter_type<unsigned long long>,
|
||||
std::formatter<unsigned long long, CharT>>);
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
static_assert(
|
||||
std::is_same_v<typename std::basic_format_context<
|
||||
OutIt, CharT>::template formatter_type<__int128_t>,
|
||||
std::formatter<__int128_t, CharT>>);
|
||||
static_assert(
|
||||
std::is_same_v<typename std::basic_format_context<
|
||||
OutIt, CharT>::template formatter_type<__uint128_t>,
|
||||
std::formatter<__uint128_t, CharT>>);
|
||||
#endif
|
||||
static_assert(
|
||||
std::is_same_v<typename std::basic_format_context<
|
||||
OutIt, CharT>::template formatter_type<float>,
|
||||
std::formatter<float, CharT>>);
|
||||
static_assert(
|
||||
std::is_same_v<typename std::basic_format_context<
|
||||
OutIt, CharT>::template formatter_type<double>,
|
||||
std::formatter<double, CharT>>);
|
||||
static_assert(
|
||||
std::is_same_v<typename std::basic_format_context<
|
||||
OutIt, CharT>::template formatter_type<long double>,
|
||||
std::formatter<long double, CharT>>);
|
||||
static_assert(
|
||||
std::is_same_v<typename std::basic_format_context<
|
||||
OutIt, CharT>::template formatter_type<const CharT*>,
|
||||
std::formatter<const CharT*, CharT>>);
|
||||
static_assert(
|
||||
std::is_same_v<typename std::basic_format_context<OutIt, CharT>::
|
||||
template formatter_type<std::basic_string_view<CharT>>,
|
||||
std::formatter<std::basic_string_view<CharT>, CharT>>);
|
||||
static_assert(
|
||||
std::is_same_v<typename std::basic_format_context<
|
||||
OutIt, CharT>::template formatter_type<const void*>,
|
||||
std::formatter<const void*, CharT>>);
|
||||
}
|
||||
|
||||
constexpr void test() {
|
||||
test<std::back_insert_iterator<std::basic_string<char>>, char>();
|
||||
test<std::back_insert_iterator<std::basic_string<wchar_t>>, wchar_t>();
|
||||
test<std::back_insert_iterator<std::basic_string<char8_t>>, char8_t>();
|
||||
test<std::back_insert_iterator<std::basic_string<char16_t>>, char16_t>();
|
||||
test<std::back_insert_iterator<std::basic_string<char32_t>>, char32_t>();
|
||||
}
|
||||
|
||||
static_assert(std::is_same_v<
|
||||
std::format_context,
|
||||
std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<char>>, char>>);
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
std::wformat_context,
|
||||
std::basic_format_context<
|
||||
std::back_insert_iterator<std::basic_string<wchar_t>>, wchar_t>>);
|
||||
|
||||
// Required for MSVC internal test runner compatibility.
|
||||
int main(int, char**) { return 0; }
|
||||
@@ -0,0 +1,33 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-format
|
||||
|
||||
// constexpr void check_arg_id(size_t id);
|
||||
|
||||
#include <format>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
constexpr bool test() {
|
||||
// [format.parse.ctx]/11
|
||||
// Remarks: Call expressions where id >= num_args_ are not
|
||||
// core constant expressions ([expr.const]).
|
||||
std::format_parse_context context("", 0);
|
||||
context.check_arg_id(1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
// expected-error@+1 {{static_assert expression is not an integral constant expression}}
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
24
libcxx/test/support/test_basic_format_arg.h
Normal file
24
libcxx/test/support/test_basic_format_arg.h
Normal file
@@ -0,0 +1,24 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <concepts>
|
||||
#include <format>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
/// Returns whether the basic_format_arg contains a type T with the expected value.
|
||||
template <class Context, class T>
|
||||
bool test_basic_format_arg(std::basic_format_arg<Context> arg, T expected) {
|
||||
return std::visit_format_arg(
|
||||
[expected](auto a) {
|
||||
if constexpr (std::same_as<decltype(a), T>)
|
||||
return a == expected;
|
||||
else
|
||||
return false;
|
||||
},
|
||||
arg);
|
||||
}
|
||||
62
libcxx/test/support/test_format_context.h
Normal file
62
libcxx/test/support/test_format_context.h
Normal file
@@ -0,0 +1,62 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SUPPORT_TEST_FORMAT_CONTEXT_HPP
|
||||
#define SUPPORT_TEST_FORMAT_CONTEXT_HPP
|
||||
|
||||
/**
|
||||
* @file Helper functions to create a @ref std::basic_format_context.
|
||||
*
|
||||
* Since the standard doesn't specify how a @ref std::basic_format_context is
|
||||
* constructed this is implementation defined. To make the public API tests of
|
||||
* the class generic this header defines helper functions to create the
|
||||
* required object.
|
||||
*
|
||||
* @note This requires every standard library implementation to write their own
|
||||
* helper function. Vendors are encouraged to file a review at
|
||||
* https://reviews.llvm.org/ so their specific implementation can be part of
|
||||
* this file.
|
||||
*/
|
||||
|
||||
#if TEST_STD_VER < 20
|
||||
#error "The format header requires at least C++20"
|
||||
#endif
|
||||
|
||||
#include <format>
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
||||
#include <locale>
|
||||
#endif
|
||||
|
||||
#if defined(_LIBCPP_VERSION)
|
||||
|
||||
/** Creates a std::basic_format_context as-if the formatting function takes no locale. */
|
||||
template <class OutIt, class CharT>
|
||||
std::basic_format_context<OutIt, CharT> test_format_context_create(
|
||||
OutIt out_it,
|
||||
std::basic_format_args<std::basic_format_context<OutIt, CharT>> args) {
|
||||
return std::__format_context_create(std::move(out_it), args);
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
||||
/** Creates a std::basic_format_context as-if the formatting function takes locale. */
|
||||
template <class OutIt, class CharT>
|
||||
std::basic_format_context<OutIt, CharT> test_format_context_create(
|
||||
OutIt out_it,
|
||||
std::basic_format_args<std::basic_format_context<OutIt, CharT>> args,
|
||||
std::locale loc) {
|
||||
return std::__format_context_create(std::move(out_it), args, std::move(loc));
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#error \
|
||||
"Please create a vendor specific version of the test functions and file a review at https://reviews.llvm.org/"
|
||||
#endif
|
||||
|
||||
#endif // SUPPORT_TEST_FORMAT_CONTEXT_HPP
|
||||
Reference in New Issue
Block a user