[libcxx-commits] [libcxx] Enable identification of code that relies on std::char_traits<char16_t>::int_type. (PR #89840)
Tom Honermann via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Apr 23 15:30:51 PDT 2024
https://github.com/tahonermann created https://github.com/llvm/llvm-project/pull/89840
*** DO NOT MERGE ***
See LWG 2959: char_traits<char16_t>::eof is a valid UTF-16 code unit. https://cplusplus.github.io/LWG/issue2959
This change is intended to facilitate the identification of code that depends on the `std::char_traits<char16_t>::int_type` type. As reported by LWG 2959, this type is always `std::uint_least16_t` which, if actually a 16-bit type, is unable to accommodate a value that is not a valid UTF-16 code unit value and therefore usable as a distinct EOF value. This change makes `std::char_traits<char16_t>::int_type` and all member functions that depend on it private such that uses of them will result in compilation failure thereby enabling identification of code that might break if the type were to be changed to a larger type that is capable of storing a distinct EOF value.
This change causes the following `llvm-libc++-shared.cfg.in` tests to fail. This is expected as these types directly exercise `std::char_traits<char16_t>`.
- `std/strings/char.traits/char.traits.specializations/char.traits.specializations.char16_t/eof.pass.cpp`
- `std/strings/char.traits/char.traits.specializations/char.traits.specializations.char16_t/eq_int_type.pass.cpp`
- `std/strings/char.traits/char.traits.specializations/char.traits.specializations.char16_t/not_eof.pass.cpp`
- `std/strings/char.traits/char.traits.specializations/char.traits.specializations.char16_t/to_char_type.pass.cpp`
- `std/strings/char.traits/char.traits.specializations/char.traits.specializations.char16_t/to_int_type.pass.cpp`
- `std/strings/char.traits/char.traits.specializations/char.traits.specializations.char16_t/types.compile.pass.cpp`
- `std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp`
The failure of the last test is interesting. It fails because it attempts to exercise formatting of `std::basic_streambuf<char16_t>`. The C++ standard does not require this specialization to exist. Since libc++ does not support `char16_t` streams, I suspect this test of `std::basic_streambuf<char16_t>` (as well as for `char8_t` and `char32_t`) is not strictly intended.
*** DO NOT MERGE ***
>From 9b80da1fea9d8feef8e1f22c7d875db1e800738c Mon Sep 17 00:00:00 2001
From: Tom Honermann <tom at honermann.net>
Date: Tue, 23 Apr 2024 18:06:11 -0400
Subject: [PATCH] Enable identification of code that relies on
std::char_traits<char16_t>::int_type.
*** DO NOT MERGE ***
See LWG 2959: char_traits<char16_t>::eof is a valid UTF-16 code unit
https://cplusplus.github.io/LWG/issue2959
This change is intended to facilitate the identification of code that depends
on the `std::char_traits<char16_t>::int_type` type. As reported by LWG 2959,
this type is always `std::uint_least16_t` which, if actually a 16-bit type,
is unable to accommodate a value that is not a valid UTF-16 code unit value
and therefore usable as a distinct EOF value. This change makes
`std::char_traits<char16_t>::int_type` and all member functions that depend
on it private such that uses of them will result in compilation failure
thereby enabling identification of code that might break if the type were to
be changed to a larger type that is capable of storing a distinct EOF value.
This change causes the following `llvm-libc++-shared.cfg.in` tests to fail.
This is expected as these types directly exercise `std::char_traits<char16_t>`.
- `std/strings/char.traits/char.traits.specializations/char.traits.specializations.char16_t/eof.pass.cpp`
- `std/strings/char.traits/char.traits.specializations/char.traits.specializations.char16_t/eq_int_type.pass.cpp`
- `std/strings/char.traits/char.traits.specializations/char.traits.specializations.char16_t/not_eof.pass.cpp`
- `std/strings/char.traits/char.traits.specializations/char.traits.specializations.char16_t/to_char_type.pass.cpp`
- `std/strings/char.traits/char.traits.specializations/char.traits.specializations.char16_t/to_int_type.pass.cpp`
- `std/strings/char.traits/char.traits.specializations/char.traits.specializations.char16_t/types.compile.pass.cpp`
- `std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp`
The failure of the last test is interesting. It fails because it attempts
to exercise formatting of `std::basic_streambuf<char16_t>`. The C++ standard
does not require this specialization to exist. Since libc++ does not support
`char16_t` streams, I suspect this test of `std::basic_streambuf<char16_t>`
(as well as for `char8_t` and `char32_t`) is not strictly intended.
*** DO NOT MERGE ***
---
libcxx/include/__string/char_traits.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libcxx/include/__string/char_traits.h b/libcxx/include/__string/char_traits.h
index 47ed1057caaab1..67e760d44c87af 100644
--- a/libcxx/include/__string/char_traits.h
+++ b/libcxx/include/__string/char_traits.h
@@ -331,7 +331,9 @@ char_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __
template <>
struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t> {
using char_type = char16_t;
+private:
using int_type = uint_least16_t;
+public:
using off_type = streamoff;
using pos_type = u16streampos;
using state_type = mbstate_t;
@@ -375,6 +377,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t> {
return __s;
}
+private:
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
return eq_int_type(__c, eof()) ? ~eof() : __c;
}
More information about the libcxx-commits
mailing list