diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst index 17a0415a8ad43..ecf6569cf43fb 100644 --- a/libcxx/docs/ReleaseNotes/19.rst +++ b/libcxx/docs/ReleaseNotes/19.rst @@ -56,7 +56,7 @@ Deprecations and Removals the LLVM 19 release while also issuing a deprecation warning). See :ref:`the hardening documentation ` for more details. -- TODO: The base template for ``std::char_traits`` has been removed in LLVM 19. If you are using ``std::char_traits`` with +- The base template for ``std::char_traits`` has been removed in LLVM 19. If you are using ``std::char_traits`` with types other than ``char``, ``wchar_t``, ``char8_t``, ``char16_t``, ``char32_t`` or a custom character type for which you specialized ``std::char_traits``, your code will stop working. The Standard does not mandate that a base template is provided, and such a base template is bound to be incorrect for some types, which could currently cause unexpected behavior diff --git a/libcxx/include/__string/char_traits.h b/libcxx/include/__string/char_traits.h index e3563c57fea0c..8ea9625d07183 100644 --- a/libcxx/include/__string/char_traits.h +++ b/libcxx/include/__string/char_traits.h @@ -72,106 +72,6 @@ exposition-only to document what members a char_traits specialization should pro }; */ -// -// Temporary extension to provide a base template for std::char_traits. -// TODO(LLVM-19): Remove this class. -// -#if !defined(_LIBCPP_CHAR_TRAITS_REMOVE_BASE_SPECIALIZATION) -template -struct _LIBCPP_DEPRECATED_( - "char_traits for T not equal to char, wchar_t, char8_t, char16_t or char32_t is non-standard and is provided " - "for a temporary period. It will be removed in LLVM 19, so please migrate off of it.") char_traits { - using char_type = _CharT; - using int_type = int; - using off_type = streamoff; - using pos_type = streampos; - using state_type = mbstate_t; - - static inline void _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_HIDE_FROM_ABI - assign(char_type& __c1, const char_type& __c2) _NOEXCEPT { - __c1 = __c2; - } - static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT { - return __c1 == __c2; - } - static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT { - return __c1 < __c2; - } - - static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int - compare(const char_type* __s1, const char_type* __s2, size_t __n) { - for (; __n; --__n, ++__s1, ++__s2) { - if (lt(*__s1, *__s2)) - return -1; - if (lt(*__s2, *__s1)) - return 1; - } - return 0; - } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) { - size_t __len = 0; - for (; !eq(*__s, char_type(0)); ++__s) - ++__len; - return __len; - } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type* - find(const char_type* __s, size_t __n, const char_type& __a) { - for (; __n; --__n) { - if (eq(*__s, __a)) - return __s; - ++__s; - } - return nullptr; - } - static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* - move(char_type* __s1, const char_type* __s2, size_t __n) { - if (__n == 0) - return __s1; - char_type* __r = __s1; - if (__s1 < __s2) { - for (; __n; --__n, ++__s1, ++__s2) - assign(*__s1, *__s2); - } else if (__s2 < __s1) { - __s1 += __n; - __s2 += __n; - for (; __n; --__n) - assign(*--__s1, *--__s2); - } - return __r; - } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* - copy(char_type* __s1, const char_type* __s2, size_t __n) { - _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2), - "char_traits::copy: source and destination ranges overlap"); - char_type* __r = __s1; - for (; __n; --__n, ++__s1, ++__s2) - assign(*__s1, *__s2); - return __r; - } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* - assign(char_type* __s, size_t __n, char_type __a) { - char_type* __r = __s; - for (; __n; --__n, ++__s) - assign(*__s, __a); - return __r; - } - - static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT { - return eq_int_type(__c, eof()) ? ~eof() : __c; - } - static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT { - return char_type(__c); - } - static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT { - return int_type(__c); - } - static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT { - return __c1 == __c2; - } - static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return int_type(EOF); } -}; -#endif // !defined(_LIBCPP_CHAR_TRAITS_REMOVE_BASE_SPECIALIZATION) - // char_traits template <> diff --git a/libcxx/test/libcxx/strings/char.traits/char.traits.specializations/arbitrary_char_type.deprecated.verify.cpp b/libcxx/test/libcxx/strings/char.traits/char.traits.specializations/arbitrary_char_type.deprecated.verify.cpp deleted file mode 100644 index ec6f34ef5462e..0000000000000 --- a/libcxx/test/libcxx/strings/char.traits/char.traits.specializations/arbitrary_char_type.deprecated.verify.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -// - -// template<> struct char_traits for arbitrary T - -// Make sure we issue deprecation warnings. - -#include - -void f() { - std::char_traits t1; (void)t1; // expected-warning{{'char_traits' is deprecated}} - std::char_traits t2; (void)t2; // expected-warning{{'char_traits' is deprecated}} - std::char_traits t3; (void)t3; // expected-warning{{'char_traits' is deprecated}} -} diff --git a/libcxx/test/libcxx/strings/char.traits/char.traits.specializations/arbitrary_char_type.pass.cpp b/libcxx/test/libcxx/strings/char.traits/char.traits.specializations/arbitrary_char_type.pass.cpp deleted file mode 100644 index c2de29d22b2fe..0000000000000 --- a/libcxx/test/libcxx/strings/char.traits/char.traits.specializations/arbitrary_char_type.pass.cpp +++ /dev/null @@ -1,146 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -// - -// template<> struct char_traits for arbitrary T - -// Non-standard but provided temporarily for users to migrate. - -// ADDITIONAL_COMPILE_FLAGS: -Wno-deprecated - -#include -#include -#include - -#include "test_macros.h" - -template -TEST_CONSTEXPR_CXX20 bool test() { - static_assert(std::is_same::char_type, Char>::value, ""); - static_assert(std::is_same::int_type, int>::value, ""); - static_assert(std::is_same::off_type, std::streamoff>::value, ""); - static_assert(std::is_same::pos_type, std::streampos>::value, ""); - static_assert(std::is_same::state_type, std::mbstate_t>::value, ""); - - assert(std::char_traits::to_int_type(Char('a')) == Char('a')); - assert(std::char_traits::to_int_type(Char('A')) == Char('A')); - assert(std::char_traits::to_int_type(0) == 0); - - assert(std::char_traits::to_char_type(Char('a')) == Char('a')); - assert(std::char_traits::to_char_type(Char('A')) == Char('A')); - assert(std::char_traits::to_char_type(0) == 0); - - assert(std::char_traits::eof() == EOF); - - assert(std::char_traits::not_eof(Char('a')) == Char('a')); - assert(std::char_traits::not_eof(Char('A')) == Char('A')); - assert(std::char_traits::not_eof(0) == 0); - assert(std::char_traits::not_eof(std::char_traits::eof()) != - std::char_traits::eof()); - - assert(std::char_traits::lt(Char('\0'), Char('A')) == (Char('\0') < Char('A'))); - assert(std::char_traits::lt(Char('A'), Char('\0')) == (Char('A') < Char('\0'))); - assert(std::char_traits::lt(Char('a'), Char('a')) == (Char('a') < Char('a'))); - assert(std::char_traits::lt(Char('A'), Char('a')) == (Char('A') < Char('a'))); - assert(std::char_traits::lt(Char('a'), Char('A')) == (Char('a') < Char('A'))); - - assert( std::char_traits::eq(Char('a'), Char('a'))); - assert(!std::char_traits::eq(Char('a'), Char('A'))); - - assert( std::char_traits::eq_int_type(Char('a'), Char('a'))); - assert(!std::char_traits::eq_int_type(Char('a'), Char('A'))); - assert(!std::char_traits::eq_int_type(std::char_traits::eof(), Char('A'))); - assert( std::char_traits::eq_int_type(std::char_traits::eof(), std::char_traits::eof())); - - { - Char s1[] = {1, 2, 3, 0}; - Char s2[] = {0}; - assert(std::char_traits::length(s1) == 3); - assert(std::char_traits::length(s2) == 0); - } - - { - Char s1[] = {1, 2, 3}; - assert(std::char_traits::find(s1, 3, Char(1)) == s1); - assert(std::char_traits::find(s1, 3, Char(2)) == s1+1); - assert(std::char_traits::find(s1, 3, Char(3)) == s1+2); - assert(std::char_traits::find(s1, 3, Char(4)) == 0); - assert(std::char_traits::find(s1, 3, Char(0)) == 0); - assert(std::char_traits::find(NULL, 0, Char(0)) == 0); - } - - { - Char s1[] = {1, 2, 3}; - Char s2[3] = {0}; - assert(std::char_traits::copy(s2, s1, 3) == s2); - assert(s2[0] == Char(1)); - assert(s2[1] == Char(2)); - assert(s2[2] == Char(3)); - assert(std::char_traits::copy(NULL, s1, 0) == NULL); - assert(std::char_traits::copy(s1, NULL, 0) == s1); - } - - { - Char s1[] = {1, 2, 3}; - assert(std::char_traits::move(s1, s1+1, 2) == s1); - assert(s1[0] == Char(2)); - assert(s1[1] == Char(3)); - assert(s1[2] == Char(3)); - s1[2] = Char(0); - assert(std::char_traits::move(s1+1, s1, 2) == s1+1); - assert(s1[0] == Char(2)); - assert(s1[1] == Char(2)); - assert(s1[2] == Char(3)); - assert(std::char_traits::move(NULL, s1, 0) == NULL); - assert(std::char_traits::move(s1, NULL, 0) == s1); - } - - { - Char s1[] = {0}; - assert(std::char_traits::compare(s1, s1, 0) == 0); - assert(std::char_traits::compare(NULL, NULL, 0) == 0); - - Char s2[] = {1, 0}; - Char s3[] = {2, 0}; - assert(std::char_traits::compare(s2, s2, 1) == 0); - assert(std::char_traits::compare(s2, s3, 1) < 0); - assert(std::char_traits::compare(s3, s2, 1) > 0); - } - - { - Char s2[3] = {0}; - assert(std::char_traits::assign(s2, 3, Char(5)) == s2); - assert(s2[0] == Char(5)); - assert(s2[1] == Char(5)); - assert(s2[2] == Char(5)); - assert(std::char_traits::assign(NULL, 0, Char(5)) == NULL); - } - - { - Char c = Char('\0'); - std::char_traits::assign(c, Char('a')); - assert(c == Char('a')); - } - - return true; -} - -int main(int, char**) { - test(); - test(); - test(); - -#if TEST_STD_VER > 17 - static_assert(test()); - static_assert(test()); - static_assert(test()); -#endif - - return 0; -}