aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Khalyavin <halyavin@gmail.com>2022-04-30 01:06:30 +0300
committerAndrey Khalyavin <halyavin@gmail.com>2022-04-30 01:06:30 +0300
commit53508f15464dfda8cefda38389d55e18d55958cc (patch)
treee2a3fee5d27a1ca195d63924be57e69d933f4cdd
parent84d0f48167dad0467bd26e32b0d876f0b49d62d8 (diff)
downloadydb-53508f15464dfda8cefda38389d55e18d55958cc.tar.gz
Update libc++ to 4684857a (25 Jan 2022).
Notable changes: * enable constexpr in std::common_iterator * add std::basic_format_arg::handle * disable formatter constructors in default template to make errors compile-time rather than runtime-time * implement pointer formatter * implement floating pointer formatter ref:05aacf96e1ad5fc10a5fdd0238b020bbfda51953
-rw-r--r--build/ymake.core.conf2
-rwxr-xr-xcontrib/libs/cxxsupp/libcxx/import2
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h44
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/__format/formatter.h58
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/__format/formatter_bool.h2
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/__format/formatter_floating_point.h717
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/__format/formatter_integer.h24
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/__format/formatter_integral.h2
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/__format/formatter_pointer.h91
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/__format/formatter_string.h10
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/__format/parser_std_format_spec.h261
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/__iterator/common_iterator.h67
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/format162
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/module.modulemap30
14 files changed, 1206 insertions, 266 deletions
diff --git a/build/ymake.core.conf b/build/ymake.core.conf
index 43c2104dc3f..984b1d74f06 100644
--- a/build/ymake.core.conf
+++ b/build/ymake.core.conf
@@ -9,7 +9,7 @@
FAKEID=3141592653
SANDBOX_FAKEID=${FAKEID}.7600000
-CPP_FAKEID=9392427
+CPP_FAKEID=9403851
GO_FAKEID=9336945
ANDROID_FAKEID=8821472
CLANG_TIDY_FAKEID=8625699
diff --git a/contrib/libs/cxxsupp/libcxx/import b/contrib/libs/cxxsupp/libcxx/import
index b8cb8a84e0b..73bee19dbee 100755
--- a/contrib/libs/cxxsupp/libcxx/import
+++ b/contrib/libs/cxxsupp/libcxx/import
@@ -1,6 +1,6 @@
#!/bin/sh -e
-rev=a2afc824
+rev=4684857a
output_dir="libcxx-r$rev"
if [ -z $1 ] ; then
git clone https://github.com/llvm/llvm-project.git --no-checkout "$output_dir/tmp"
diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h b/contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h
index 59429c13d41..da829d52fbf 100644
--- a/contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h
+++ b/contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h
@@ -14,7 +14,9 @@
#include <__config>
#include <__format/format_error.h>
#include <__format/format_fwd.h>
+#include <__format/format_parse_context.h>
#include <__functional_base>
+#include <__memory/addressof.h>
#include <__variant/monostate.h>
#include <string>
#include <string_view>
@@ -56,7 +58,8 @@ enum class _LIBCPP_ENUM_VIS __arg_t : uint8_t {
__long_double,
__const_char_type_ptr,
__string_view,
- __ptr
+ __ptr,
+ __handle
};
} // namespace __format
@@ -104,6 +107,8 @@ visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__string_view);
case __format::__arg_t::__ptr:
return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__ptr);
+ case __format::__arg_t::__handle:
+ return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__handle);
}
_LIBCPP_UNREACHABLE();
}
@@ -111,8 +116,7 @@ visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) {
template <class _Context>
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_arg {
public:
- // TODO FMT Define the handle class.
- class handle;
+ class _LIBCPP_TEMPLATE_VIS handle;
_LIBCPP_HIDE_FROM_ABI basic_format_arg() noexcept
: __type_{__format::__arg_t::__none} {}
@@ -161,7 +165,7 @@ private:
const char_type* __const_char_type_ptr;
basic_string_view<char_type> __string_view;
const void* __ptr;
- // TODO FMT Add the handle.
+ handle __handle;
};
__format::__arg_t __type_;
@@ -245,7 +249,37 @@ private:
explicit basic_format_arg(nullptr_t) noexcept
: __ptr(nullptr), __type_(__format::__arg_t::__ptr) {}
- // TODO FMT Implement the _Tp* constructor.
+ 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) {}
+};
+
+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_);
+ }
+
+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));
+ }) {}
};
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/formatter.h b/contrib/libs/cxxsupp/libcxx/include/__format/formatter.h
index 1adce75a861..38b73bba32f 100644
--- a/contrib/libs/cxxsupp/libcxx/include/__format/formatter.h
+++ b/contrib/libs/cxxsupp/libcxx/include/__format/formatter.h
@@ -38,26 +38,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// to support compilers with partial C++20 support.
#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
-// Currently not implemented specializations throw an exception when used. This
-// does not conform to the Standard. However not all Standard defined formatters
-// have been implemented yet. Until that time the current behavior is intended.
-// TODO FMT Disable the default template.
+/// The default formatter template.
+///
+/// [format.formatter.spec]/5
+/// If F is a disabled specialization of formatter, these values are false:
+/// - is_default_constructible_v<F>,
+/// - is_copy_constructible_v<F>,
+/// - is_move_constructible_v<F>,
+/// - is_copy_assignable<F>, and
+/// - is_move_assignable<F>.
template <class _Tp, class _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter {
- _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI auto parse(auto& __parse_ctx)
- -> decltype(__parse_ctx.begin()) {
- __throw();
- }
-
- _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI auto format(_Tp, auto& __ctx)
- -> decltype(__ctx.out()) {
- __throw();
- }
-
-private:
- _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw() {
- __throw_format_error("Argument type not implemented yet");
- }
+ formatter() = delete;
+ formatter(const formatter&) = delete;
+ formatter& operator=(const formatter&) = delete;
};
namespace __format_spec {
@@ -193,6 +187,34 @@ __write(output_iterator<const _CharT&> auto __out_it, const _CharT* __first,
/**
* @overload
*
+ * Writes additional zero's for the precision before the exponent.
+ * This is used when the precision requested in the format string is larger
+ * than the maximum precision of the floating-point type. These precision
+ * digits are always 0.
+ *
+ * @param __exponent The location of the exponent character.
+ * @param __num_trailing_zeros The number of 0's to write before the exponent
+ * character.
+ */
+template <class _CharT, class _Fill>
+_LIBCPP_HIDE_FROM_ABI auto __write(output_iterator<const _CharT&> auto __out_it, const _CharT* __first,
+ const _CharT* __last, size_t __size, size_t __width, _Fill __fill,
+ __format_spec::_Flags::_Alignment __alignment, const _CharT* __exponent,
+ size_t __num_trailing_zeros) -> decltype(__out_it) {
+ _LIBCPP_ASSERT(__first <= __last, "Not a valid range");
+ _LIBCPP_ASSERT(__num_trailing_zeros > 0, "The overload not writing trailing zeros should have been used");
+
+ __padding_size_result __padding = __padding_size(__size + __num_trailing_zeros, __width, __alignment);
+ __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, __fill);
+ __out_it = _VSTD::copy(__first, __exponent, _VSTD::move(__out_it));
+ __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __num_trailing_zeros, _CharT('0'));
+ __out_it = _VSTD::copy(__exponent, __last, _VSTD::move(__out_it));
+ return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill);
+}
+
+/**
+ * @overload
+ *
* Uses a transformation operation before writing an element.
*
* TODO FMT Fill will probably change to support Unicode grapheme cluster.
diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_bool.h b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_bool.h
index fdd1d75355d..1e40bc0a435 100644
--- a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_bool.h
+++ b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_bool.h
@@ -102,7 +102,7 @@ using __formatter_bool = __formatter_integral<__parser_bool<_CharT>>;
// For each charT, for each cv-unqualified arithmetic type ArithmeticT other
// than char, wchar_t, char8_t, char16_t, or char32_t, a specialization
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<bool, _CharT>
: public __format_spec::__formatter_bool<_CharT> {
using _Base = __format_spec::__formatter_bool<_CharT>;
diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_floating_point.h b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_floating_point.h
new file mode 100644
index 00000000000..2e710b409de
--- /dev/null
+++ b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_floating_point.h
@@ -0,0 +1,717 @@
+// -*- 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_FORMATTER_FLOATING_POINT_H
+#define _LIBCPP___FORMAT_FORMATTER_FLOATING_POINT_H
+
+#include <__algorithm/copy.h>
+#include <__algorithm/copy_n.h>
+#include <__algorithm/fill_n.h>
+#include <__algorithm/find.h>
+#include <__algorithm/min.h>
+#include <__algorithm/rotate.h>
+#include <__algorithm/transform.h>
+#include <__concepts/arithmetic.h>
+#include <__config>
+#include <__debug>
+#include <__format/format_error.h>
+#include <__format/format_fwd.h>
+#include <__format/format_string.h>
+#include <__format/formatter.h>
+#include <__format/formatter_integral.h>
+#include <__format/parser_std_format_spec.h>
+#include <__utility/move.h>
+#include <charconv>
+#include <cmath>
+
+#ifndef _LIBCPP_HAS_NO_LOCALIZATION
+# include <locale>
+#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)
+
+namespace __format_spec {
+
+template <floating_point _Tp>
+_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value) {
+ to_chars_result __r = _VSTD::to_chars(__first, __last, __value);
+ _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small");
+ return __r.ptr;
+}
+
+template <floating_point _Tp>
+_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, chars_format __fmt) {
+ to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __fmt);
+ _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small");
+ return __r.ptr;
+}
+
+template <floating_point _Tp>
+_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, chars_format __fmt, int __precision) {
+ to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __fmt, __precision);
+ _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small");
+ return __r.ptr;
+}
+
+// https://en.cppreference.com/w/cpp/language/types#cite_note-1
+// float min subnormal: +/-0x1p-149 max: +/- 3.402,823,4 10^38
+// double min subnormal: +/-0x1p-1074 max +/- 1.797,693,134,862,315,7 10^308
+// long double (x86) min subnormal: +/-0x1p-16446 max: +/- 1.189,731,495,357,231,765,021 10^4932
+//
+// The maximum number of digits required for the integral part is based on the
+// maximum's value power of 10. Every power of 10 requires one additional
+// decimal digit.
+// The maximum number of digits required for the fractional part is based on
+// the minimal subnormal hexadecimal output's power of 10. Every division of a
+// fraction's binary 1 by 2, requires one additional decimal digit.
+//
+// The maximum size of a formatted value depends on the selected output format.
+// Ignoring the fact the format string can request a precision larger than the
+// values maximum required, these values are:
+//
+// sign 1 code unit
+// __max_integral
+// radix point 1 code unit
+// __max_fractional
+// exponent character 1 code unit
+// sign 1 code unit
+// __max_fractional_value
+// -----------------------------------
+// total 4 code units extra required.
+//
+// TODO FMT Optimize the storage to avoid storing digits that are known to be zero.
+// https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/
+
+// TODO FMT Add long double specialization when to_chars has proper long double support.
+template <class _Tp>
+struct __traits;
+
+template <floating_point _Fp>
+static constexpr size_t __float_buffer_size(int __precision) {
+ using _Traits = __traits<_Fp>;
+ return 4 + _Traits::__max_integral + __precision + _Traits::__max_fractional_value;
+}
+
+template <>
+struct __traits<float> {
+ static constexpr int __max_integral = 38;
+ static constexpr int __max_fractional = 149;
+ static constexpr int __max_fractional_value = 3;
+ static constexpr size_t __stack_buffer_size = 256;
+
+ static constexpr int __hex_precision_digits = 3;
+};
+
+template <>
+struct __traits<double> {
+ static constexpr int __max_integral = 308;
+ static constexpr int __max_fractional = 1074;
+ static constexpr int __max_fractional_value = 4;
+ static constexpr size_t __stack_buffer_size = 1024;
+
+ static constexpr int __hex_precision_digits = 4;
+};
+
+/// Helper class to store the conversion buffer.
+///
+/// Depending on the maxium size required for a value, the buffer is allocated
+/// on the stack or the heap.
+template <floating_point _Fp>
+class _LIBCPP_TEMPLATE_VIS __float_buffer {
+ using _Traits = __traits<_Fp>;
+
+public:
+ // TODO FMT Improve this constructor to do a better estimate.
+ // When using a scientific formatting with a precision of 6 a stack buffer
+ // will always suffice. At the moment that isn't important since floats and
+ // doubles use a stack buffer, unless the precision used in the format string
+ // is large.
+ // When supporting long doubles the __max_integral part becomes 4932 which
+ // may be too much for some platforms. For these cases a better estimate is
+ // required.
+ explicit _LIBCPP_HIDE_FROM_ABI __float_buffer(int __precision)
+ : __precision_(__precision != -1 ? __precision : _Traits::__max_fractional) {
+
+ // When the precision is larger than _Traits::__max_fractional the digits in
+ // the range (_Traits::__max_fractional, precision] will contain the value
+ // zero. There's no need to request to_chars to write these zeros:
+ // - When the value is large a temporary heap buffer needs to be allocated.
+ // - When to_chars writes the values they need to be "copied" to the output:
+ // - char: std::fill on the output iterator is faster than std::copy.
+ // - wchar_t: same argument as char, but additional std::copy won't work.
+ // The input is always a char buffer, so every char in the buffer needs
+ // to be converted from a char to a wchar_t.
+ if (__precision_ > _Traits::__max_fractional) {
+ __num_trailing_zeros_ = __precision_ - _Traits::__max_fractional;
+ __precision_ = _Traits::__max_fractional;
+ }
+
+ __size_ = __format_spec::__float_buffer_size<_Fp>(__precision_);
+ if (__size_ > _Traits::__stack_buffer_size)
+ // The allocated buffer's contents don't need initialization.
+ __begin_ = allocator<char>{}.allocate(__size_);
+ else
+ __begin_ = __buffer_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI ~__float_buffer() {
+ if (__size_ > _Traits::__stack_buffer_size)
+ allocator<char>{}.deallocate(__begin_, __size_);
+ }
+ _LIBCPP_HIDE_FROM_ABI __float_buffer(const __float_buffer&) = delete;
+ _LIBCPP_HIDE_FROM_ABI __float_buffer& operator=(const __float_buffer&) = delete;
+
+ _LIBCPP_HIDE_FROM_ABI char* begin() const { return __begin_; }
+ _LIBCPP_HIDE_FROM_ABI char* end() const { return __begin_ + __size_; }
+
+ _LIBCPP_HIDE_FROM_ABI int __precision() const { return __precision_; }
+ _LIBCPP_HIDE_FROM_ABI int __num_trailing_zeros() const { return __num_trailing_zeros_; }
+ _LIBCPP_HIDE_FROM_ABI void __remove_trailing_zeros() { __num_trailing_zeros_ = 0; }
+
+private:
+ int __precision_;
+ int __num_trailing_zeros_{0};
+ size_t __size_;
+ char* __begin_;
+ char __buffer_[_Traits::__stack_buffer_size];
+};
+
+struct __float_result {
+ /// Points at the beginning of the integral part in the buffer.
+ ///
+ /// When there's no sign character this points at the start of the buffer.
+ char* __integral;
+
+ /// Points at the radix point, when not present it's the same as \ref __last.
+ char* __radix_point;
+
+ /// Points at the exponent character, when not present it's the same as \ref __last.
+ char* __exponent;
+
+ /// Points beyond the last written element in the buffer.
+ char* __last;
+};
+
+/// Finds the position of the exponent character 'e' at the end of the buffer.
+///
+/// Assuming there is an exponent the input will terminate with
+/// eSdd and eSdddd (S = sign, d = digit)
+///
+/// \returns a pointer to the exponent or __last when not found.
+constexpr inline _LIBCPP_HIDE_FROM_ABI char* __find_exponent(char* __first, char* __last) {
+ ptrdiff_t __size = __last - __first;
+ if (__size > 4) {
+ __first = __last - _VSTD::min(__size, ptrdiff_t(6));
+ for (; __first != __last - 3; ++__first) {
+ if (*__first == 'e')
+ return __first;
+ }
+ }
+ return __last;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_default(const __float_buffer<_Fp>& __buffer, _Tp __value,
+ char* __integral) {
+ __float_result __result;
+ __result.__integral = __integral;
+ __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value);
+
+ __result.__exponent = __format_spec::__find_exponent(__result.__integral, __result.__last);
+
+ // Constrains:
+ // - There's at least one decimal digit before the radix point.
+ // - The radix point, when present, is placed before the exponent.
+ __result.__radix_point = _VSTD::find(__result.__integral + 1, __result.__exponent, '.');
+
+ // When the radix point isn't found its position is the exponent instead of
+ // __result.__last.
+ if (__result.__radix_point == __result.__exponent)
+ __result.__radix_point = __result.__last;
+
+ // clang-format off
+ _LIBCPP_ASSERT((__result.__integral != __result.__last) &&
+ (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
+ (__result.__exponent == __result.__last || *__result.__exponent == 'e'),
+ "Post-condition failure.");
+ // clang-format on
+
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_hexadecimal_lower_case(const __float_buffer<_Fp>& __buffer,
+ _Tp __value, int __precision,
+ char* __integral) {
+ __float_result __result;
+ __result.__integral = __integral;
+ if (__precision == -1)
+ __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::hex);
+ else
+ __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::hex, __precision);
+
+ // H = one or more hex-digits
+ // S = sign
+ // D = one or more decimal-digits
+ // When the fractional part is zero and no precision the output is 0p+0
+ // else the output is 0.HpSD
+ // So testing the second position can differentiate between these two cases.
+ char* __first = __integral + 1;
+ if (*__first == '.') {
+ __result.__radix_point = __first;
+ // One digit is the minimum
+ // 0.hpSd
+ // ^-- last
+ // ^---- integral = end of search
+ // ^-------- start of search
+ // 0123456
+ //
+ // Four digits is the maximum
+ // 0.hpSdddd
+ // ^-- last
+ // ^---- integral = end of search
+ // ^-------- start of search
+ // 0123456789
+ static_assert(__traits<_Fp>::__hex_precision_digits <= 4, "Guard against possible underflow.");
+
+ char* __last = __result.__last - 2;
+ __first = __last - __traits<_Fp>::__hex_precision_digits;
+ __result.__exponent = _VSTD::find(__first, __last, 'p');
+ } else {
+ __result.__radix_point = __result.__last;
+ __result.__exponent = __first;
+ }
+
+ // clang-format off
+ _LIBCPP_ASSERT((__result.__integral != __result.__last) &&
+ (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
+ (__result.__exponent != __result.__last && *__result.__exponent == 'p'),
+ "Post-condition failure.");
+ // clang-format on
+
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_hexadecimal_upper_case(const __float_buffer<_Fp>& __buffer,
+ _Tp __value, int __precision,
+ char* __integral) {
+ __float_result __result =
+ __format_spec::__format_buffer_hexadecimal_lower_case(__buffer, __value, __precision, __integral);
+ _VSTD::transform(__result.__integral, __result.__exponent, __result.__integral, __hex_to_upper);
+ *__result.__exponent = 'P';
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_lower_case(const __float_buffer<_Fp>& __buffer,
+ _Tp __value, int __precision,
+ char* __integral) {
+ __float_result __result;
+ __result.__integral = __integral;
+ __result.__last =
+ __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::scientific, __precision);
+
+ char* __first = __integral + 1;
+ _LIBCPP_ASSERT(__first != __result.__last, "No exponent present");
+ if (*__first == '.') {
+ __result.__radix_point = __first;
+ __result.__exponent = __format_spec::__find_exponent(__first + 1, __result.__last);
+ } else {
+ __result.__radix_point = __result.__last;
+ __result.__exponent = __first;
+ }
+
+ // clang-format off
+ _LIBCPP_ASSERT((__result.__integral != __result.__last) &&
+ (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
+ (__result.__exponent != __result.__last && *__result.__exponent == 'e'),
+ "Post-condition failure.");
+ // clang-format on
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_upper_case(const __float_buffer<_Fp>& __buffer,
+ _Tp __value, int __precision,
+ char* __integral) {
+ __float_result __result =
+ __format_spec::__format_buffer_scientific_lower_case(__buffer, __value, __precision, __integral);
+ *__result.__exponent = 'E';
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_fixed(const __float_buffer<_Fp>& __buffer, _Tp __value,
+ int __precision, char* __integral) {
+ __float_result __result;
+ __result.__integral = __integral;
+ __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::fixed, __precision);
+
+ // When there's no precision there's no radix point.
+ // Else the radix point is placed at __precision + 1 from the end.
+ // By converting __precision to a bool the subtraction can be done
+ // unconditionally.
+ __result.__radix_point = __result.__last - (__precision + bool(__precision));
+ __result.__exponent = __result.__last;
+
+ // clang-format off
+ _LIBCPP_ASSERT((__result.__integral != __result.__last) &&
+ (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
+ (__result.__exponent == __result.__last),
+ "Post-condition failure.");
+ // clang-format on
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_lower_case(__float_buffer<_Fp>& __buffer, _Tp __value,
+ int __precision, char* __integral) {
+
+ __buffer.__remove_trailing_zeros();
+
+ __float_result __result;
+ __result.__integral = __integral;
+ __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::general, __precision);
+
+ char* __first = __integral + 1;
+ if (__first == __result.__last) {
+ __result.__radix_point = __result.__last;
+ __result.__exponent = __result.__last;
+ } else {
+ __result.__exponent = __format_spec::__find_exponent(__first, __result.__last);
+ if (__result.__exponent != __result.__last)
+ // In scientific mode if there's a radix point it will always be after
+ // the first digit. (This is the position __first points at).
+ __result.__radix_point = *__first == '.' ? __first : __result.__last;
+ else {
+ // In fixed mode the algorithm truncates trailing spaces and possibly the
+ // radix point. There's no good guess for the position of the radix point
+ // therefore scan the output after the first digit.
+ __result.__radix_point = _VSTD::find(__first, __result.__last, '.');
+ }
+ }
+
+ // clang-format off
+ _LIBCPP_ASSERT((__result.__integral != __result.__last) &&
+ (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
+ (__result.__exponent == __result.__last || *__result.__exponent == 'e'),
+ "Post-condition failure.");
+ // clang-format on
+
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_upper_case(__float_buffer<_Fp>& __buffer, _Tp __value,
+ int __precision, char* __integral) {
+ __float_result __result =
+ __format_spec::__format_buffer_general_lower_case(__buffer, __value, __precision, __integral);
+ if (__result.__exponent != __result.__last)
+ *__result.__exponent = 'E';
+ return __result;
+}
+
+# ifndef _LIBCPP_HAS_NO_LOCALIZATION
+template <class _OutIt, class _Fp, class _CharT>
+_LIBCPP_HIDE_FROM_ABI _OutIt __format_locale_specific_form(_OutIt __out_it, const __float_buffer<_Fp>& __buffer,
+ const __float_result& __result, _VSTD::locale __loc,
+ size_t __width, _Flags::_Alignment __alignment,
+ _CharT __fill) {
+ const auto& __np = use_facet<numpunct<_CharT>>(__loc);
+ string __grouping = __np.grouping();
+ char* __first = __result.__integral;
+ // When no radix point or exponent are present __last will be __result.__last.
+ char* __last = _VSTD::min(__result.__radix_point, __result.__exponent);
+
+ ptrdiff_t __digits = __last - __first;
+ if (!__grouping.empty()) {
+ if (__digits <= __grouping[0])
+ __grouping.clear();
+ else
+ __grouping = __determine_grouping(__digits, __grouping);
+ }
+
+ size_t __size = __result.__last - __buffer.begin() + // Formatted string
+ __buffer.__num_trailing_zeros() + // Not yet rendered zeros
+ __grouping.size() - // Grouping contains one
+ !__grouping.empty(); // additional character
+
+ __formatter::__padding_size_result __padding = {0, 0};
+ bool __zero_padding = __alignment == _Flags::_Alignment::__default;
+ if (__size < __width) {
+ if (__zero_padding) {
+ __alignment = _Flags::_Alignment::__right;
+ __fill = _CharT('0');
+ }
+
+ __padding = __formatter::__padding_size(__size, __width, __alignment);
+ }
+
+ // sign and (zero padding or alignment)
+ if (__zero_padding && __first != __buffer.begin())
+ *__out_it++ = *__buffer.begin();
+ __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, __fill);
+ if (!__zero_padding && __first != __buffer.begin())
+ *__out_it++ = *__buffer.begin();
+
+ // integral part
+ if (__grouping.empty()) {
+ __out_it = _VSTD::copy_n(__first, __digits, _VSTD::move(__out_it));
+ } else {
+ auto __r = __grouping.rbegin();
+ auto __e = __grouping.rend() - 1;
+ _CharT __sep = __np.thousands_sep();
+ // The output is divided in small groups of numbers to write:
+ // - A group before the first separator.
+ // - A separator and a group, repeated for the number of separators.
+ // - A group after the last separator.
+ // This loop achieves that process by testing the termination condition
+ // midway in the loop.
+ while (true) {
+ __out_it = _VSTD::copy_n(__first, *__r, _VSTD::move(__out_it));
+ __first += *__r;
+
+ if (__r == __e)
+ break;
+
+ ++__r;
+ *__out_it++ = __sep;
+ }
+ }
+
+ // fractional part
+ if (__result.__radix_point != __result.__last) {
+ *__out_it++ = __np.decimal_point();
+ __out_it = _VSTD::copy(__result.__radix_point + 1, __result.__exponent, _VSTD::move(__out_it));
+ __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __buffer.__num_trailing_zeros(), _CharT('0'));
+ }
+
+ // exponent
+ if (__result.__exponent != __result.__last)
+ __out_it = _VSTD::copy(__result.__exponent, __result.__last, _VSTD::move(__out_it));
+
+ // alignment
+ return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill);
+}
+
+# endif // _LIBCPP_HAS_NO_LOCALIZATION
+
+template <__formatter::__char_type _CharT>
+class _LIBCPP_TEMPLATE_VIS __formatter_floating_point : public __parser_floating_point<_CharT> {
+public:
+ template <floating_point _Tp>
+ _LIBCPP_HIDE_FROM_ABI auto format(_Tp __value, auto& __ctx) -> decltype(__ctx.out()) {
+ if (this->__width_needs_substitution())
+ this->__substitute_width_arg_id(__ctx.arg(this->__width));
+
+ bool __negative = _VSTD::signbit(__value);
+
+ if (!_VSTD::isfinite(__value)) [[unlikely]]
+ return __format_non_finite(__ctx.out(), __negative, _VSTD::isnan(__value));
+
+ bool __has_precision = this->__has_precision_field();
+ if (this->__precision_needs_substitution())
+ this->__substitute_precision_arg_id(__ctx.arg(this->__precision));
+
+ // Depending on the std-format-spec string the sign and the value
+ // might not be outputted together:
+ // - zero-padding may insert additional '0' characters.
+ // Therefore the value is processed as a non negative value.
+ // The function @ref __insert_sign will insert a '-' when the value was
+ // negative.
+
+ if (__negative)
+ __value = _VSTD::copysign(__value, +1.0);
+
+ // TODO FMT _Fp should just be _Tp when to_chars has proper long double support.
+ using _Fp = conditional_t<same_as<_Tp, long double>, double, _Tp>;
+ // Force the type of the precision to avoid -1 to become an unsigned value.
+ __float_buffer<_Fp> __buffer(__has_precision ? int(this->__precision) : -1);
+ __float_result __result = __format_buffer(__buffer, __value, __negative, __has_precision);
+
+ if (this->__alternate_form && __result.__radix_point == __result.__last) {
+ *__result.__last++ = '.';
+
+ // When there is an exponent the point needs to be moved before the
+ // exponent. When there's no exponent the rotate does nothing. Since
+ // rotate tests whether the operation is a nop, call it unconditionally.
+ _VSTD::rotate(__result.__exponent, __result.__last - 1, __result.__last);
+ __result.__radix_point = __result.__exponent;
+
+ // The radix point is always placed before the exponent.
+ // - No exponent needs to point to the new last.
+ // - An exponent needs to move one position to the right.
+ // So it's safe to increment the value unconditionally.
+ ++__result.__exponent;
+ }
+
+# ifndef _LIBCPP_HAS_NO_LOCALIZATION
+ if (this->__locale_specific_form)
+ return __format_spec::__format_locale_specific_form(__ctx.out(), __buffer, __result, __ctx.locale(),
+ this->__width, this->__alignment, this->__fill);
+# endif
+
+ ptrdiff_t __size = __result.__last - __buffer.begin();
+ int __num_trailing_zeros = __buffer.__num_trailing_zeros();
+ if (__size + __num_trailing_zeros >= this->__width) {
+ if (__num_trailing_zeros && __result.__exponent != __result.__last)
+ // Insert trailing zeros before exponent character.
+ return _VSTD::copy(__result.__exponent, __result.__last,
+ _VSTD::fill_n(_VSTD::copy(__buffer.begin(), __result.__exponent, __ctx.out()),
+ __num_trailing_zeros, _CharT('0')));
+
+ return _VSTD::fill_n(_VSTD::copy(__buffer.begin(), __result.__last, __ctx.out()), __num_trailing_zeros,
+ _CharT('0'));
+ }
+
+ auto __out_it = __ctx.out();
+ char* __first = __buffer.begin();
+ if (this->__alignment == _Flags::_Alignment::__default) {
+ // When there is a sign output it before the padding. Note the __size
+ // doesn't need any adjustment, regardless whether the sign is written
+ // here or in __formatter::__write.
+ if (__first != __result.__integral)
+ *__out_it++ = *__first++;
+ // After the sign is written, zero padding is the same a right alignment
+ // with '0'.
+ this->__alignment = _Flags::_Alignment::__right;
+ this->__fill = _CharT('0');
+ }
+
+ if (__num_trailing_zeros)
+ return __formatter::__write(_VSTD::move(__out_it), __first, __result.__last, __size, this->__width, this->__fill,
+ this->__alignment, __result.__exponent, __num_trailing_zeros);
+
+ return __formatter::__write(_VSTD::move(__out_it), __first, __result.__last, __size, this->__width, this->__fill,
+ this->__alignment);
+ }
+
+private:
+ template <class _OutIt>
+ _LIBCPP_HIDE_FROM_ABI _OutIt __format_non_finite(_OutIt __out_it, bool __negative, bool __isnan) {
+ char __buffer[4];
+ char* __last = __insert_sign(__buffer, __negative, this->__sign);
+
+ // to_char can return inf, infinity, nan, and nan(n-char-sequence).
+ // The format library requires inf and nan.
+ // All in one expression to avoid dangling references.
+ __last = _VSTD::copy_n(&("infnanINFNAN"[6 * (this->__type == _Flags::_Type::__float_hexadecimal_upper_case ||
+ this->__type == _Flags::_Type::__scientific_upper_case ||
+ this->__type == _Flags::_Type::__fixed_upper_case ||
+ this->__type == _Flags::_Type::__general_upper_case) +
+ 3 * __isnan]),
+ 3, __last);
+
+ // [format.string.std]/13
+ // A zero (0) character preceding the width field pads the field with
+ // leading zeros (following any indication of sign or base) to the field
+ // width, except when applied to an infinity or NaN.
+ if (this->__alignment == _Flags::_Alignment::__default)
+ this->__alignment = _Flags::_Alignment::__right;
+
+ ptrdiff_t __size = __last - __buffer;
+ if (__size >= this->__width)
+ return _VSTD::copy_n(__buffer, __size, _VSTD::move(__out_it));
+
+ return __formatter::__write(_VSTD::move(__out_it), __buffer, __last, __size, this->__width, this->__fill,
+ this->__alignment);
+ }
+
+ /// Fills the buffer with the data based on the requested formatting.
+ ///
+ /// This function, when needed, turns the characters to upper case and
+ /// determines the "interesting" locations which are returned to the caller.
+ ///
+ /// This means the caller never has to convert the contents of the buffer to
+ /// upper case or search for radix points and the location of the exponent.
+ /// This gives a bit of overhead. The original code didn't do that, but due
+ /// to the number of possible additional work needed to turn this number to
+ /// the proper output the code was littered with tests for upper cases and
+ /// searches for radix points and exponents.
+ /// - When a precision larger than the type's precision is selected
+ /// additional zero characters need to be written before the exponent.
+ /// - alternate form needs to add a radix point when not present.
+ /// - localization needs to do grouping in the integral part.
+ template <class _Fp, class _Tp>
+ // TODO FMT _Fp should just be _Tp when to_chars has proper long double support.
+ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer(__float_buffer<_Fp>& __buffer, _Tp __value, bool __negative,
+ bool __has_precision) {
+ char* __first = __insert_sign(__buffer.begin(), __negative, this->__sign);
+ switch (this->__type) {
+ case _Flags::_Type::__default:
+ return __format_spec::__format_buffer_default(__buffer, __value, __first);
+
+ case _Flags::_Type::__float_hexadecimal_lower_case:
+ return __format_spec::__format_buffer_hexadecimal_lower_case(
+ __buffer, __value, __has_precision ? __buffer.__precision() : -1, __first);
+
+ case _Flags::_Type::__float_hexadecimal_upper_case:
+ return __format_spec::__format_buffer_hexadecimal_upper_case(
+ __buffer, __value, __has_precision ? __buffer.__precision() : -1, __first);
+
+ case _Flags::_Type::__scientific_lower_case:
+ return __format_spec::__format_buffer_scientific_lower_case(__buffer, __value, __buffer.__precision(), __first);
+
+ case _Flags::_Type::__scientific_upper_case:
+ return __format_spec::__format_buffer_scientific_upper_case(__buffer, __value, __buffer.__precision(), __first);
+
+ case _Flags::_Type::__fixed_lower_case:
+ case _Flags::_Type::__fixed_upper_case:
+ return __format_spec::__format_buffer_fixed(__buffer, __value, __buffer.__precision(), __first);
+
+ case _Flags::_Type::__general_lower_case:
+ return __format_spec::__format_buffer_general_lower_case(__buffer, __value, __buffer.__precision(), __first);
+
+ case _Flags::_Type::__general_upper_case:
+ return __format_spec::__format_buffer_general_upper_case(__buffer, __value, __buffer.__precision(), __first);
+
+ default:
+ _LIBCPP_ASSERT(false, "The parser should have validated the type");
+ _LIBCPP_UNREACHABLE();
+ }
+ }
+};
+
+} //namespace __format_spec
+
+template <__formatter::__char_type _CharT>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<float, _CharT>
+ : public __format_spec::__formatter_floating_point<_CharT> {};
+template <__formatter::__char_type _CharT>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<double, _CharT>
+ : public __format_spec::__formatter_floating_point<_CharT> {};
+template <__formatter::__char_type _CharT>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<long double, _CharT>
+ : public __format_spec::__formatter_floating_point<_CharT> {};
+
+# endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
+
+#endif //_LIBCPP_STD_VER > 17
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___FORMAT_FORMATTER_FLOATING_POINT_H
diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_integer.h b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_integer.h
index 767df36e61e..e1f3d4e3489 100644
--- a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_integer.h
+++ b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_integer.h
@@ -81,25 +81,25 @@ using __formatter_integer = __formatter_integral<__parser_integer<_CharT>>;
// than char, wchar_t, char8_t, char16_t, or char32_t, a specialization
// Signed integral types.
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
formatter<signed char, _CharT>
: public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<short, _CharT>
: public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<int, _CharT>
: public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<long, _CharT>
: public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
formatter<long long, _CharT>
: public __format_spec::__formatter_integer<_CharT> {};
#ifndef _LIBCPP_HAS_NO_INT128
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
formatter<__int128_t, _CharT>
: public __format_spec::__formatter_integer<_CharT> {
@@ -119,28 +119,28 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
#endif
// Unsigned integral types.
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
formatter<unsigned char, _CharT>
: public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
formatter<unsigned short, _CharT>
: public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
formatter<unsigned, _CharT>
: public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
formatter<unsigned long, _CharT>
: public __format_spec::__formatter_integer<_CharT> {};
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
formatter<unsigned long long, _CharT>
: public __format_spec::__formatter_integer<_CharT> {};
#ifndef _LIBCPP_HAS_NO_INT128
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
formatter<__uint128_t, _CharT>
: public __format_spec::__formatter_integer<_CharT> {
diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_integral.h b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_integral.h
index 73e2fed8c0b..f164ee61097 100644
--- a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_integral.h
+++ b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_integral.h
@@ -82,7 +82,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace __format_spec {
/** Wrapper around @ref to_chars, returning the output pointer. */
-template <class _Tp>
+template <integral _Tp>
_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last,
_Tp __value, int __base) {
// TODO FMT Evaluate code overhead due to not calling the internal function
diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_pointer.h b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_pointer.h
new file mode 100644
index 00000000000..aa2eb641c6c
--- /dev/null
+++ b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_pointer.h
@@ -0,0 +1,91 @@
+// -*- 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_FORMATTER_POINTER_H
+#define _LIBCPP___FORMAT_FORMATTER_POINTER_H
+
+#include <__algorithm/copy.h>
+#include <__availability>
+#include <__config>
+#include <__debug>
+#include <__format/format_error.h>
+#include <__format/format_fwd.h>
+#include <__format/formatter.h>
+#include <__format/formatter_integral.h>
+#include <__format/parser_std_format_spec.h>
+#include <__iterator/access.h>
+#include <__nullptr>
+#include <cstdint>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_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)
+
+namespace __format_spec {
+
+template <__formatter::__char_type _CharT>
+class _LIBCPP_TEMPLATE_VIS __formatter_pointer : public __parser_pointer<_CharT> {
+public:
+ _LIBCPP_HIDE_FROM_ABI auto format(const void* __ptr, auto& __ctx) -> decltype(__ctx.out()) {
+ _LIBCPP_ASSERT(this->__alignment != _Flags::_Alignment::__default,
+ "The call to parse should have updated the alignment");
+ if (this->__width_needs_substitution())
+ this->__substitute_width_arg_id(__ctx.arg(this->__width));
+
+ // This code looks a lot like the code to format a hexadecimal integral,
+ // but that code isn't public. Making that code public requires some
+ // refactoring.
+ // TODO FMT Remove code duplication.
+ char __buffer[2 + 2 * sizeof(uintptr_t)];
+ __buffer[0] = '0';
+ __buffer[1] = 'x';
+ char* __last = __to_buffer(__buffer + 2, _VSTD::end(__buffer), reinterpret_cast<uintptr_t>(__ptr), 16);
+
+ unsigned __size = __last - __buffer;
+ if (__size >= this->__width)
+ return _VSTD::copy(__buffer, __last, __ctx.out());
+
+ return __formatter::__write(__ctx.out(), __buffer, __last, __size, this->__width, this->__fill, this->__alignment);
+ }
+};
+
+} // namespace __format_spec
+
+// [format.formatter.spec]/2.4
+// For each charT, the pointer type specializations template<>
+// - struct formatter<nullptr_t, charT>;
+// - template<> struct formatter<void*, charT>;
+// - template<> struct formatter<const void*, charT>;
+template <__formatter::__char_type _CharT>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<nullptr_t, _CharT>
+ : public __format_spec::__formatter_pointer<_CharT> {};
+template <__formatter::__char_type _CharT>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<void*, _CharT>
+ : public __format_spec::__formatter_pointer<_CharT> {};
+template <__formatter::__char_type _CharT>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<const void*, _CharT>
+ : public __format_spec::__formatter_pointer<_CharT> {};
+
+# endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
+
+#endif //_LIBCPP_STD_VER > 17
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___FORMAT_FORMATTER_POINTER_H
diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_string.h b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_string.h
index 75a81f5184a..04950faa4a2 100644
--- a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_string.h
+++ b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_string.h
@@ -64,7 +64,7 @@ public:
// [format.formatter.spec]/2.2 For each charT, the string type specializations
// Formatter const char*.
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
formatter<const _CharT*, _CharT>
: public __format_spec::__formatter_string<_CharT> {
@@ -98,7 +98,7 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
};
// Formatter char*.
-template <class _CharT>
+template <__formatter::__char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
formatter<_CharT*, _CharT> : public formatter<const _CharT*, _CharT> {
using _Base = formatter<const _CharT*, _CharT>;
@@ -110,7 +110,7 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
};
// Formatter const char[].
-template <class _CharT, size_t _Size>
+template <__formatter::__char_type _CharT, size_t _Size>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
formatter<const _CharT[_Size], _CharT>
: public __format_spec::__formatter_string<_CharT> {
@@ -123,7 +123,7 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
};
// Formatter std::string.
-template <class _CharT, class _Traits, class _Allocator>
+template <__formatter::__char_type _CharT, class _Traits, class _Allocator>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT>
: public __format_spec::__formatter_string<_CharT> {
@@ -138,7 +138,7 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
};
// Formatter std::string_view.
-template <class _CharT, class _Traits>
+template <__formatter::__char_type _CharT, class _Traits>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<basic_string_view<_CharT, _Traits>, _CharT>
: public __format_spec::__formatter_string<_CharT> {
using _Base = __format_spec::__formatter_string<_CharT>;
diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/parser_std_format_spec.h b/contrib/libs/cxxsupp/libcxx/include/__format/parser_std_format_spec.h
index 6eae27d9ad1..9d893e9ced2 100644
--- a/contrib/libs/cxxsupp/libcxx/include/__format/parser_std_format_spec.h
+++ b/contrib/libs/cxxsupp/libcxx/include/__format/parser_std_format_spec.h
@@ -476,6 +476,21 @@ __parse_type(const _CharT* __begin, _Flags& __flags) {
}
/**
+ * Process the parsed alignment and zero-padding state of arithmetic types.
+ *
+ * [format.string.std]/13
+ * If the 0 character and an align option both appear, the 0 character is
+ * ignored.
+ *
+ * For the formatter a @ref __default alignment means zero-padding.
+ */
+_LIBCPP_HIDE_FROM_ABI constexpr void __process_arithmetic_alignment(_Flags& __flags) {
+ __flags.__zero_padding &= __flags.__alignment == _Flags::_Alignment::__default;
+ if (!__flags.__zero_padding && __flags.__alignment == _Flags::_Alignment::__default)
+ __flags.__alignment = _Flags::_Alignment::__right;
+}
+
+/**
* The parser for the std-format-spec.
*
* [format.string.std]/1 specifies the std-format-spec:
@@ -648,23 +663,9 @@ protected:
return __begin;
}
- /**
- * Handles the post-parsing updates for the integer types.
- *
- * Updates the zero-padding and alignment for integer types.
- *
- * [format.string.std]/13
- * If the 0 character and an align option both appear, the 0 character is
- * ignored.
- *
- * For the formatter a @ref __default alignment means zero-padding. Update
- * the alignment based on parsed format string.
- */
+ /** Handles the post-parsing updates for the integer types. */
_LIBCPP_HIDE_FROM_ABI constexpr void __handle_integer() noexcept {
- this->__zero_padding &= this->__alignment == _Flags::_Alignment::__default;
- if (!this->__zero_padding &&
- this->__alignment == _Flags::_Alignment::__default)
- this->__alignment = _Flags::_Alignment::__right;
+ __process_arithmetic_alignment(static_cast<_Flags&>(*this));
}
/**
@@ -701,8 +702,232 @@ protected:
}
};
-// TODO FMT Add a parser for floating-point values.
-// TODO FMT Add a parser for pointer values.
+/**
+ * The parser for the std-format-spec.
+ *
+ * This implements the parser for the floating-point types.
+ *
+ * See @ref __parser_string.
+ */
+template <class _CharT>
+class _LIBCPP_TEMPLATE_VIS __parser_floating_point
+ : public __parser_width, // provides __width(|as_arg)
+ public __parser_precision, // provides __precision(|as_arg)
+ public __parser_fill_align<_CharT>, // provides __fill and uses __flags
+ public _Flags // provides __flags
+{
+public:
+ using char_type = _CharT;
+
+ /**
+ * The low-level std-format-spec parse function.
+ *
+ * @pre __begin points at the beginning of the std-format-spec. This means
+ * directly after the ':'.
+ * @pre The std-format-spec parses the entire input, or the first unmatched
+ * character is a '}'.
+ *
+ * @returns The iterator pointing at the last parsed character.
+ */
+ _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx)
+ -> decltype(__parse_ctx.begin()) {
+ auto __it = __parse(__parse_ctx);
+ __process_arithmetic_alignment(static_cast<_Flags&>(*this));
+ __process_display_type();
+ return __it;
+ }
+protected:
+ /**
+ * The low-level std-format-spec parse function.
+ *
+ * @pre __begin points at the beginning of the std-format-spec. This means
+ * directly after the ':'.
+ * @pre The std-format-spec parses the entire input, or the first unmatched
+ * character is a '}'.
+ *
+ * @returns The iterator pointing at the last parsed character.
+ */
+ _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx)
+ -> decltype(__parse_ctx.begin()) {
+ auto __begin = __parse_ctx.begin();
+ auto __end = __parse_ctx.end();
+ if (__begin == __end)
+ return __begin;
+
+ __begin = __parser_fill_align<_CharT>::__parse(__begin, __end,
+ static_cast<_Flags&>(*this));
+ if (__begin == __end)
+ return __begin;
+
+ __begin = __parse_sign(__begin, static_cast<_Flags&>(*this));
+ if (__begin == __end)
+ return __begin;
+
+ __begin = __parse_alternate_form(__begin, static_cast<_Flags&>(*this));
+ if (__begin == __end)
+ return __begin;
+
+ __begin = __parse_zero_padding(__begin, static_cast<_Flags&>(*this));
+ if (__begin == __end)
+ return __begin;
+
+ __begin = __parser_width::__parse(__begin, __end, __parse_ctx);
+ if (__begin == __end)
+ return __begin;
+
+ __begin = __parser_precision::__parse(__begin, __end, __parse_ctx);
+ if (__begin == __end)
+ return __begin;
+
+ __begin =
+ __parse_locale_specific_form(__begin, static_cast<_Flags&>(*this));
+ if (__begin == __end)
+ return __begin;
+
+ __begin = __parse_type(__begin, static_cast<_Flags&>(*this));
+
+ if (__begin != __end && *__begin != _CharT('}'))
+ __throw_format_error(
+ "The format-spec should consume the input or end with a '}'");
+
+ return __begin;
+ }
+
+ /** Processes the parsed std-format-spec based on the parsed display type. */
+ _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type() {
+ switch (this->__type) {
+ case _Flags::_Type::__default:
+ // When no precision specified then it keeps default since that
+ // formatting differs from the other types.
+ if (this->__has_precision_field())
+ this->__type = _Flags::_Type::__general_lower_case;
+ break;
+ case _Flags::_Type::__float_hexadecimal_lower_case:
+ case _Flags::_Type::__float_hexadecimal_upper_case:
+ // Precision specific behavior will be handled later.
+ break;
+ case _Flags::_Type::__scientific_lower_case:
+ case _Flags::_Type::__scientific_upper_case:
+ case _Flags::_Type::__fixed_lower_case:
+ case _Flags::_Type::__fixed_upper_case:
+ case _Flags::_Type::__general_lower_case:
+ case _Flags::_Type::__general_upper_case:
+ if (!this->__has_precision_field()) {
+ // Set the default precision for the call to to_chars.
+ this->__precision = 6;
+ this->__precision_as_arg = false;
+ }
+ break;
+
+ default:
+ __throw_format_error("The format-spec type has a type not supported for "
+ "a floating-point argument");
+ }
+ }
+};
+
+/**
+ * The parser for the std-format-spec.
+ *
+ * This implements the parser for the pointer types.
+ *
+ * See @ref __parser_string.
+ */
+template <class _CharT>
+class _LIBCPP_TEMPLATE_VIS __parser_pointer : public __parser_width, // provides __width(|as_arg)
+ public __parser_fill_align<_CharT>, // provides __fill and uses __flags
+ public _Flags // provides __flags
+{
+public:
+ using char_type = _CharT;
+
+ _LIBCPP_HIDE_FROM_ABI constexpr __parser_pointer() {
+ // Implements LWG3612 Inconsistent pointer alignment in std::format.
+ // The issue's current status is "Tentatively Ready" and libc++ status is
+ // still experimental.
+ //
+ // TODO FMT Validate this with the final resolution of LWG3612.
+ this->__alignment = _Flags::_Alignment::__right;
+ }
+
+ /**
+ * The low-level std-format-spec parse function.
+ *
+ * @pre __begin points at the beginning of the std-format-spec. This means
+ * directly after the ':'.
+ * @pre The std-format-spec parses the entire input, or the first unmatched
+ * character is a '}'.
+ *
+ * @returns The iterator pointing at the last parsed character.
+ */
+ _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
+ auto __it = __parse(__parse_ctx);
+ __process_display_type();
+ return __it;
+ }
+
+protected:
+ /**
+ * The low-level std-format-spec parse function.
+ *
+ * @pre __begin points at the beginning of the std-format-spec. This means
+ * directly after the ':'.
+ * @pre The std-format-spec parses the entire input, or the first unmatched
+ * character is a '}'.
+ *
+ * @returns The iterator pointing at the last parsed character.
+ */
+ _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) {
+ auto __begin = __parse_ctx.begin();
+ auto __end = __parse_ctx.end();
+ if (__begin == __end)
+ return __begin;
+
+ __begin = __parser_fill_align<_CharT>::__parse(__begin, __end, static_cast<_Flags&>(*this));
+ if (__begin == __end)
+ return __begin;
+
+ // An integer presentation type isn't defined in the Standard.
+ // Since a pointer is formatted as an integer it can be argued it's an
+ // integer presentation type. However there are two LWG-issues asserting it
+ // isn't an integer presentation type:
+ // - LWG3612 Inconsistent pointer alignment in std::format
+ // - LWG3644 std::format does not define "integer presentation type"
+ //
+ // There's a paper to make additional clarifications on the status of
+ // formatting pointers and proposes additional fields to be valid. That
+ // paper hasn't been reviewed by the Committee yet.
+ // - P2510 Formatting pointers
+ //
+ // The current implementation assumes formatting pointers isn't covered by
+ // "integer presentation type".
+ // TODO FMT Apply the LWG-issues/papers after approval/rejection by the Committee.
+
+ __begin = __parser_width::__parse(__begin, __end, __parse_ctx);
+ if (__begin == __end)
+ return __begin;
+
+ __begin = __parse_type(__begin, static_cast<_Flags&>(*this));
+
+ if (__begin != __end && *__begin != _CharT('}'))
+ __throw_format_error("The format-spec should consume the input or end with a '}'");
+
+ return __begin;
+ }
+
+ /** Processes the parsed std-format-spec based on the parsed display type. */
+ _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type() {
+ switch (this->__type) {
+ case _Flags::_Type::__default:
+ this->__type = _Flags::_Type::__pointer;
+ break;
+ case _Flags::_Type::__pointer:
+ break;
+ default:
+ __throw_format_error("The format-spec type has a type not supported for a pointer argument");
+ }
+ }
+};
/** Helper struct returned from @ref __get_string_alignment. */
template <class _CharT>
diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/common_iterator.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/common_iterator.h
index 9a142769e55..df4c7bd18e8 100644
--- a/contrib/libs/cxxsupp/libcxx/include/__iterator/common_iterator.h
+++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/common_iterator.h
@@ -41,7 +41,7 @@ class common_iterator {
: __value(_VSTD::move(__x)) {}
public:
- const iter_value_t<_Iter>* operator->() const {
+ constexpr const iter_value_t<_Iter>* operator->() const noexcept {
return _VSTD::addressof(__value);
}
};
@@ -58,7 +58,7 @@ class common_iterator {
constructible_from<iter_value_t<_Iter>, iter_reference_t<_Iter>> &&
move_constructible<iter_value_t<_Iter>>;
- const iter_value_t<_Iter>& operator*() const {
+ constexpr const iter_value_t<_Iter>& operator*() const noexcept {
return __value;
}
};
@@ -75,7 +75,7 @@ public:
requires convertible_to<const _I2&, _Iter> && convertible_to<const _S2&, _Sent>
constexpr common_iterator(const common_iterator<_I2, _S2>& __other)
: __hold_([&]() -> variant<_Iter, _Sent> {
- _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Constructed from valueless iterator.");
+ _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Attempted to construct from a valueless common_iterator");
if (__other.__hold_.index() == 0)
return variant<_Iter, _Sent>{in_place_index<0>, _VSTD::__unchecked_get<0>(__other.__hold_)};
return variant<_Iter, _Sent>{in_place_index<1>, _VSTD::__unchecked_get<1>(__other.__hold_)};
@@ -85,7 +85,7 @@ public:
requires convertible_to<const _I2&, _Iter> && convertible_to<const _S2&, _Sent> &&
assignable_from<_Iter&, const _I2&> && assignable_from<_Sent&, const _S2&>
common_iterator& operator=(const common_iterator<_I2, _S2>& __other) {
- _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Assigned from valueless iterator.");
+ _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Attempted to assign from a valueless common_iterator");
auto __idx = __hold_.index();
auto __other_idx = __other.__hold_.index();
@@ -105,18 +105,16 @@ public:
return *this;
}
- decltype(auto) operator*()
+ constexpr decltype(auto) operator*()
{
- _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_),
- "Cannot dereference sentinel. Common iterator not holding an iterator.");
+ _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator");
return *_VSTD::__unchecked_get<_Iter>(__hold_);
}
- decltype(auto) operator*() const
+ constexpr decltype(auto) operator*() const
requires __dereferenceable<const _Iter>
{
- _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_),
- "Cannot dereference sentinel. Common iterator not holding an iterator.");
+ _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator");
return *_VSTD::__unchecked_get<_Iter>(__hold_);
}
@@ -127,9 +125,7 @@ public:
is_reference_v<iter_reference_t<_I2>> ||
constructible_from<iter_value_t<_I2>, iter_reference_t<_I2>>)
{
- _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_),
- "Cannot dereference sentinel. Common iterator not holding an iterator.");
-
+ _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator");
if constexpr (is_pointer_v<_Iter> || requires(const _Iter& __i) { __i.operator->(); }) {
return _VSTD::__unchecked_get<_Iter>(__hold_);
} else if constexpr (is_reference_v<iter_reference_t<_Iter>>) {
@@ -141,15 +137,12 @@ public:
}
common_iterator& operator++() {
- _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_),
- "Cannot increment sentinel. Common iterator not holding an iterator.");
+ _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator");
++_VSTD::__unchecked_get<_Iter>(__hold_); return *this;
}
decltype(auto) operator++(int) {
- _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_),
- "Cannot increment sentinel. Common iterator not holding an iterator.");
-
+ _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator");
if constexpr (forward_iterator<_Iter>) {
auto __tmp = *this;
++*this;
@@ -166,10 +159,9 @@ public:
template<class _I2, sentinel_for<_Iter> _S2>
requires sentinel_for<_Sent, _I2>
- friend bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) {
- _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception() &&
- !__y.__hold_.valueless_by_exception(),
- "One or both common_iterators are valueless. (Cannot compare valueless iterators.)");
+ friend constexpr bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) {
+ _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator");
+ _LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator");
auto __x_index = __x.__hold_.index();
auto __y_index = __y.__hold_.index();
@@ -185,10 +177,9 @@ public:
template<class _I2, sentinel_for<_Iter> _S2>
requires sentinel_for<_Sent, _I2> && equality_comparable_with<_Iter, _I2>
- friend bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) {
- _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception() &&
- !__y.__hold_.valueless_by_exception(),
- "One or both common_iterators are valueless. (Cannot compare valueless iterators.)");
+ friend constexpr bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) {
+ _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator");
+ _LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator");
auto __x_index = __x.__hold_.index();
auto __y_index = __y.__hold_.index();
@@ -207,10 +198,9 @@ public:
template<sized_sentinel_for<_Iter> _I2, sized_sentinel_for<_Iter> _S2>
requires sized_sentinel_for<_Sent, _I2>
- friend iter_difference_t<_I2> operator-(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) {
- _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception() &&
- !__y.__hold_.valueless_by_exception(),
- "One or both common_iterators are valueless. (Cannot subtract valueless iterators.)");
+ friend constexpr iter_difference_t<_I2> operator-(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) {
+ _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to subtract from a valueless common_iterator");
+ _LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to subtract a valueless common_iterator");
auto __x_index = __x.__hold_.index();
auto __y_index = __y.__hold_.index();
@@ -227,24 +217,21 @@ public:
return _VSTD::__unchecked_get<_Sent>(__x.__hold_) - _VSTD::__unchecked_get<_I2>(__y.__hold_);
}
- friend iter_rvalue_reference_t<_Iter> iter_move(const common_iterator& __i)
+ friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const common_iterator& __i)
noexcept(noexcept(ranges::iter_move(declval<const _Iter&>())))
requires input_iterator<_Iter>
{
- _LIBCPP_ASSERT(holds_alternative<_Iter>(__i.__hold_),
- "Cannot iter_move a sentinel. Common iterator not holding an iterator.");
+ _LIBCPP_ASSERT(holds_alternative<_Iter>(__i.__hold_), "Attempted to iter_move a non-dereferenceable common_iterator");
return ranges::iter_move( _VSTD::__unchecked_get<_Iter>(__i.__hold_));
}
template<indirectly_swappable<_Iter> _I2, class _S2>
- friend void iter_swap(const common_iterator& __x, const common_iterator<_I2, _S2>& __y)
+ friend constexpr void iter_swap(const common_iterator& __x, const common_iterator<_I2, _S2>& __y)
noexcept(noexcept(ranges::iter_swap(declval<const _Iter&>(), declval<const _I2&>())))
{
- _LIBCPP_ASSERT(holds_alternative<_Iter>(__x.__hold_),
- "Cannot swap __y with a sentinel. Common iterator (__x) not holding an iterator.");
- _LIBCPP_ASSERT(holds_alternative<_Iter>(__y.__hold_),
- "Cannot swap __x with a sentinel. Common iterator (__y) not holding an iterator.");
- return ranges::iter_swap( _VSTD::__unchecked_get<_Iter>(__x.__hold_), _VSTD::__unchecked_get<_Iter>(__y.__hold_));
+ _LIBCPP_ASSERT(holds_alternative<_Iter>(__x.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator");
+ _LIBCPP_ASSERT(holds_alternative<_I2>(__y.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator");
+ return ranges::iter_swap(_VSTD::__unchecked_get<_Iter>(__x.__hold_), _VSTD::__unchecked_get<_I2>(__y.__hold_));
}
};
@@ -271,7 +258,7 @@ struct __arrow_type_or_void {
template<class _Iter, class _Sent>
requires __common_iter_has_ptr_op<_Iter, _Sent>
struct __arrow_type_or_void<_Iter, _Sent> {
- using type = decltype(declval<const common_iterator<_Iter, _Sent>>().operator->());
+ using type = decltype(declval<const common_iterator<_Iter, _Sent>&>().operator->());
};
template<class _Iter, class _Sent>
diff --git a/contrib/libs/cxxsupp/libcxx/include/format b/contrib/libs/cxxsupp/libcxx/include/format
index 788b9c299ab..4cf146ead17 100644
--- a/contrib/libs/cxxsupp/libcxx/include/format
+++ b/contrib/libs/cxxsupp/libcxx/include/format
@@ -14,43 +14,15 @@
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);
- };
+ template<class Out, class charT> class basic_format_context;
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;
- };
+ template<class Context> class basic_format_args;
using format_args = basic_format_args<format_context>;
using wformat_args = basic_format_args<wformat_context>;
-
// [format.functions], formatting functions
template<class... Args>
string format(string_view fmt, const Args&... args);
@@ -90,8 +62,7 @@ namespace std {
Out out;
iter_difference_t<Out> size;
};
-
- template<class Out, class... Args>
+ template<class Out, class... Args>
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
string_view fmt, const Args&... args);
template<class Out, class... Args>
@@ -116,99 +87,22 @@ namespace std {
size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);
// [format.formatter], formatter
- template<> struct formatter<char, char>;
- template<> struct formatter<char, wchar_t>;
- template<> struct formatter<wchar_t, wchar_t>;
-
- template<> struct formatter<charT*, charT>;
- template<> struct formatter<const charT*, charT>;
- template<size_t N> struct formatter<const charT[N], charT>;
- template<class traits, class Allocator>
- struct formatter<basic_string<charT, traits, Allocator>, charT>;
- template<class traits>
- struct formatter<basic_string_view<charT, traits>, charT>;
+ template<class T, class charT = char> struct formatter;
// [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);
- };
+ template<class charT> class basic_format_parse_context;
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 Context> class basic_format_arg;
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, class... Args> struct format-arg-store; // exposition only
template<class Context = format_context, class... Args>
format-arg-store<Context, Args...>
@@ -218,43 +112,7 @@ namespace std {
make_wformat_args(const Args&... args);
// [format.error], class format_error
- class format_error : public runtime_error {
- public:
- explicit format_error(const string& what_arg);
- explicit format_error(const char* what_arg);
- };
-
- // [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>;
+ class format_error;
}
*/
@@ -277,7 +135,9 @@ namespace std {
#include <__format/formatter.h>
#include <__format/formatter_bool.h>
#include <__format/formatter_char.h>
+#include <__format/formatter_floating_point.h>
#include <__format/formatter_integer.h>
+#include <__format/formatter_pointer.h>
#include <__format/formatter_string.h>
#include <__format/parser_std_format_spec.h>
#include <__variant/monostate.h>
@@ -367,6 +227,8 @@ __handle_replacement_field(const _CharT* __begin, const _CharT* __end,
[&](auto __arg) {
if constexpr (same_as<decltype(__arg), monostate>)
__throw_format_error("Argument index out of bounds");
+ else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)
+ __arg.format(__parse_ctx, __ctx);
else {
formatter<decltype(__arg), _CharT> __formatter;
__parse_ctx.advance_to(__formatter.parse(__parse_ctx));
diff --git a/contrib/libs/cxxsupp/libcxx/include/module.modulemap b/contrib/libs/cxxsupp/libcxx/include/module.modulemap
index a927f9d0e67..90fae9bb836 100644
--- a/contrib/libs/cxxsupp/libcxx/include/module.modulemap
+++ b/contrib/libs/cxxsupp/libcxx/include/module.modulemap
@@ -488,25 +488,27 @@ 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_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" }
- module format_string { private header "__format/format_string.h" }
- module format_to_n_result { private header "__format/format_to_n_result.h" }
- module formatter { private header "__format/formatter.h" }
- module formatter_bool { private header "__format/formatter_bool.h" }
- module formatter_char { private header "__format/formatter_char.h" }
- module formatter_integer { private header "__format/formatter_integer.h" }
- module formatter_integral { private header "__format/formatter_integral.h" }
- module formatter_string { private header "__format/formatter_string.h" }
- module parser_std_format_spec { private header "__format/parser_std_format_spec.h" }
+ 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" }
+ module format_string { private header "__format/format_string.h" }
+ module format_to_n_result { private header "__format/format_to_n_result.h" }
+ module formatter { private header "__format/formatter.h" }
+ module formatter_bool { private header "__format/formatter_bool.h" }
+ module formatter_char { private header "__format/formatter_char.h" }
+ module formatter_floating_point { private header "__format/formatter_floating_point.h" }
+ module formatter_integer { private header "__format/formatter_integer.h" }
+ module formatter_integral { private header "__format/formatter_integral.h" }
+ module formatter_pointer { private header "__format/formatter_pointer.h" }
+ module formatter_string { private header "__format/formatter_string.h" }
+ module parser_std_format_spec { private header "__format/parser_std_format_spec.h" }
}
}
module forward_list {