diff options
author | Mark de Wever <koraq@xs4all.nl> | 2023-11-29 17:55:09 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-29 17:55:09 +0100 |
commit | 16b8c9608f2081c4f5a9beab6432c4aed842f2f8 (patch) | |
tree | c76d3c75a9b821d218185e5a3b9e5562d76d9c64 /libcxx/include/__format | |
parent | bdecfebce4b0af94b3afa3e20add0b9d232f21ad (diff) | |
download | llvm-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.h | 10 | ||||
-rw-r--r-- | libcxx/include/__format/formatter_char.h | 16 |
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 |