diff options
author | mikhnenko <mikhnenko@yandex-team.com> | 2023-10-19 20:07:54 +0300 |
---|---|---|
committer | mikhnenko <mikhnenko@yandex-team.com> | 2023-10-19 20:43:09 +0300 |
commit | 551e835dcfdbb3255de090d52f01532d0949919b (patch) | |
tree | abafea6f13096357d6428f2331791acacf4b1bce | |
parent | 8f6ce3db4c6eb113f7950898ac756095e7423ca6 (diff) | |
download | ydb-551e835dcfdbb3255de090d52f01532d0949919b.tar.gz |
Import 18 May 2022 4d8268fbf4cd30d39530622b7f1dc487122b4f3c
-rw-r--r-- | build/sysincl/stl-to-libcxx.yml | 1 | ||||
-rw-r--r-- | build/ymake.core.conf | 2 | ||||
-rw-r--r-- | contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h | 293 | ||||
-rw-r--r-- | contrib/libs/cxxsupp/libcxx/include/__format/format_arg_store.h | 251 | ||||
-rw-r--r-- | contrib/libs/cxxsupp/libcxx/include/__format/format_args.h | 43 | ||||
-rw-r--r-- | contrib/libs/cxxsupp/libcxx/include/__format/format_fwd.h | 3 | ||||
-rw-r--r-- | contrib/libs/cxxsupp/libcxx/include/format | 22 | ||||
-rw-r--r-- | contrib/libs/cxxsupp/libcxx/ya.make | 2 |
8 files changed, 437 insertions, 180 deletions
diff --git a/build/sysincl/stl-to-libcxx.yml b/build/sysincl/stl-to-libcxx.yml index 47661b9782..6605bd33ed 100644 --- a/build/sysincl/stl-to-libcxx.yml +++ b/build/sysincl/stl-to-libcxx.yml @@ -361,6 +361,7 @@ - __filesystem/file_time_type.h: contrib/libs/cxxsupp/libcxx/include/__filesystem/file_time_type.h - __format/concepts.h: contrib/libs/cxxsupp/libcxx/include/__format/concepts.h - __format/enable_insertable.h: contrib/libs/cxxsupp/libcxx/include/__format/enable_insertable.h + - __format/format_arg_store.h: contrib/libs/cxxsupp/libcxx/include/__format/format_arg_store.h - __functional/binary_function.h: contrib/libs/cxxsupp/libcxx/include/__functional/binary_function.h - __functional/binary_negate.h: contrib/libs/cxxsupp/libcxx/include/__functional/binary_negate.h - __functional/bind.h: contrib/libs/cxxsupp/libcxx/include/__functional/bind.h diff --git a/build/ymake.core.conf b/build/ymake.core.conf index e42f2ebc90..4a28310160 100644 --- a/build/ymake.core.conf +++ b/build/ymake.core.conf @@ -9,7 +9,7 @@ FAKEID=628318530716 SANDBOX_FAKEID=${FAKEID}.7600000 -CPP_FAKEID=2023-10-17 +CPP_FAKEID=2023-10-18 GO_FAKEID=11100371 ANDROID_FAKEID=2023-05-17 CLANG_TIDY_FAKEID=2023-06-06 diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h b/contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h index 45356b22cd..3c61446378 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h @@ -35,6 +35,14 @@ namespace __format { /// /// @note The 128-bit types are unconditionally in the list to avoid the values /// of the enums to depend on the availability of 128-bit integers. +/// +/// @note The value is stored as a 5-bit value in the __packed_arg_t_bits. This +/// limits the maximum number of elements to 32. +/// When modifying update the test +/// test/libcxx/utilities/format/format.arguments/format.arg/arg_t.compile.pass.cpp +/// It could be packed in 4-bits but that means a new type directly becomes an +/// ABI break. The packed type is 64-bit so this reduces the maximum number of +/// packed elements from 16 to 12. enum class _LIBCPP_ENUM_VIS __arg_t : uint8_t { __none, __boolean, @@ -53,58 +61,151 @@ enum class _LIBCPP_ENUM_VIS __arg_t : uint8_t { __ptr, __handle }; + +inline constexpr unsigned __packed_arg_t_bits = 5; +inline constexpr uint8_t __packed_arg_t_mask = 0x1f; + +inline constexpr unsigned __packed_types_storage_bits = 64; +inline constexpr unsigned __packed_types_max = __packed_types_storage_bits / __packed_arg_t_bits; + +_LIBCPP_HIDE_FROM_ABI +constexpr bool __use_packed_format_arg_store(size_t __size) { return __size <= __packed_types_max; } + +_LIBCPP_HIDE_FROM_ABI +constexpr __arg_t __get_packed_type(uint64_t __types, size_t __id) { + _LIBCPP_ASSERT(__id <= __packed_types_max, ""); + + if (__id > 0) + __types >>= __id * __packed_arg_t_bits; + + return static_cast<__format::__arg_t>(__types & __packed_arg_t_mask); +} + } // 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) { +_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{}); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__monostate_); case __format::__arg_t::__boolean: - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__boolean); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__boolean_); case __format::__arg_t::__char_type: - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__char_type); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__char_type_); case __format::__arg_t::__int: - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__int); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__int_); case __format::__arg_t::__long_long: - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__long_long); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__long_long_); case __format::__arg_t::__i128: -#ifndef _LIBCPP_HAS_NO_INT128 - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__i128); -#else +# ifndef _LIBCPP_HAS_NO_INT128 + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__i128_); +# else __libcpp_unreachable(); -#endif +# endif case __format::__arg_t::__unsigned: - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__unsigned); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__unsigned_); case __format::__arg_t::__unsigned_long_long: - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), - __arg.__unsigned_long_long); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__unsigned_long_long_); case __format::__arg_t::__u128: -#ifndef _LIBCPP_HAS_NO_INT128 - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__u128); -#else - __libcpp_unreachable(); -#endif +# ifndef _LIBCPP_HAS_NO_INT128 + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__u128_); +# else + __libcpp_unreachable(); +# endif case __format::__arg_t::__float: - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__float); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__float_); case __format::__arg_t::__double: - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__double); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__double_); case __format::__arg_t::__long_double: - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__long_double); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__long_double_); case __format::__arg_t::__const_char_type_ptr: - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), - __arg.__const_char_type_ptr); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__const_char_type_ptr_); case __format::__arg_t::__string_view: - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__string_view); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__string_view_); case __format::__arg_t::__ptr: - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__ptr); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__ptr_); case __format::__arg_t::__handle: - return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__handle); + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), + typename basic_format_arg<_Context>::handle{__arg.__value_.__handle_}); } + __libcpp_unreachable(); } +/// Contains the values used in basic_format_arg. +/// +/// This is a separate type so it's possible to store the values and types in +/// separate arrays. +template <class _Context> +class __basic_format_arg_value { + using _CharT = typename _Context::char_type; + +public: + /// Contains the implementation for basic_format_arg::handle. + struct __handle { + template <class _Tp> + _LIBCPP_HIDE_FROM_ABI explicit __handle(const _Tp& __v) noexcept + : __ptr_(_VSTD::addressof(__v)), + __format_([](basic_format_parse_context<_CharT>& __parse_ctx, _Context& __ctx, const void* __ptr) { + using _Formatter = typename _Context::template formatter_type<_Tp>; + using _Qp = conditional_t<requires { _Formatter().format(declval<const _Tp&>(), declval<_Context&>()); }, + const _Tp, _Tp>; + _Formatter __f; + __parse_ctx.advance_to(__f.parse(__parse_ctx)); + __ctx.advance_to(__f.format(*const_cast<_Qp*>(static_cast<const _Tp*>(__ptr)), __ctx)); + }) {} + + const void* __ptr_; + void (*__format_)(basic_format_parse_context<_CharT>&, _Context&, const void*); + }; + + union { + monostate __monostate_; + bool __boolean_; + _CharT __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 _CharT* __const_char_type_ptr_; + basic_string_view<_CharT> __string_view_; + const void* __ptr_; + __handle __handle_; + }; + + // These constructors contain the exact storage type used. If adjustments are + // required, these will be done in __create_format_arg. + + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value() noexcept : __monostate_() {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(bool __value) noexcept : __boolean_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(_CharT __value) noexcept : __char_type_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(int __value) noexcept : __int_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(unsigned __value) noexcept : __unsigned_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(long long __value) noexcept : __long_long_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(unsigned long long __value) noexcept + : __unsigned_long_long_(__value) {} +# ifndef _LIBCPP_HAS_NO_INT128 + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__int128_t __value) noexcept : __i128_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__uint128_t __value) noexcept : __u128_(__value) {} +# endif + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(float __value) noexcept : __float_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(double __value) noexcept : __double_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(long double __value) noexcept : __long_double_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const _CharT* __value) noexcept : __const_char_type_ptr_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(basic_string_view<_CharT> __value) noexcept + : __string_view_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const void* __value) noexcept : __ptr_(__value) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__handle __value) noexcept : __handle_(__value) {} +}; + template <class _Context> class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_arg { public: @@ -131,146 +232,28 @@ private: // .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...> - make_format_args(const _Args&...); - - template <class _Visitor, class _Ctx> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT friend decltype(auto) - visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx> __arg); - - union { - bool __boolean; - 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; - handle __handle; - }; +public: + __basic_format_arg_value<_Context> __value_; __format::__arg_t __type_; - _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(const bool& __v) noexcept - : __boolean(__v), __type_(__format::__arg_t::__boolean) {} - - template <class _Tp> - _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(const _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(const _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(const _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) {} - - template <class _Tp> - requires is_void_v<_Tp> _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(_Tp* __p) noexcept - : __ptr(__p), __type_(__format::__arg_t::__ptr) {} - - template <class _Tp> - _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(const _Tp& __v) noexcept - : __handle(__v), __type_(__format::__arg_t::__handle) {} + _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(__format::__arg_t __type, + __basic_format_arg_value<_Context> __value) noexcept + : __value_(__value), __type_(__type) {} }; template <class _Context> class _LIBCPP_TEMPLATE_VIS basic_format_arg<_Context>::handle { - friend class basic_format_arg<_Context>; - public: _LIBCPP_HIDE_FROM_ABI void format(basic_format_parse_context<char_type>& __parse_ctx, _Context& __ctx) const { - __format_(__parse_ctx, __ctx, __ptr_); + __handle_.__format_(__parse_ctx, __ctx, __handle_.__ptr_); } + _LIBCPP_HIDE_FROM_ABI explicit handle(typename __basic_format_arg_value<_Context>::__handle __handle) noexcept + : __handle_(__handle) {} + private: - const void* __ptr_; - void (*__format_)(basic_format_parse_context<char_type>&, _Context&, const void*); - - template <class _Tp> - _LIBCPP_HIDE_FROM_ABI explicit handle(const _Tp& __v) noexcept - : __ptr_(_VSTD::addressof(__v)), - __format_([](basic_format_parse_context<char_type>& __parse_ctx, _Context& __ctx, const void* __ptr) { - typename _Context::template formatter_type<_Tp> __f; - __parse_ctx.advance_to(__f.parse(__parse_ctx)); - __ctx.advance_to(__f.format(*static_cast<const _Tp*>(__ptr), __ctx)); - }) {} + typename __basic_format_arg_value<_Context>::__handle __handle_; }; #endif //_LIBCPP_STD_VER > 17 diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/format_arg_store.h b/contrib/libs/cxxsupp/libcxx/include/__format/format_arg_store.h new file mode 100644 index 0000000000..28c9c28d96 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__format/format_arg_store.h @@ -0,0 +1,251 @@ +// -*- 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_STORE_H +#define _LIBCPP___FORMAT_FORMAT_ARG_STORE_H + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#include <__config> +#include <__format/concepts.h> +#include <__format/format_arg.h> +#include <cstring> +#include <string> +#include <string_view> +#include <type_traits> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __format { + +/// \returns The @c __arg_t based on the type of the formatting argument. +/// +/// \pre \c __formattable<_Tp, typename _Context::char_type> +template <class _Context, class _Tp> +consteval __arg_t __determine_arg_t(); + +// Boolean +template <class, same_as<bool> _Tp> +consteval __arg_t __determine_arg_t() { + return __arg_t::__boolean; +} + +// Char +template <class _Context, same_as<typename _Context::char_type> _Tp> +consteval __arg_t __determine_arg_t() { + return __arg_t::__char_type; +} +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <class _Context, class _CharT> + requires(same_as<typename _Context::char_type, wchar_t> && same_as<_CharT, char>) +consteval __arg_t __determine_arg_t() { + return __arg_t::__char_type; +} +# endif + +// Signed integers +template <class, __libcpp_signed_integer _Tp> +consteval __arg_t __determine_arg_t() { + if constexpr (sizeof(_Tp) <= sizeof(int)) + return __arg_t::__int; + else if constexpr (sizeof(_Tp) <= sizeof(long long)) + return __arg_t::__long_long; +# ifndef _LIBCPP_HAS_NO_INT128 + else if constexpr (sizeof(_Tp) == sizeof(__int128_t)) + return __arg_t::__i128; +# endif + else + static_assert(sizeof(_Tp) == 0, "an unsupported signed integer was used"); +} + +// Unsigned integers +template <class, __libcpp_unsigned_integer _Tp> +consteval __arg_t __determine_arg_t() { + if constexpr (sizeof(_Tp) <= sizeof(unsigned)) + return __arg_t::__unsigned; + else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long)) + return __arg_t::__unsigned_long_long; +# ifndef _LIBCPP_HAS_NO_INT128 + else if constexpr (sizeof(_Tp) == sizeof(__uint128_t)) + return __arg_t::__u128; +# endif + else + static_assert(sizeof(_Tp) == 0, "an unsupported unsigned integer was used"); +} + +// Floating-point +template <class, same_as<float> _Tp> +consteval __arg_t __determine_arg_t() { + return __arg_t::__float; +} +template <class, same_as<double> _Tp> +consteval __arg_t __determine_arg_t() { + return __arg_t::__double; +} +template <class, same_as<long double> _Tp> +consteval __arg_t __determine_arg_t() { + return __arg_t::__long_double; +} + +// Char pointer +template <class _Context, class _Tp> + requires(same_as<typename _Context::char_type*, _Tp> || same_as<const typename _Context::char_type*, _Tp>) +consteval __arg_t __determine_arg_t() { + return __arg_t::__const_char_type_ptr; +} + +// Char array +template <class _Context, class _Tp> + requires(is_array_v<_Tp> && same_as<_Tp, typename _Context::char_type[extent_v<_Tp>]>) +consteval __arg_t __determine_arg_t() { + return __arg_t::__string_view; +} + +// String view +template <class _Context, class _Tp> + requires(same_as<typename _Context::char_type, typename _Tp::value_type> && + same_as<_Tp, basic_string_view<typename _Tp::value_type, typename _Tp::traits_type>>) +consteval __arg_t __determine_arg_t() { + return __arg_t::__string_view; +} + +// String +template <class _Context, class _Tp> + requires( + same_as<typename _Context::char_type, typename _Tp::value_type> && + same_as<_Tp, basic_string<typename _Tp::value_type, typename _Tp::traits_type, typename _Tp::allocator_type>>) +consteval __arg_t __determine_arg_t() { + return __arg_t::__string_view; +} + +// Pointers +template <class, class _Ptr> + requires(same_as<_Ptr, void*> || same_as<_Ptr, const void*> || same_as<_Ptr, nullptr_t>) +consteval __arg_t __determine_arg_t() { + return __arg_t::__ptr; +} + +// Handle +// +// Note this version can't be constrained avoiding ambiguous overloads. +// That means it can be instantiated by disabled formatters. To solve this, a +// constrained version for not formattable formatters is added. That overload +// is marked as deleted to fail creating a storage type for disabled formatters. +template <class _Context, class _Tp> +consteval __arg_t __determine_arg_t() { + return __arg_t::__handle; +} + +template <class _Context, class _Tp> + requires(!__formattable<_Tp, typename _Context::char_type>) +consteval __arg_t __determine_arg_t() = delete; + +template <class _Context, class _Tp> +_LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp&& __value) noexcept { + constexpr __arg_t __arg = __determine_arg_t<_Context, remove_cvref_t<_Tp>>(); + static_assert(__arg != __arg_t::__none); + + // Not all types can be used to directly initialize the + // __basic_format_arg_value. First handle all types needing adjustment, the + // final else requires no adjustment. + if constexpr (__arg == __arg_t::__char_type) + // On some platforms initializing a wchar_t from a char is a narrowing + // conversion. + return basic_format_arg<_Context>{__arg, static_cast<typename _Context::char_type>(__value)}; + else if constexpr (__arg == __arg_t::__int) + return basic_format_arg<_Context>{__arg, static_cast<int>(__value)}; + else if constexpr (__arg == __arg_t::__long_long) + return basic_format_arg<_Context>{__arg, static_cast<long long>(__value)}; + else if constexpr (__arg == __arg_t::__unsigned) + return basic_format_arg<_Context>{__arg, static_cast<unsigned>(__value)}; + else if constexpr (__arg == __arg_t::__unsigned_long_long) + return basic_format_arg<_Context>{__arg, static_cast<unsigned long long>(__value)}; + else if constexpr (__arg == __arg_t::__string_view) + // Using std::size on a character array will add the NUL-terminator to the size. + if constexpr (is_array_v<remove_cvref_t<_Tp>>) + return basic_format_arg<_Context>{ + __arg, basic_string_view<typename _Context::char_type>{__value, extent_v<remove_cvref_t<_Tp>> - 1}}; + else + // When the _Traits or _Allocator are different an implicit conversion will + // fail. + return basic_format_arg<_Context>{ + __arg, basic_string_view<typename _Context::char_type>{__value.data(), __value.size()}}; + else if constexpr (__arg == __arg_t::__ptr) + return basic_format_arg<_Context>{__arg, static_cast<const void*>(__value)}; + else if constexpr (__arg == __arg_t::__handle) + return basic_format_arg<_Context>{ + __arg, typename __basic_format_arg_value<_Context>::__handle{_VSTD::forward<_Tp>(__value)}}; + else + return basic_format_arg<_Context>{__arg, __value}; +} + +template <class _Context, class... _Args> +_LIBCPP_HIDE_FROM_ABI void __create_packed_storage(uint64_t& __types, __basic_format_arg_value<_Context>* __values, + _Args&&... __args) noexcept { + int __shift = 0; + ( + [&] { + basic_format_arg<_Context> __arg = __create_format_arg<_Context>(_VSTD::forward<_Args>(__args)); + if (__shift != 0) + __types |= static_cast<uint64_t>(__arg.__type_) << __shift; + else + // Assigns the initial value. + __types = static_cast<uint64_t>(__arg.__type_); + __shift += __packed_arg_t_bits; + *__values++ = __arg.__value_; + }(), + ...); +} + +template <class _Context, class... _Args> +_LIBCPP_HIDE_FROM_ABI void __store_basic_format_arg(basic_format_arg<_Context>* __data, _Args&&... __args) noexcept { + ([&] { *__data++ = __create_format_arg<_Context>(_VSTD::forward<_Args>(__args)); }(), ...); +} + +template <class _Context, size_t N> +struct __packed_format_arg_store { + __basic_format_arg_value<_Context> __values_[N]; + uint64_t __types_; +}; + +template <class _Context, size_t N> +struct __unpacked_format_arg_store { + basic_format_arg<_Context> __args_[N]; +}; + +} // namespace __format + +template <class _Context, class... _Args> +struct _LIBCPP_TEMPLATE_VIS __format_arg_store { + _LIBCPP_HIDE_FROM_ABI + __format_arg_store(_Args&&... __args) noexcept { + if constexpr (sizeof...(_Args) != 0) { + if constexpr (__format::__use_packed_format_arg_store(sizeof...(_Args))) + __format::__create_packed_storage(__storage.__types_, __storage.__values_, _VSTD::forward<_Args>(__args)...); + else + __format::__store_basic_format_arg<_Context>(__storage.__args_, _VSTD::forward<_Args>(__args)...); + } + } + + using _Storage = conditional_t<__format::__use_packed_format_arg_store(sizeof...(_Args)), + __format::__packed_format_arg_store<_Context, sizeof...(_Args)>, + __format::__unpacked_format_arg_store<_Context, sizeof...(_Args)>>; + + _Storage __storage; +}; + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMAT_ARG_STORE_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/format_args.h b/contrib/libs/cxxsupp/libcxx/include/__format/format_args.h index 40dde98400..d90dc50acb 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/format_args.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/format_args.h @@ -12,8 +12,11 @@ #include <__availability> #include <__config> +#include <__format/format_arg.h> +#include <__format/format_arg_store.h> #include <__format/format_fwd.h> #include <cstddef> +#include <cstdint> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,29 +29,47 @@ _LIBCPP_BEGIN_NAMESPACE_STD 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_args(const __format_arg_store<_Context, _Args...>& __store) noexcept + : __size_(sizeof...(_Args)) { + if constexpr (sizeof...(_Args) != 0) { + if constexpr (__format::__use_packed_format_arg_store(sizeof...(_Args))) { + __values_ = __store.__storage.__values_; + __types_ = __store.__storage.__types_; + } else + __args_ = __store.__storage.__args_; + } + } _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> get(size_t __id) const noexcept { - return __id < __size_ ? __data_[__id] : basic_format_arg<_Context>{}; + if (__id >= __size_) + return basic_format_arg<_Context>{}; + + if (__format::__use_packed_format_arg_store(__size_)) + return basic_format_arg<_Context>{__format::__get_packed_type(__types_, __id), __values_[__id]}; + + return __args_[__id]; } _LIBCPP_HIDE_FROM_ABI size_t __size() const noexcept { return __size_; } private: size_t __size_{0}; - const basic_format_arg<_Context>* __data_{nullptr}; + // [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] + union { + struct { + const __basic_format_arg_value<_Context>* __values_; + uint64_t __types_; + }; + const basic_format_arg<_Context>* __args_; + }; }; #endif //_LIBCPP_STD_VER > 17 diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/format_fwd.h b/contrib/libs/cxxsupp/libcxx/include/__format/format_fwd.h index 908d10dbc3..f7c72e2121 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/format_fwd.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/format_fwd.h @@ -25,9 +25,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD 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 _OutIt, class _CharT> requires output_iterator<_OutIt, const _CharT&> class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context; diff --git a/contrib/libs/cxxsupp/libcxx/include/format b/contrib/libs/cxxsupp/libcxx/include/format index 070bfe286f..55ce2b18a9 100644 --- a/contrib/libs/cxxsupp/libcxx/include/format +++ b/contrib/libs/cxxsupp/libcxx/include/format @@ -130,6 +130,7 @@ namespace std { #include <__format/concepts.h> #include <__format/enable_insertable.h> #include <__format/format_arg.h> +#include <__format/format_arg_store.h> #include <__format/format_args.h> #include <__format/format_context.h> #include <__format/format_error.h> @@ -176,22 +177,25 @@ using format_args = basic_format_args<format_context>; using wformat_args = basic_format_args<wformat_context>; #endif +// TODO FMT This helper wrapper can probably be removed after P2418 has been +// implemented. 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; -}; +_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> +__make_format_args(_Args&&... __args) { + return _VSTD::__format_arg_store<_Context, _Args...>( + _VSTD::forward<_Args>(__args)...); +} +// TODO FMT After P2418 specify the return type instead of using auto. 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)...}; +_LIBCPP_HIDE_FROM_ABI auto make_format_args(const _Args&... __args) { + return _VSTD::__make_format_args<_Context>(__args...); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +// TODO FMT After P2418 specify the return type instead of using auto. template <class... _Args> -_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> -make_wformat_args(const _Args&... __args) { +_LIBCPP_HIDE_FROM_ABI auto make_wformat_args(const _Args&... __args) { return _VSTD::make_format_args<wformat_context>(__args...); } #endif diff --git a/contrib/libs/cxxsupp/libcxx/ya.make b/contrib/libs/cxxsupp/libcxx/ya.make index d68f266dc5..a672848b92 100644 --- a/contrib/libs/cxxsupp/libcxx/ya.make +++ b/contrib/libs/cxxsupp/libcxx/ya.make @@ -15,7 +15,7 @@ LICENSE_TEXTS(.yandex_meta/licenses.list.txt) VERSION(2022-05-18) -ORIGINAL_SOURCE(https://github.com/llvm/llvm-project/archive/f0e61029506fd63bb300f2dbbd65ba792e4ef3a2.tar.gz) +ORIGINAL_SOURCE(https://github.com/llvm/llvm-project/archive/4d8268fbf4cd30d39530622b7f1dc487122b4f3c.tar.gz) ADDINCL( GLOBAL contrib/libs/cxxsupp/libcxx/include |