aboutsummaryrefslogtreecommitdiff
path: root/libcxx/include/__format
diff options
context:
space:
mode:
authorMark de Wever <koraq@xs4all.nl>2023-11-29 17:55:09 +0100
committerGitHub <noreply@github.com>2023-11-29 17:55:09 +0100
commit16b8c9608f2081c4f5a9beab6432c4aed842f2f8 (patch)
treec76d3c75a9b821d218185e5a3b9e5562d76d9c64 /libcxx/include/__format
parentbdecfebce4b0af94b3afa3e20add0b9d232f21ad (diff)
downloadllvm-16b8c9608f2081c4f5a9beab6432c4aed842f2f8.zip
llvm-16b8c9608f2081c4f5a9beab6432c4aed842f2f8.tar.gz
llvm-16b8c9608f2081c4f5a9beab6432c4aed842f2f8.tar.bz2
[libc++][format] Fixes formatting code units as integers. (#73396)
This paper was voted in as a DR, so it's retroactively enabled back to C++20; the C++ version that introduced std::format. Implements: - P2909R4 Fix formatting of code units as integers (Dude, where’s my ``char``?)
Diffstat (limited to 'libcxx/include/__format')
-rw-r--r--libcxx/include/__format/format_arg_store.h10
-rw-r--r--libcxx/include/__format/formatter_char.h16
2 files changed, 14 insertions, 12 deletions
diff --git a/libcxx/include/__format/format_arg_store.h b/libcxx/include/__format/format_arg_store.h
index 15ec8eb..2962962 100644
--- a/libcxx/include/__format/format_arg_store.h
+++ b/libcxx/include/__format/format_arg_store.h
@@ -172,9 +172,13 @@ _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp& __valu
// __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)};
+
+# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+ if constexpr (same_as<typename _Context::char_type, wchar_t> && same_as<_Dp, char>)
+ return basic_format_arg<_Context>{__arg, static_cast<wchar_t>(static_cast<unsigned char>(__value))};
+ else
+# endif
+ return basic_format_arg<_Context>{__arg, __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)
diff --git a/libcxx/include/__format/formatter_char.h b/libcxx/include/__format/formatter_char.h
index d6e61e8..3358d42 100644
--- a/libcxx/include/__format/formatter_char.h
+++ b/libcxx/include/__format/formatter_char.h
@@ -21,7 +21,7 @@
#include <__format/parser_std_format_spec.h>
#include <__format/write_escaped.h>
#include <__type_traits/conditional.h>
-#include <__type_traits/is_signed.h>
+#include <__type_traits/make_unsigned.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -51,22 +51,21 @@ public:
return __formatter::__format_escaped_char(__value, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx));
# endif
- if constexpr (sizeof(_CharT) <= sizeof(int))
- // Promotes _CharT to an integral type. This reduces the number of
- // instantiations of __format_integer reducing code size.
+ if constexpr (sizeof(_CharT) <= sizeof(unsigned))
return __formatter::__format_integer(
- static_cast<conditional_t<is_signed_v<_CharT>, int, unsigned>>(__value),
+ static_cast<unsigned>(static_cast<make_unsigned_t<_CharT>>(__value)),
__ctx,
__parser_.__get_parsed_std_specifications(__ctx));
else
- return __formatter::__format_integer(__value, __ctx, __parser_.__get_parsed_std_specifications(__ctx));
+ return __formatter::__format_integer(
+ static_cast<make_unsigned_t<_CharT>>(__value), __ctx, __parser_.__get_parsed_std_specifications(__ctx));
}
template <class _FormatContext>
_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(char __value, _FormatContext& __ctx) const
requires(same_as<_CharT, wchar_t>)
{
- return format(static_cast<wchar_t>(__value), __ctx);
+ return format(static_cast<wchar_t>(static_cast<unsigned char>(__value)), __ctx);
}
# if _LIBCPP_STD_VER >= 23
@@ -84,8 +83,7 @@ template <>
struct _LIBCPP_TEMPLATE_VIS formatter<char, wchar_t> : public __formatter_char<wchar_t> {};
template <>
-struct _LIBCPP_TEMPLATE_VIS formatter<wchar_t, wchar_t> : public __formatter_char<wchar_t> {
-};
+struct _LIBCPP_TEMPLATE_VIS formatter<wchar_t, wchar_t> : public __formatter_char<wchar_t> {};
# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS