diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -44,6 +44,9 @@ Improvements and New Features ----------------------------- +- Declarations of ``std::c8rtomb()`` and ``std::mbrtoc8()`` from P0482R6 are + now provided when implementations in the global namespace are provided by + the C library. Deprecations and Removals ------------------------- diff --git a/libcxx/docs/Status/Cxx20.rst b/libcxx/docs/Status/Cxx20.rst --- a/libcxx/docs/Status/Cxx20.rst +++ b/libcxx/docs/Status/Cxx20.rst @@ -49,6 +49,8 @@ .. [#note-P0883.1] P0883: shared_ptr and floating-point changes weren't applied as they themselves aren't implemented yet. .. [#note-P0883.2] P0883: ``ATOMIC_FLAG_INIT`` was marked deprecated in version 14.0, but was undeprecated with the implementation of LWG3659 in version 15.0. .. [#note-P2231] P2231: Optional is complete. The changes to variant haven't been implemented yet. + .. [#note-P0482] P0482: Declarations of ``std::pmr::u8string`` and ``std::hash`` are blocked pending implementation + of polymorphic allocator support from P0220. .. _issues-status-cxx20: diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv --- a/libcxx/docs/Status/Cxx20Papers.csv +++ b/libcxx/docs/Status/Cxx20Papers.csv @@ -53,7 +53,7 @@ "`P0318R1 `__","LWG","unwrap_ref_decay and unwrap_reference","San Diego","|Complete|","8.0" "`P0356R5 `__","LWG","Simplified partial function application","San Diego","|Complete|","13.0" "`P0357R3 `__","LWG","reference_wrapper for incomplete types","San Diego","|Complete|","8.0" -"`P0482R6 `__","CWG","char8_t: A type for UTF-8 characters and strings","San Diego","|In Progress|","" +"`P0482R6 `__","CWG","char8_t: A type for UTF-8 characters and strings","San Diego","|Partial| [#note-P0482]_","16.0" "`P0487R1 `__","LWG","Fixing ``operator>>(basic_istream&, CharT*)``\ (LWG 2499)","San Diego","|Complete|","8.0" "`P0591R4 `__","LWG","Utility functions to implement uses-allocator construction","San Diego","* *","" "`P0595R2 `__","CWG","P0595R2 std::is_constant_evaluated()","San Diego","|Complete|","9.0" diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1208,6 +1208,22 @@ # define _LIBCPP_PACKED # endif +// c8rtomb() and mbrtoc8() were added in C++20 and C23. Support for these +// functions is gradually being added to existing C libraries. The conditions +// below check for known C library versions and conditions under which these +// functions are declared by the C library. +# define _LIBCPP_HAS_NO_C8RTOMB_MBRTOC8 +// GNU libc 2.36 and newer declare c8rtomb() and mbrtoc8() in C++ modes if +// __cpp_char8_t is defined or if C2X extensions are enabled. Unfortunately, +// determining the latter depends on internal GNU libc details. If the +// __cpp_char8_t feature test macro is not defined, then a char8_t typedef +// will be declared as well. +# if defined(_LIBCPP_GLIBC_PREREQ) +# if _LIBCPP_GLIBC_PREREQ(2, 36) && (defined(__cpp_char8_t) || __GLIBC_USE(ISOC2X)) +# undef _LIBCPP_HAS_NO_C8RTOMB_MBRTOC8 +# endif +# endif + #endif // __cplusplus #endif // _LIBCPP___CONFIG diff --git a/libcxx/include/cuchar b/libcxx/include/cuchar --- a/libcxx/include/cuchar +++ b/libcxx/include/cuchar @@ -25,6 +25,8 @@ mbstate_t size_t +size_t mbrtoc8(char8_t* pc8, const char* s, size_t n, mbstate_t* ps); // since C++20 +size_t c8rtomb(char* s, char8_t c8, mbstate_t* ps); // since C++20 size_t mbrtoc16(char16_t* pc16, const char* s, size_t n, mbstate_t* ps); size_t c16rtomb(char* s, char16_t c16, mbstate_t* ps); size_t mbrtoc32(char32_t* pc32, const char* s, size_t n, mbstate_t* ps); @@ -58,6 +60,10 @@ using ::mbstate_t _LIBCPP_USING_IF_EXISTS; using ::size_t _LIBCPP_USING_IF_EXISTS; +# if !defined(_LIBCPP_HAS_NO_C8RTOMB_MBRTOC8) +using ::mbrtoc8 _LIBCPP_USING_IF_EXISTS; +using ::c8rtomb _LIBCPP_USING_IF_EXISTS; +# endif using ::mbrtoc16 _LIBCPP_USING_IF_EXISTS; using ::c16rtomb _LIBCPP_USING_IF_EXISTS; using ::mbrtoc32 _LIBCPP_USING_IF_EXISTS; diff --git a/libcxx/include/uchar.h b/libcxx/include/uchar.h --- a/libcxx/include/uchar.h +++ b/libcxx/include/uchar.h @@ -23,6 +23,8 @@ mbstate_t size_t +size_t mbrtoc8(char8_t* pc8, const char* s, size_t n, mbstate_t* ps); // since C++20 +size_t c8rtomb(char* s, char8_t c8, mbstate_t* ps); // since C++20 size_t mbrtoc16(char16_t* pc16, const char* s, size_t n, mbstate_t* ps); size_t c16rtomb(char* s, char16_t c16, mbstate_t* ps); size_t mbrtoc32(char32_t* pc32, const char* s, size_t n, mbstate_t* ps); diff --git a/libcxx/test/std/depr/depr.c.headers/uchar_h.compile.pass.cpp b/libcxx/test/std/depr/depr.c.headers/uchar_h.compile.pass.cpp --- a/libcxx/test/std/depr/depr.c.headers/uchar_h.compile.pass.cpp +++ b/libcxx/test/std/depr/depr.c.headers/uchar_h.compile.pass.cpp @@ -23,6 +23,11 @@ // __STDC_UTF_16__ may or may not be defined by the C standard library // __STDC_UTF_32__ may or may not be defined by the C standard library +#if !defined(TEST_HAS_NO_C8RTOMB_MBRTOC8) +ASSERT_SAME_TYPE(size_t, decltype(mbrtoc8((char8_t*)0, (const char*)0, (size_t)0, (mbstate_t*)0))); +ASSERT_SAME_TYPE(size_t, decltype(c8rtomb((char*)0, (char8_t)0, (mbstate_t*)0))); +#endif + ASSERT_SAME_TYPE(size_t, decltype(mbrtoc16((char16_t*)0, (const char*)0, (size_t)0, (mbstate_t*)0))); ASSERT_SAME_TYPE(size_t, decltype(c16rtomb((char*)0, (char16_t)0, (mbstate_t*)0))); diff --git a/libcxx/test/std/strings/c.strings/cuchar.compile.pass.cpp b/libcxx/test/std/strings/c.strings/cuchar.compile.pass.cpp --- a/libcxx/test/std/strings/c.strings/cuchar.compile.pass.cpp +++ b/libcxx/test/std/strings/c.strings/cuchar.compile.pass.cpp @@ -20,11 +20,14 @@ #include "test_macros.h" -// TODO: Implement mbrtoc8 and c8rtomb, and add tests for those - // __STDC_UTF_16__ may or may not be defined by the C standard library // __STDC_UTF_32__ may or may not be defined by the C standard library +#if !defined(TEST_HAS_NO_C8RTOMB_MBRTOC8) +ASSERT_SAME_TYPE(size_t, decltype(std::mbrtoc8((char8_t*)0, (const char*)0, (size_t)0, (mbstate_t*)0))); +ASSERT_SAME_TYPE(size_t, decltype(std::c8rtomb((char*)0, (char8_t)0, (mbstate_t*)0))); +#endif + ASSERT_SAME_TYPE(size_t, decltype(std::mbrtoc16((char16_t*)0, (const char*)0, (size_t)0, (mbstate_t*)0))); ASSERT_SAME_TYPE(size_t, decltype(std::c16rtomb((char*)0, (char16_t)0, (mbstate_t*)0))); diff --git a/libcxx/test/std/strings/c.strings/no_c8rtomb_mbrtoc8.verify.cpp b/libcxx/test/std/strings/c.strings/no_c8rtomb_mbrtoc8.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/strings/c.strings/no_c8rtomb_mbrtoc8.verify.cpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03 + +// The system-provided seems to be broken on AIX: +// error: 'error' diagnostics seen but not expected: +// File /usr/include/uchar.h Line 38: cannot combine with previous 'type-name' declaration specifier +// File /usr/include/uchar.h Line 39: cannot combine with previous 'type-name' declaration specifier +// 2 errors generated. +// XFAIL: LIBCXX-AIX-FIXME + +#include + +using U = decltype(::c8rtomb); +using V = decltype(::mbrtoc8); +#if defined(_LIBCPP_HAS_NO_C8RTOMB_MBRTOC8) +// expected-error@-3 {{no member named 'c8rtomb' in the global namespace}} +// expected-error@-3 {{no member named 'mbrtoc8' in the global namespace}} +#else +// expected-no-diagnostics +#endif diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h --- a/libcxx/test/support/test_macros.h +++ b/libcxx/test/support/test_macros.h @@ -391,6 +391,10 @@ # define TEST_HAS_NO_FGETPOS_FSETPOS #endif +#if defined(_LIBCPP_HAS_NO_C8RTOMB_MBRTOC8) +# define TEST_HAS_NO_C8RTOMB_MBRTOC8 +#endif + #if defined(TEST_COMPILER_CLANG) # define TEST_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") # define TEST_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")