[v4,2/3] stdlib: Implement mbrtoc8(), c8rtomb(), and the char8_t typedef.

Message ID 20220630125215.6052-3-tom@honermann.net (mailing list archive)
State Committed
Headers
Series C++20 P0482R6 and C2X N2653: char8_t, mbrtoc8(), and c8rtomb() |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent

Commit Message

Tom Honermann June 30, 2022, 12:52 p.m. UTC
  This change provides implementations for the mbrtoc8 and c8rtomb
functions adopted for C++20 via WG21 P0482R6 and for C2X via WG14
N2653.  It also provides the char8_t typedef from WG14 N2653.

The mbrtoc8 and c8rtomb functions are declared in uchar.h in C2X
mode or when the _GNU_SOURCE macro or C++20 __cpp_char8_t feature
test macro is defined.

The char8_t typedef is declared in uchar.h in C2X mode or when the
_GNU_SOURCE macro is defined and the C++20 __cpp_char8_t feature
test macro is not defined (if __cpp_char8_t is defined, then char8_t
is a builtin type).
---
 NEWS                                          |   9 ++
 sysdeps/mach/hurd/i386/libc.abilist           |   2 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |   2 +
 sysdeps/unix/sysv/linux/arc/libc.abilist      |   2 +
 sysdeps/unix/sysv/linux/arm/be/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/arm/le/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/csky/libc.abilist     |   2 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist     |   2 +
 sysdeps/unix/sysv/linux/i386/libc.abilist     |   2 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist     |   2 +
 .../sysv/linux/m68k/coldfire/libc.abilist     |   2 +
 .../unix/sysv/linux/m68k/m680x0/libc.abilist  |   2 +
 .../sysv/linux/microblaze/be/libc.abilist     |   2 +
 .../sysv/linux/microblaze/le/libc.abilist     |   2 +
 .../sysv/linux/mips/mips32/fpu/libc.abilist   |   2 +
 .../sysv/linux/mips/mips32/nofpu/libc.abilist |   2 +
 .../sysv/linux/mips/mips64/n32/libc.abilist   |   2 +
 .../sysv/linux/mips/mips64/n64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist    |   2 +
 sysdeps/unix/sysv/linux/or1k/libc.abilist     |   2 +
 .../linux/powerpc/powerpc32/fpu/libc.abilist  |   2 +
 .../powerpc/powerpc32/nofpu/libc.abilist      |   2 +
 .../linux/powerpc/powerpc64/be/libc.abilist   |   2 +
 .../linux/powerpc/powerpc64/le/libc.abilist   |   2 +
 .../unix/sysv/linux/riscv/rv32/libc.abilist   |   2 +
 .../unix/sysv/linux/riscv/rv64/libc.abilist   |   2 +
 .../unix/sysv/linux/s390/s390-32/libc.abilist |   2 +
 .../unix/sysv/linux/s390/s390-64/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/sh/be/libc.abilist    |   2 +
 sysdeps/unix/sysv/linux/sh/le/libc.abilist    |   2 +
 .../sysv/linux/sparc/sparc32/libc.abilist     |   2 +
 .../sysv/linux/sparc/sparc64/libc.abilist     |   2 +
 .../unix/sysv/linux/x86_64/64/libc.abilist    |   2 +
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |   2 +
 wcsmbs/Makefile                               |   2 +-
 wcsmbs/Versions                               |   3 +
 wcsmbs/c8rtomb.c                              | 132 ++++++++++++++++++
 wcsmbs/mbrtoc8.c                              | 126 +++++++++++++++++
 wcsmbs/uchar.h                                |  21 +++
 40 files changed, 360 insertions(+), 1 deletion(-)
 create mode 100644 wcsmbs/c8rtomb.c
 create mode 100644 wcsmbs/mbrtoc8.c
  

Comments

Adhemerval Zanella July 4, 2022, 6:33 p.m. UTC | #1
> On 30 Jun 2022, at 09:52, Tom Honermann via Libc-alpha <libc-alpha@sourceware.org> wrote:
> 
> This change provides implementations for the mbrtoc8 and c8rtomb
> functions adopted for C++20 via WG21 P0482R6 and for C2X via WG14
> N2653.  It also provides the char8_t typedef from WG14 N2653.
> 
> The mbrtoc8 and c8rtomb functions are declared in uchar.h in C2X
> mode or when the _GNU_SOURCE macro or C++20 __cpp_char8_t feature
> test macro is defined.
> 
> The char8_t typedef is declared in uchar.h in C2X mode or when the
> _GNU_SOURCE macro is defined and the C++20 __cpp_char8_t feature
> test macro is not defined (if __cpp_char8_t is defined, then char8_t
> is a builtin type).

LGTM with a minor nit below.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

> ---
> NEWS                                          |   9 ++
> sysdeps/mach/hurd/i386/libc.abilist           |   2 +
> sysdeps/unix/sysv/linux/aarch64/libc.abilist  |   2 +
> sysdeps/unix/sysv/linux/alpha/libc.abilist    |   2 +
> sysdeps/unix/sysv/linux/arc/libc.abilist      |   2 +
> sysdeps/unix/sysv/linux/arm/be/libc.abilist   |   2 +
> sysdeps/unix/sysv/linux/arm/le/libc.abilist   |   2 +
> sysdeps/unix/sysv/linux/csky/libc.abilist     |   2 +
> sysdeps/unix/sysv/linux/hppa/libc.abilist     |   2 +
> sysdeps/unix/sysv/linux/i386/libc.abilist     |   2 +
> sysdeps/unix/sysv/linux/ia64/libc.abilist     |   2 +
> .../sysv/linux/m68k/coldfire/libc.abilist     |   2 +
> .../unix/sysv/linux/m68k/m680x0/libc.abilist  |   2 +
> .../sysv/linux/microblaze/be/libc.abilist     |   2 +
> .../sysv/linux/microblaze/le/libc.abilist     |   2 +
> .../sysv/linux/mips/mips32/fpu/libc.abilist   |   2 +
> .../sysv/linux/mips/mips32/nofpu/libc.abilist |   2 +
> .../sysv/linux/mips/mips64/n32/libc.abilist   |   2 +
> .../sysv/linux/mips/mips64/n64/libc.abilist   |   2 +
> sysdeps/unix/sysv/linux/nios2/libc.abilist    |   2 +
> sysdeps/unix/sysv/linux/or1k/libc.abilist     |   2 +
> .../linux/powerpc/powerpc32/fpu/libc.abilist  |   2 +
> .../powerpc/powerpc32/nofpu/libc.abilist      |   2 +
> .../linux/powerpc/powerpc64/be/libc.abilist   |   2 +
> .../linux/powerpc/powerpc64/le/libc.abilist   |   2 +
> .../unix/sysv/linux/riscv/rv32/libc.abilist   |   2 +
> .../unix/sysv/linux/riscv/rv64/libc.abilist   |   2 +
> .../unix/sysv/linux/s390/s390-32/libc.abilist |   2 +
> .../unix/sysv/linux/s390/s390-64/libc.abilist |   2 +
> sysdeps/unix/sysv/linux/sh/be/libc.abilist    |   2 +
> sysdeps/unix/sysv/linux/sh/le/libc.abilist    |   2 +
> .../sysv/linux/sparc/sparc32/libc.abilist     |   2 +
> .../sysv/linux/sparc/sparc64/libc.abilist     |   2 +
> .../unix/sysv/linux/x86_64/64/libc.abilist    |   2 +
> .../unix/sysv/linux/x86_64/x32/libc.abilist   |   2 +
> wcsmbs/Makefile                               |   2 +-
> wcsmbs/Versions                               |   3 +
> wcsmbs/c8rtomb.c                              | 132 ++++++++++++++++++
> wcsmbs/mbrtoc8.c                              | 126 +++++++++++++++++
> wcsmbs/uchar.h                                |  21 +++
> 40 files changed, 360 insertions(+), 1 deletion(-)
> create mode 100644 wcsmbs/c8rtomb.c
> create mode 100644 wcsmbs/mbrtoc8.c
> 
> diff --git a/NEWS b/NEWS
> index b0a3d7e512..94243e2170 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -46,6 +46,15 @@ Major new features:
>   to more flexibly configure and operate on filesystem mounts.  The new
>   mount APIs are specifically designed to work with namespaces.
> 
> +* Support for the mbrtoc8 and c8rtomb multibyte/UTF-8 character conversion
> +  functions has been added per the ISO C2X N2653 and C++20 P0482R6 proposals.
> +  Support for the char8_t typedef has been added per the ISO C2X N2653
> +  proposal.  The functions are declared in uchar.h in C2X mode or when the
> +  _GNU_SOURCE macro or C++20 __cpp_char8_t feature test macro is defined.
> +  The char8_t typedef is declared in uchar.h in C2X mode or when the
> +  _GNU_SOURCE macro is defined and the C++20 __cpp_char8_t feature test macro
> +  is not defined (if __cpp_char8_t is defined, then char8_t is a builtin type).
> +
> Deprecated and removed features, and other changes affecting compatibility:
> 
> * Support for prelink will be removed in the next release; this includes
> diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
> index 4dc87e9061..66fb0e28fa 100644
> --- a/sysdeps/mach/hurd/i386/libc.abilist
> +++ b/sysdeps/mach/hurd/i386/libc.abilist
> @@ -2289,6 +2289,8 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 close_range F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.4 __confstr_chk F
> GLIBC_2.4 __fgets_chk F
> GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> index 8dba065b81..b3cf9fdd70 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> @@ -2616,8 +2616,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> index 08f4750022..2a45006462 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> @@ -2713,8 +2713,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
> index 75db763023..0ac6bba241 100644
> --- a/sysdeps/unix/sysv/linux/arc/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
> @@ -2377,8 +2377,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
> index fa33f317ac..bfa763906b 100644
> --- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
> @@ -496,8 +496,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
> index dba2e4ce42..ffcd7ca432 100644
> --- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
> @@ -493,8 +493,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
> index e6ff921c29..940777b118 100644
> --- a/sysdeps/unix/sysv/linux/csky/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
> @@ -2652,8 +2652,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> index 8a40cece83..508efe6626 100644
> --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> @@ -2601,8 +2601,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
> index a89826049f..16b91fcee9 100644
> --- a/sysdeps/unix/sysv/linux/i386/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
> @@ -2785,8 +2785,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> index d1d96b7469..51b646790d 100644
> --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> @@ -2551,8 +2551,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> index 63a62f267a..ddb43651f2 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> @@ -497,8 +497,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> index f68325f9bc..3db7deb4d0 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> @@ -2728,8 +2728,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
> index 247af2075c..94afb7ad0b 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
> @@ -2701,8 +2701,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
> index b0ac3f9009..5873751425 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
> @@ -2698,8 +2698,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> index b22cd6bf2f..f296e4edb7 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> @@ -2693,8 +2693,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> index 12fc2cce3e..1888756819 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> @@ -2691,8 +2691,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> index d3e96dfd43..7dfacee25b 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> @@ -2699,8 +2699,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> index cb58ed4db0..53e188aafe 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> @@ -2602,8 +2602,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> index 61ad58a599..bc6a836b1b 100644
> --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> @@ -2740,8 +2740,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist
> index 1260dc4e2e..299fa67961 100644
> --- a/sysdeps/unix/sysv/linux/or1k/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist
> @@ -2123,8 +2123,10 @@ GLIBC_2.35 wprintf F
> GLIBC_2.35 write F
> GLIBC_2.35 writev F
> GLIBC_2.35 wscanf F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> index 363939762c..a5a072394d 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> @@ -2755,8 +2755,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> index f512ad8baf..2d26fd8639 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> @@ -2788,8 +2788,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> index c9bdc9859c..d9f1c593ea 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> @@ -2510,8 +2510,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> index f091be30bd..874f33dbcc 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> @@ -2812,8 +2812,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
> index 7ea73f9af8..465798a56f 100644
> --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
> @@ -2379,8 +2379,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> index 333fa62714..ecc0544c05 100644
> --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> @@ -2579,8 +2579,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> index a867467b12..3e8d00d513 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> @@ -2753,8 +2753,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> index dbad5b3163..a872a3d186 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> @@ -2547,8 +2547,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
> index 6f755cc173..a2938ca2be 100644
> --- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
> @@ -2608,8 +2608,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
> index 77d936aa3c..ef318251c5 100644
> --- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
> @@ -2605,8 +2605,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> index 09bb4363e1..2e2fbe72e2 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> @@ -2748,8 +2748,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> index 9df9cb6adb..e1991259cd 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> @@ -2574,8 +2574,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> index 4829450ad0..7d0843d1d8 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> @@ -2525,8 +2525,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> index caea228bcb..761958f768 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> @@ -2631,8 +2631,10 @@ GLIBC_2.35 __memcmpeq F
> GLIBC_2.35 _dl_find_object F
> GLIBC_2.35 epoll_pwait2 F
> GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 c8rtomb F
> GLIBC_2.36 fsmount F
> GLIBC_2.36 fsopen F
> +GLIBC_2.36 mbrtoc8 F
> GLIBC_2.36 move_mount F
> GLIBC_2.36 pidfd_getfd F
> GLIBC_2.36 pidfd_open F
> diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
> index df9a85f4a9..bda281ad70 100644
> --- a/wcsmbs/Makefile
> +++ b/wcsmbs/Makefile
> @@ -42,7 +42,7 @@ routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
> 	    wcsmbsload mbsrtowcs_l \
> 	    isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf \
> 	    isoc99_swscanf isoc99_vswscanf \
> -	    mbrtoc16 c16rtomb mbrtoc32 c32rtomb
> +	    mbrtoc8 c8rtomb mbrtoc16 c16rtomb mbrtoc32 c32rtomb
> 
> strop-tests :=  wcscmp wcsncmp wmemcmp wcslen wcschr wcsrchr wcscpy wcsnlen \
> 		wcpcpy wcsncpy wcpncpy wcscat wcsncat wcschrnul wcsspn wcspbrk \
> diff --git a/wcsmbs/Versions b/wcsmbs/Versions
> index 0b31c1b940..ec28acfb73 100644
> --- a/wcsmbs/Versions
> +++ b/wcsmbs/Versions
> @@ -49,4 +49,7 @@ libc {
>     wcstof32; wcstof64; wcstof32x;
>     wcstof32_l; wcstof64_l; wcstof32x_l;
>   }
> +  GLIBC_2.36 {
> +    c8rtomb; mbrtoc8;
> +  }
> }
> diff --git a/wcsmbs/c8rtomb.c b/wcsmbs/c8rtomb.c
> new file mode 100644
> index 0000000000..b564770eb5
> --- /dev/null
> +++ b/wcsmbs/c8rtomb.c
> @@ -0,0 +1,132 @@
> +/* UTF-8 to multibyte conversion.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <errno.h>
> +#include <uchar.h>
> +#include <wchar.h>
> +
> +
> +/* This is the private state used if PS is NULL.  */
> +static mbstate_t state;
> +
> +size_t
> +c8rtomb (char *s, char8_t c8, mbstate_t *ps)
> +{
> +  /* This implementation depends on the converter invoked by wcrtomb not
> +     needing to retain state in either the top most bit of ps->__count or
> +     in ps->__value between invocations.  This implementation uses the
> +     top most bit of ps->__count to indicate that trailing code units are
> +     expected and uses ps->__value to store previously seen code units.  */
> +
> +  wchar_t wc;
> +
> +  if (ps == NULL)
> +    ps = &state;
> +
> +  if (s == NULL)
> +    {
> +      /* if 's' is a null pointer, behave as if u8'\0' was passed as 'c8'.  If
> +         this occurs for an incomplete code unit sequence, then an error will
> +         be reported below.  */
> +      c8 = u8""[0];
> +    }
> +
> +  if (! (ps->__count & 0x80000000))
> +    {
> +      /* Initial state.  */
> +      if ((c8 >= 0x80 && c8 <= 0xC1) || c8 >= 0xF5)
> +	{
> +	  /* An invalid lead code unit.  */
> +	  __set_errno (EILSEQ);
> +	  return -1;
> +	}
> +      if (c8 >= 0xC2)
> +	{
> +	  /* A valid lead code unit.  */
> +	  ps->__count |= 0x80000000;
> +	  ps->__value.__wchb[0] = c8;
> +	  ps->__value.__wchb[3] = 1;
> +	  return 0;
> +	}
> +      /* A single byte (ASCII) code unit.  */
> +      wc = c8;
> +    }
> +  else
> +    {
> +      char8_t cu1 = ps->__value.__wchb[0];
> +      if (ps->__value.__wchb[3] == 1)
> +	{
> +	  /* A single lead code unit was previously seen.  */
> +	  if ((c8 < 0x80 || c8 > 0xBF)
> +              || (cu1 == 0xE0 && c8 < 0xA0)
> +              || (cu1 == 0xED && c8 > 0x9F)
> +              || (cu1 == 0xF0 && c8 < 0x90)
> +              || (cu1 == 0xF4 && c8 > 0x8F))
> +	    {
> +	      /* An invalid second code unit.  */
> +	      __set_errno (EILSEQ);
> +	      return -1;
> +	    }
> +	  if (cu1 >= 0xE0)
> +	    {
> +	      /* A three or four code unit sequence.  */
> +	      ps->__value.__wchb[1] = c8;
> +	      ++ps->__value.__wchb[3];
> +	      return 0;
> +	    }
> +	  wc = ((cu1 & 0x1F) << 6)
> +	       + (c8 & 0x3F);
> +	}
> +      else
> +	{
> +	  char8_t cu2 = ps->__value.__wchb[1];
> +	  /* A three or four byte code unit sequence.  */
> +	  if (c8 < 0x80 || c8 > 0xBF)
> +	    {
> +	      /* An invalid third or fourth code unit.  */
> +	      __set_errno (EILSEQ);
> +	      return -1;
> +	    }
> +	  if (ps->__value.__wchb[3] == 2 && cu1 >= 0xF0)
> +	    {
> +	      /* A four code unit sequence.  */
> +	      ps->__value.__wchb[2] = c8;
> +	      ++ps->__value.__wchb[3];
> +	      return 0;
> +	    }
> +	  if (cu1 < 0xF0)
> +	    {
> +	      wc = ((cu1 & 0x0F) << 12)
> +		   + ((cu2 & 0x3F) << 6)
> +		   + (c8 & 0x3F);
> +	    }
> +	  else
> +	    {
> +	      char8_t cu3 = ps->__value.__wchb[2];
> +	      wc = ((cu1 & 0x07) << 18)
> +		   + ((cu2 & 0x3F) << 12)
> +		   + ((cu3 & 0x3F) << 6)
> +		   + (c8 & 0x3F);
> +	    }
> +	}
> +      ps->__count &= 0x7fffffff;
> +      ps->__value.__wch = 0;
> +    }
> +
> +  return wcrtomb (s, wc, ps);
> +}
> diff --git a/wcsmbs/mbrtoc8.c b/wcsmbs/mbrtoc8.c
> new file mode 100644
> index 0000000000..f2fab3b6a7
> --- /dev/null
> +++ b/wcsmbs/mbrtoc8.c
> @@ -0,0 +1,126 @@
> +/* Multibyte to UTF-8 conversion.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <assert.h>
> +#include <dlfcn.h>
> +#include <errno.h>
> +#include <gconv.h>
> +#include <uchar.h>
> +#include <wcsmbsload.h>
> +
> +#include <sysdep.h>
> +
> +#ifndef EILSEQ
> +# define EILSEQ EINVAL
> +#endif
> +
> +
> +/* This is the private state used if PS is NULL.  */
> +static mbstate_t state;
> +
> +size_t
> +mbrtoc8 (char8_t *pc8, const char *s, size_t n, mbstate_t *ps)
> +{
> +  /* This implementation depends on the converter invoked by mbrtowc() not

Refer to function name without ‘()’.

> +     needing to retain state in either the top most bit of ps->__count or
> +     in ps->__value between invocations.  This implementation uses the
> +     top most bit of ps->__count to indicate that trailing code units are
> +     yet to be written and uses ps->__value to store those code units.  */
> +
> +  if (ps == NULL)
> +    ps = &state;
> +
> +  /* If state indicates that trailing code units are yet to be written, write
> +     those first regardless of whether 's' is a null pointer.  */
> +  if (ps->__count & 0x80000000)
> +    {
> +      /* ps->__value.__wchb[3] stores the index of the next code unit to
> +         write.  Code units are stored in reverse order.  */
> +      size_t i = ps->__value.__wchb[3];
> +      if (pc8 != NULL)
> +	{
> +	  *pc8 = ps->__value.__wchb[i];
> +	}
> +      if (i == 0)
> +	{
> +	  ps->__count &= 0x7fffffff;
> +	  ps->__value.__wch = 0;
> +	}
> +      else
> +	--ps->__value.__wchb[3];
> +      return -3;
> +    }
> +
> +  if (s == NULL)
> +    {
> +      /* if 's' is a null pointer, behave as if a null pointer was passed for
> +         'pc8', an empty string was passed for 's', and 1 passed for 'n'.  */
> +      pc8 = NULL;
> +      s = "";
> +      n = 1;
> +    }
> +
> +  wchar_t wc;
> +  size_t result;
> +
> +  result = mbrtowc (&wc, s, n, ps);
> +  if (result <= n)
> +    {
> +      if (wc <= 0x7F)
> +	{
> +	  if (pc8 != NULL)
> +	    *pc8 = wc;
> +	}
> +      else if (wc <= 0x7FF)
> +	{
> +	  if (pc8 != NULL)
> +	    *pc8 = 0xC0 + ((wc >> 6) & 0x1F);
> +	  ps->__value.__wchb[0] = 0x80 + (wc & 0x3F);
> +	  ps->__value.__wchb[3] = 0;
> +	  ps->__count |= 0x80000000;
> +	}
> +      else if (wc <= 0xFFFF)
> +	{
> +	  if (pc8 != NULL)
> +	    *pc8 = 0xE0 + ((wc >> 12) & 0x0F);
> +	  ps->__value.__wchb[1] = 0x80 + ((wc >> 6) & 0x3F);
> +	  ps->__value.__wchb[0] = 0x80 + (wc & 0x3F);
> +	  ps->__value.__wchb[3] = 1;
> +	  ps->__count |= 0x80000000;
> +	}
> +      else if (wc <= 0x10FFFF)
> +	{
> +	  if (pc8 != NULL)
> +	    *pc8 = 0xF0 + ((wc >> 18) & 0x07);
> +	  ps->__value.__wchb[2] = 0x80 + ((wc >> 12) & 0x3F);
> +	  ps->__value.__wchb[1] = 0x80 + ((wc >> 6) & 0x3F);
> +	  ps->__value.__wchb[0] = 0x80 + (wc & 0x3F);
> +	  ps->__value.__wchb[3] = 2;
> +	  ps->__count |= 0x80000000;
> +	}
> +    }
> +  if (result == 0 && wc != 0)
> +    {
> +      /* mbrtowc() never returns -3.  When a MB sequence converts to multiple
> +         WCs, no input is consumed when writing the subsequent WCs resulting
> +         in a result of 0 even if a null character wasn't written.  */
> +      result = -3;
> +    }
> +
> +  return result;
> +}
> diff --git a/wcsmbs/uchar.h b/wcsmbs/uchar.h
> index 051cdcbeb5..c37e8619a0 100644
> --- a/wcsmbs/uchar.h
> +++ b/wcsmbs/uchar.h
> @@ -31,6 +31,13 @@
> #include <bits/types.h>
> #include <bits/types/mbstate_t.h>
> 
> +/* Declare the C2x char8_t typedef in C2x modes, but only if the C++
> +  __cpp_char8_t feature test macro is not defined.  */
> +#if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
> +/* Define the 8-bit character type.  */
> +typedef unsigned char char8_t;
> +#endif
> +
> #ifndef __USE_ISOCXX11
> /* Define the 16-bit and 32-bit character types.  */
> typedef __uint_least16_t char16_t;
> @@ -40,6 +47,20 @@ typedef __uint_least32_t char32_t;
> 
> __BEGIN_DECLS
> 
> +/* Declare the C2x mbrtoc8() and c8rtomb() functions in C2x modes or if
> +   the C++ __cpp_char8_t feature test macro is defined.  */
> +#if __GLIBC_USE (ISOC2X) || defined __cpp_char8_t
> +/* Write char8_t representation of multibyte character pointed
> +   to by S to PC8.  */
> +extern size_t mbrtoc8  (char8_t *__restrict __pc8,
> +			const char *__restrict __s, size_t __n,
> +			mbstate_t *__restrict __p) __THROW;
> +
> +/* Write multibyte representation of char8_t C8 to S.  */
> +extern size_t c8rtomb  (char *__restrict __s, char8_t __c8,
> +			mbstate_t *__restrict __ps) __THROW;
> +#endif
> +
> /* Write char16_t representation of multibyte character pointed
>    to by S to PC16.  */
> extern size_t mbrtoc16 (char16_t *__restrict __pc16,
> -- 
> 2.32.0
>
  
Joseph Myers July 19, 2022, 9:08 p.m. UTC | #2
This change appears to introduce a failure of 
wcsmbs/check-installed-headers-cxx with GCC mainline, because uchar.h now 
produces:

../wcsmbs/uchar.h:38:23: error: identifier 'char8_t' is a keyword in C++20 [-Werror=c++20-compat]
   38 | typedef unsigned char char8_t;

(recall we want our installed headers to avoid warnings *without* relying 
on the default disabling of warnings in system headers).

Unfortunately, GCC for C++ doesn't disable -Wc++20-compat inside 
__extension__ (unlike what the C front end does), so simply adding 
__extension__ to that declaration wouldn't help, but we could use 
diagnostic disabling pragmas (as already done in some installed headers).
  
Adhemerval Zanella July 20, 2022, 12:04 p.m. UTC | #3
On 19/07/22 18:08, Joseph Myers wrote:
> This change appears to introduce a failure of 
> wcsmbs/check-installed-headers-cxx with GCC mainline, because uchar.h now 
> produces:
> 
> ../wcsmbs/uchar.h:38:23: error: identifier 'char8_t' is a keyword in C++20 [-Werror=c++20-compat]
>    38 | typedef unsigned char char8_t;
> 
> (recall we want our installed headers to avoid warnings *without* relying 
> on the default disabling of warnings in system headers).
> 
> Unfortunately, GCC for C++ doesn't disable -Wc++20-compat inside 
> __extension__ (unlike what the C front end does), so simply adding 
> __extension__ to that declaration wouldn't help, but we could use 
> diagnostic disabling pragmas (as already done in some installed headers).
> 

My understanding is compiler will define __cpp_char8_t exactly to avoid
such redefinition.  But it seems from gcc documentation that it is only
actually enabled with -fchar8_t.  Do we a preprocessor flag to indicate
it?
  
Florian Weimer July 20, 2022, 1:54 p.m. UTC | #4
* Adhemerval Zanella Netto via Libc-alpha:

> On 19/07/22 18:08, Joseph Myers wrote:
>> This change appears to introduce a failure of 
>> wcsmbs/check-installed-headers-cxx with GCC mainline, because uchar.h now 
>> produces:
>> 
>> ../wcsmbs/uchar.h:38:23: error: identifier 'char8_t' is a keyword in C++20 [-Werror=c++20-compat]
>>    38 | typedef unsigned char char8_t;
>> 
>> (recall we want our installed headers to avoid warnings *without* relying 
>> on the default disabling of warnings in system headers).
>> 
>> Unfortunately, GCC for C++ doesn't disable -Wc++20-compat inside 
>> __extension__ (unlike what the C front end does), so simply adding 
>> __extension__ to that declaration wouldn't help, but we could use 
>> diagnostic disabling pragmas (as already done in some installed headers).

> My understanding is compiler will define __cpp_char8_t exactly to avoid
> such redefinition.  But it seems from gcc documentation that it is only
> actually enabled with -fchar8_t.  Do we a preprocessor flag to indicate
> it? 

I think __cpp_char8_t is only defined if the language mode is active.
The warning is independent of the language mode, though.

Thanks,
Florian
  
Adhemerval Zanella July 20, 2022, 2:31 p.m. UTC | #5
On 20/07/22 10:54, Florian Weimer wrote:
> * Adhemerval Zanella Netto via Libc-alpha:
> 
>> On 19/07/22 18:08, Joseph Myers wrote:
>>> This change appears to introduce a failure of 
>>> wcsmbs/check-installed-headers-cxx with GCC mainline, because uchar.h now 
>>> produces:
>>>
>>> ../wcsmbs/uchar.h:38:23: error: identifier 'char8_t' is a keyword in C++20 [-Werror=c++20-compat]
>>>    38 | typedef unsigned char char8_t;
>>>
>>> (recall we want our installed headers to avoid warnings *without* relying 
>>> on the default disabling of warnings in system headers).
>>>
>>> Unfortunately, GCC for C++ doesn't disable -Wc++20-compat inside 
>>> __extension__ (unlike what the C front end does), so simply adding 
>>> __extension__ to that declaration wouldn't help, but we could use 
>>> diagnostic disabling pragmas (as already done in some installed headers).
> 
>> My understanding is compiler will define __cpp_char8_t exactly to avoid
>> such redefinition.  But it seems from gcc documentation that it is only
>> actually enabled with -fchar8_t.  Do we a preprocessor flag to indicate
>> it? 
> 
> I think __cpp_char8_t is only defined if the language mode is active.
> The warning is independent of the language mode, though.

Maybe we also skip chat8_t definition for __cplusplus == 202002L ?
  
Florian Weimer July 20, 2022, 3:05 p.m. UTC | #6
* Adhemerval Zanella Netto:

>> I think __cpp_char8_t is only defined if the language mode is active.
>> The warning is independent of the language mode, though.
>
> Maybe we also skip chat8_t definition for __cplusplus == 202002L ?

We have to do that in any case, but we still need to deal with the
warning in the earlier language modes.

Thanks,
Florian
  
Tom Honermann July 20, 2022, 4:47 p.m. UTC | #7
Confirmed that this issue can be easily reproduced outside the testsuite.

$ cat t.cpp
#include <uchar.h>

$ g++ --version
g++ (GCC) 13.0.0 20220720 (experimental)
...

$ g++ -c -I/path/to/glibc-char8_t/include -std=c++17 
-Werror=c++20-compat t.cpp
In file included from t.cpp:1:
/home/tom/products/glibc-char8_t/include/uchar.h:38:23: error: 
identifier ‘char8_t’ is a keyword in C++20 [-Werror=c++20-compat]
    38 | typedef unsigned char char8_t;
       |                       ^~~~~~~
cc1plus: some warnings being treated as errors

The char8_t typedef is currently guarded by:

/* Declare the C2x char8_t typedef in C2x modes, but only if the C++
   __cpp_char8_t feature test macro is not defined.  */
#if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
/* Define the 8-bit character type.  */
typedef unsigned char char8_t;
#endif

__GLIBC_USE (ISOC2X) evaluates to true because gcc unconditionally 
defines _GNU_SOURCE. I believe otherwise, C++17 mode would only (or 
should only) imply __GLIBC_USE (ISOC11).

Regardless, it seems that directives should be added to suppress the 
diagnostic. I tried prototyping such a fix, but it doesn't seem to work 
for me. I don't understand why.

$ diff -U3 uchar.h.old uchar.h
--- uchar.h.old 2022-07-20 12:37:55.544301692 -0400
+++ uchar.h     2022-07-20 12:43:21.124365563 -0400
@@ -34,8 +34,17 @@
  /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
    __cpp_char8_t feature test macro is not defined.  */
  #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
+/* Suppress the C++20 compatability diagnostic regarding char8_t being a
+   keyword.  */
+#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wc++20-compat"
+#endif
  /* Define the 8-bit character type.  */
  typedef unsigned char char8_t;
+#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+# pragma GCC diagnostic pop
+#endif
  #endif

  #ifndef __USE_ISOCXX11

Tom.

On 7/19/22 5:08 PM, Joseph Myers wrote:
> This change appears to introduce a failure of
> wcsmbs/check-installed-headers-cxx with GCC mainline, because uchar.h now
> produces:
>
> ../wcsmbs/uchar.h:38:23: error: identifier 'char8_t' is a keyword in C++20 [-Werror=c++20-compat]
>     38 | typedef unsigned char char8_t;
>
> (recall we want our installed headers to avoid warnings *without* relying
> on the default disabling of warnings in system headers).
>
> Unfortunately, GCC for C++ doesn't disable -Wc++20-compat inside
> __extension__ (unlike what the C front end does), so simply adding
> __extension__ to that declaration wouldn't help, but we could use
> diagnostic disabling pragmas (as already done in some installed headers).
>
  
Tom Honermann July 20, 2022, 4:53 p.m. UTC | #8
On 7/20/22 11:05 AM, Florian Weimer wrote:
> * Adhemerval Zanella Netto:
>
>>> I think __cpp_char8_t is only defined if the language mode is active.
>>> The warning is independent of the language mode, though.
>> Maybe we also skip chat8_t definition for __cplusplus == 202002L ?
> We have to do that in any case, but we still need to deal with the
> warning in the earlier language modes.

Declaring the char8_t typedef (and related mbrtoc8 and c8rtomb 
functions) in C++ modes that don't enable the builtin char8_t type 
(including -std=c++20 -fno-char8_t) is beneficial for compatibility with 
C in C23 or _GNU_SOURCE modes.

Tom.

>
> Thanks,
> Florian
>
  
Adhemerval Zanella July 21, 2022, 7:22 p.m. UTC | #9
On 20/07/22 13:47, Tom Honermann wrote:
> Confirmed that this issue can be easily reproduced outside the testsuite.
> 
> $ cat t.cpp
> #include <uchar.h>
> 
> $ g++ --version
> g++ (GCC) 13.0.0 20220720 (experimental)
> ...
> 
> $ g++ -c -I/path/to/glibc-char8_t/include -std=c++17 -Werror=c++20-compat t.cpp
> In file included from t.cpp:1:
> /home/tom/products/glibc-char8_t/include/uchar.h:38:23: error: identifier ‘char8_t’ is a keyword in C++20 [-Werror=c++20-compat]
>    38 | typedef unsigned char char8_t;
>       |                       ^~~~~~~
> cc1plus: some warnings being treated as errors
> 
> The char8_t typedef is currently guarded by:
> 
> /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
>   __cpp_char8_t feature test macro is not defined.  */
> #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
> /* Define the 8-bit character type.  */
> typedef unsigned char char8_t;
> #endif
> 
> __GLIBC_USE (ISOC2X) evaluates to true because gcc unconditionally defines _GNU_SOURCE. I believe otherwise, C++17 mode would only (or should only) imply __GLIBC_USE (ISOC11).
> 
> Regardless, it seems that directives should be added to suppress the diagnostic. I tried prototyping such a fix, but it doesn't seem to work for me. I don't understand why.

I have tried as well and I can't get to work either.  It would expect to work
as we have done bits/stdlib-bsearch.h, could it be a gcc issue?

> 
> $ diff -U3 uchar.h.old uchar.h
> --- uchar.h.old 2022-07-20 12:37:55.544301692 -0400
> +++ uchar.h     2022-07-20 12:43:21.124365563 -0400
> @@ -34,8 +34,17 @@
>  /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
>    __cpp_char8_t feature test macro is not defined.  */
>  #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
> +/* Suppress the C++20 compatability diagnostic regarding char8_t being a
> +   keyword.  */
> +#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
> +# pragma GCC diagnostic push
> +# pragma GCC diagnostic ignored "-Wc++20-compat"
> +#endif
>  /* Define the 8-bit character type.  */
>  typedef unsigned char char8_t;
> +#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
> +# pragma GCC diagnostic pop
> +#endif
>  #endif
> 
>  #ifndef __USE_ISOCXX11
> 
> Tom.
> 
> On 7/19/22 5:08 PM, Joseph Myers wrote:
>> This change appears to introduce a failure of
>> wcsmbs/check-installed-headers-cxx with GCC mainline, because uchar.h now
>> produces:
>>
>> ../wcsmbs/uchar.h:38:23: error: identifier 'char8_t' is a keyword in C++20 [-Werror=c++20-compat]
>>     38 | typedef unsigned char char8_t;
>>
>> (recall we want our installed headers to avoid warnings *without* relying
>> on the default disabling of warnings in system headers).
>>
>> Unfortunately, GCC for C++ doesn't disable -Wc++20-compat inside
>> __extension__ (unlike what the C front end does), so simply adding
>> __extension__ to that declaration wouldn't help, but we could use
>> diagnostic disabling pragmas (as already done in some installed headers).
>>
  
Tom Honermann July 21, 2022, 8:51 p.m. UTC | #10
On 7/21/22 3:22 PM, Adhemerval Zanella Netto wrote:
>
> On 20/07/22 13:47, Tom Honermann wrote:
>> Confirmed that this issue can be easily reproduced outside the testsuite.
>>
>> $ cat t.cpp
>> #include <uchar.h>
>>
>> $ g++ --version
>> g++ (GCC) 13.0.0 20220720 (experimental)
>> ...
>>
>> $ g++ -c -I/path/to/glibc-char8_t/include -std=c++17 -Werror=c++20-compat t.cpp
>> In file included from t.cpp:1:
>> /home/tom/products/glibc-char8_t/include/uchar.h:38:23: error: identifier ‘char8_t’ is a keyword in C++20 [-Werror=c++20-compat]
>>     38 | typedef unsigned char char8_t;
>>        |                       ^~~~~~~
>> cc1plus: some warnings being treated as errors
>>
>> The char8_t typedef is currently guarded by:
>>
>> /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
>>    __cpp_char8_t feature test macro is not defined.  */
>> #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
>> /* Define the 8-bit character type.  */
>> typedef unsigned char char8_t;
>> #endif
>>
>> __GLIBC_USE (ISOC2X) evaluates to true because gcc unconditionally defines _GNU_SOURCE. I believe otherwise, C++17 mode would only (or should only) imply __GLIBC_USE (ISOC11).
>>
>> Regardless, it seems that directives should be added to suppress the diagnostic. I tried prototyping such a fix, but it doesn't seem to work for me. I don't understand why.
> I have tried as well and I can't get to work either.  It would expect to work
> as we have done bits/stdlib-bsearch.h, could it be a gcc issue?

Yes, this appears to be a gcc issue. I spent some time looking at gcc 
source code, but didn't find anything obvious. I verified the same 
technique does work to suppress the similar warning issued for use of, 
e.g., constexpr, as an identifier when -Wc++11-compat is enabled. I 
found tests that exercise #pragma GCC diagnostic ignored "-Wc++-compat", 
but none for -Wc++20-compat (or -Wc++11-compat).

Tom.

>
>> $ diff -U3 uchar.h.old uchar.h
>> --- uchar.h.old 2022-07-20 12:37:55.544301692 -0400
>> +++ uchar.h     2022-07-20 12:43:21.124365563 -0400
>> @@ -34,8 +34,17 @@
>>   /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
>>     __cpp_char8_t feature test macro is not defined.  */
>>   #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
>> +/* Suppress the C++20 compatability diagnostic regarding char8_t being a
>> +   keyword.  */
>> +#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
>> +# pragma GCC diagnostic push
>> +# pragma GCC diagnostic ignored "-Wc++20-compat"
>> +#endif
>>   /* Define the 8-bit character type.  */
>>   typedef unsigned char char8_t;
>> +#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
>> +# pragma GCC diagnostic pop
>> +#endif
>>   #endif
>>
>>   #ifndef __USE_ISOCXX11
>>
>> Tom.
>>
>> On 7/19/22 5:08 PM, Joseph Myers wrote:
>>> This change appears to introduce a failure of
>>> wcsmbs/check-installed-headers-cxx with GCC mainline, because uchar.h now
>>> produces:
>>>
>>> ../wcsmbs/uchar.h:38:23: error: identifier 'char8_t' is a keyword in C++20 [-Werror=c++20-compat]
>>>      38 | typedef unsigned char char8_t;
>>>
>>> (recall we want our installed headers to avoid warnings *without* relying
>>> on the default disabling of warnings in system headers).
>>>
>>> Unfortunately, GCC for C++ doesn't disable -Wc++20-compat inside
>>> __extension__ (unlike what the C front end does), so simply adding
>>> __extension__ to that declaration wouldn't help, but we could use
>>> diagnostic disabling pragmas (as already done in some installed headers).
>>>
  
Adhemerval Zanella July 21, 2022, 8:56 p.m. UTC | #11
On 21/07/22 17:51, Tom Honermann wrote:
> On 7/21/22 3:22 PM, Adhemerval Zanella Netto wrote:
>>
>> On 20/07/22 13:47, Tom Honermann wrote:
>>> Confirmed that this issue can be easily reproduced outside the testsuite.
>>>
>>> $ cat t.cpp
>>> #include <uchar.h>
>>>
>>> $ g++ --version
>>> g++ (GCC) 13.0.0 20220720 (experimental)
>>> ...
>>>
>>> $ g++ -c -I/path/to/glibc-char8_t/include -std=c++17 -Werror=c++20-compat t.cpp
>>> In file included from t.cpp:1:
>>> /home/tom/products/glibc-char8_t/include/uchar.h:38:23: error: identifier ‘char8_t’ is a keyword in C++20 [-Werror=c++20-compat]
>>>     38 | typedef unsigned char char8_t;
>>>        |                       ^~~~~~~
>>> cc1plus: some warnings being treated as errors
>>>
>>> The char8_t typedef is currently guarded by:
>>>
>>> /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
>>>    __cpp_char8_t feature test macro is not defined.  */
>>> #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
>>> /* Define the 8-bit character type.  */
>>> typedef unsigned char char8_t;
>>> #endif
>>>
>>> __GLIBC_USE (ISOC2X) evaluates to true because gcc unconditionally defines _GNU_SOURCE. I believe otherwise, C++17 mode would only (or should only) imply __GLIBC_USE (ISOC11).
>>>
>>> Regardless, it seems that directives should be added to suppress the diagnostic. I tried prototyping such a fix, but it doesn't seem to work for me. I don't understand why.
>> I have tried as well and I can't get to work either.  It would expect to work
>> as we have done bits/stdlib-bsearch.h, could it be a gcc issue?
> 
> Yes, this appears to be a gcc issue. I spent some time looking at gcc source code, but didn't find anything obvious. I verified the same technique does work to suppress the similar warning issued for use of, e.g., constexpr, as an identifier when -Wc++11-compat is enabled. I found tests that exercise #pragma GCC diagnostic ignored "-Wc++-compat", but none for -Wc++20-compat (or -Wc++11-compat).
> 
> Tom.
> 

In any case I think the fix below is the correct way (in fact I don't see
another way so I am assuming a compiler issue here).  We also need to avoid 
declare the typedef for __cplusplus >= 202002L.

>>
>>> $ diff -U3 uchar.h.old uchar.h
>>> --- uchar.h.old 2022-07-20 12:37:55.544301692 -0400
>>> +++ uchar.h     2022-07-20 12:43:21.124365563 -0400
>>> @@ -34,8 +34,17 @@
>>>   /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
>>>     __cpp_char8_t feature test macro is not defined.  */
>>>   #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
>>> +/* Suppress the C++20 compatability diagnostic regarding char8_t being a
>>> +   keyword.  */
>>> +#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)

Use __GNUC_PREREQ.

>>> +# pragma GCC diagnostic push
>>> +# pragma GCC diagnostic ignored "-Wc++20-compat"
>>> +#endif
>>>   /* Define the 8-bit character type.  */
>>>   typedef unsigned char char8_t;
>>> +#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
>>> +# pragma GCC diagnostic pop
>>> +#endif
>>>   #endif
>>>
>>>   #ifndef __USE_ISOCXX11
>>>
>>> Tom.
>>>
>>> On 7/19/22 5:08 PM, Joseph Myers wrote:
>>>> This change appears to introduce a failure of
>>>> wcsmbs/check-installed-headers-cxx with GCC mainline, because uchar.h now
>>>> produces:
>>>>
>>>> ../wcsmbs/uchar.h:38:23: error: identifier 'char8_t' is a keyword in C++20 [-Werror=c++20-compat]
>>>>      38 | typedef unsigned char char8_t;
>>>>
>>>> (recall we want our installed headers to avoid warnings *without* relying
>>>> on the default disabling of warnings in system headers).
>>>>
>>>> Unfortunately, GCC for C++ doesn't disable -Wc++20-compat inside
>>>> __extension__ (unlike what the C front end does), so simply adding
>>>> __extension__ to that declaration wouldn't help, but we could use
>>>> diagnostic disabling pragmas (as already done in some installed headers).
>>>>
  
Tom Honermann July 22, 2022, 5:24 a.m. UTC | #12
On 7/21/22 4:56 PM, Adhemerval Zanella Netto wrote:
>
> On 21/07/22 17:51, Tom Honermann wrote:
>> On 7/21/22 3:22 PM, Adhemerval Zanella Netto wrote:
>>> On 20/07/22 13:47, Tom Honermann wrote:
>>>> Confirmed that this issue can be easily reproduced outside the testsuite.
>>>>
>>>> $ cat t.cpp
>>>> #include <uchar.h>
>>>>
>>>> $ g++ --version
>>>> g++ (GCC) 13.0.0 20220720 (experimental)
>>>> ...
>>>>
>>>> $ g++ -c -I/path/to/glibc-char8_t/include -std=c++17 -Werror=c++20-compat t.cpp
>>>> In file included from t.cpp:1:
>>>> /home/tom/products/glibc-char8_t/include/uchar.h:38:23: error: identifier ‘char8_t’ is a keyword in C++20 [-Werror=c++20-compat]
>>>>      38 | typedef unsigned char char8_t;
>>>>         |                       ^~~~~~~
>>>> cc1plus: some warnings being treated as errors
>>>>
>>>> The char8_t typedef is currently guarded by:
>>>>
>>>> /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
>>>>     __cpp_char8_t feature test macro is not defined.  */
>>>> #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
>>>> /* Define the 8-bit character type.  */
>>>> typedef unsigned char char8_t;
>>>> #endif
>>>>
>>>> __GLIBC_USE (ISOC2X) evaluates to true because gcc unconditionally defines _GNU_SOURCE. I believe otherwise, C++17 mode would only (or should only) imply __GLIBC_USE (ISOC11).
>>>>
>>>> Regardless, it seems that directives should be added to suppress the diagnostic. I tried prototyping such a fix, but it doesn't seem to work for me. I don't understand why.
>>> I have tried as well and I can't get to work either.  It would expect to work
>>> as we have done bits/stdlib-bsearch.h, could it be a gcc issue?
>> Yes, this appears to be a gcc issue. I spent some time looking at gcc source code, but didn't find anything obvious. I verified the same technique does work to suppress the similar warning issued for use of, e.g., constexpr, as an identifier when -Wc++11-compat is enabled. I found tests that exercise #pragma GCC diagnostic ignored "-Wc++-compat", but none for -Wc++20-compat (or -Wc++11-compat).
>>
>> Tom.
>>
> In any case I think the fix below is the correct way (in fact I don't see
> another way so I am assuming a compiler issue here).
I agree. I debugged gcc tonight and discovered what the problem was. 
I'll submit a patch to gcc.
> We also need to avoid
> declare the typedef for __cplusplus >= 202002L.
The typedef is already avoided if the __cpp_char8_t feature test macro 
is defined (builtin char8_t support can be enabled in previous C++ 
standard modes via the -fchar8_t option).
>
>>>> $ diff -U3 uchar.h.old uchar.h
>>>> --- uchar.h.old 2022-07-20 12:37:55.544301692 -0400
>>>> +++ uchar.h     2022-07-20 12:43:21.124365563 -0400
>>>> @@ -34,8 +34,17 @@
>>>>    /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
>>>>      __cpp_char8_t feature test macro is not defined.  */
>>>>    #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
>>>> +/* Suppress the C++20 compatability diagnostic regarding char8_t being a
>>>> +   keyword.  */
>>>> +#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
> Use __GNUC_PREREQ.

Yes, thank you. I also determined that the -Wc++20-compat option was 
added to gcc 10 and is only recognized in C++ modes, so the diagnostic 
suppression guards will be __GNUC_PREREQ (10, 0) && defined __cplusplus.

I'll follow up with a patch soon.

Tom.

>
>>>> +# pragma GCC diagnostic push
>>>> +# pragma GCC diagnostic ignored "-Wc++20-compat"
>>>> +#endif
>>>>    /* Define the 8-bit character type.  */
>>>>    typedef unsigned char char8_t;
>>>> +#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
>>>> +# pragma GCC diagnostic pop
>>>> +#endif
>>>>    #endif
>>>>
>>>>    #ifndef __USE_ISOCXX11
>>>>
>>>> Tom.
>>>>
>>>> On 7/19/22 5:08 PM, Joseph Myers wrote:
>>>>> This change appears to introduce a failure of
>>>>> wcsmbs/check-installed-headers-cxx with GCC mainline, because uchar.h now
>>>>> produces:
>>>>>
>>>>> ../wcsmbs/uchar.h:38:23: error: identifier 'char8_t' is a keyword in C++20 [-Werror=c++20-compat]
>>>>>       38 | typedef unsigned char char8_t;
>>>>>
>>>>> (recall we want our installed headers to avoid warnings *without* relying
>>>>> on the default disabling of warnings in system headers).
>>>>>
>>>>> Unfortunately, GCC for C++ doesn't disable -Wc++20-compat inside
>>>>> __extension__ (unlike what the C front end does), so simply adding
>>>>> __extension__ to that declaration wouldn't help, but we could use
>>>>> diagnostic disabling pragmas (as already done in some installed headers).
>>>>>
  
Adhemerval Zanella July 22, 2022, 11:21 a.m. UTC | #13
On 22/07/22 02:24, Tom Honermann wrote:
> On 7/21/22 4:56 PM, Adhemerval Zanella Netto wrote:
>>
>> On 21/07/22 17:51, Tom Honermann wrote:
>>> On 7/21/22 3:22 PM, Adhemerval Zanella Netto wrote:
>>>> On 20/07/22 13:47, Tom Honermann wrote:
>>>>> Confirmed that this issue can be easily reproduced outside the testsuite.
>>>>>
>>>>> $ cat t.cpp
>>>>> #include <uchar.h>
>>>>>
>>>>> $ g++ --version
>>>>> g++ (GCC) 13.0.0 20220720 (experimental)
>>>>> ...
>>>>>
>>>>> $ g++ -c -I/path/to/glibc-char8_t/include -std=c++17 -Werror=c++20-compat t.cpp
>>>>> In file included from t.cpp:1:
>>>>> /home/tom/products/glibc-char8_t/include/uchar.h:38:23: error: identifier ‘char8_t’ is a keyword in C++20 [-Werror=c++20-compat]
>>>>>      38 | typedef unsigned char char8_t;
>>>>>         |                       ^~~~~~~
>>>>> cc1plus: some warnings being treated as errors
>>>>>
>>>>> The char8_t typedef is currently guarded by:
>>>>>
>>>>> /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
>>>>>     __cpp_char8_t feature test macro is not defined.  */
>>>>> #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
>>>>> /* Define the 8-bit character type.  */
>>>>> typedef unsigned char char8_t;
>>>>> #endif
>>>>>
>>>>> __GLIBC_USE (ISOC2X) evaluates to true because gcc unconditionally defines _GNU_SOURCE. I believe otherwise, C++17 mode would only (or should only) imply __GLIBC_USE (ISOC11).
>>>>>
>>>>> Regardless, it seems that directives should be added to suppress the diagnostic. I tried prototyping such a fix, but it doesn't seem to work for me. I don't understand why.
>>>> I have tried as well and I can't get to work either.  It would expect to work
>>>> as we have done bits/stdlib-bsearch.h, could it be a gcc issue?
>>> Yes, this appears to be a gcc issue. I spent some time looking at gcc source code, but didn't find anything obvious. I verified the same technique does work to suppress the similar warning issued for use of, e.g., constexpr, as an identifier when -Wc++11-compat is enabled. I found tests that exercise #pragma GCC diagnostic ignored "-Wc++-compat", but none for -Wc++20-compat (or -Wc++11-compat).
>>>
>>> Tom.
>>>
>> In any case I think the fix below is the correct way (in fact I don't see
>> another way so I am assuming a compiler issue here).
> I agree. I debugged gcc tonight and discovered what the problem was. I'll submit a patch to gcc.
>> We also need to avoid
>> declare the typedef for __cplusplus >= 202002L.
> The typedef is already avoided if the __cpp_char8_t feature test macro is defined (builtin char8_t support can be enabled in previous C++ standard modes via the -fchar8_t option).

If the compiler preprocessor defined for -std=c++20? I had the impression it is
enabled iff -fchar8_t is set.
  
Adhemerval Zanella July 22, 2022, 2:15 p.m. UTC | #14
On 22/07/22 08:21, Adhemerval Zanella Netto wrote:
> 
> 
> On 22/07/22 02:24, Tom Honermann wrote:
>> On 7/21/22 4:56 PM, Adhemerval Zanella Netto wrote:
>>>
>>> On 21/07/22 17:51, Tom Honermann wrote:
>>>> On 7/21/22 3:22 PM, Adhemerval Zanella Netto wrote:
>>>>> On 20/07/22 13:47, Tom Honermann wrote:
>>>>>> Confirmed that this issue can be easily reproduced outside the testsuite.
>>>>>>
>>>>>> $ cat t.cpp
>>>>>> #include <uchar.h>
>>>>>>
>>>>>> $ g++ --version
>>>>>> g++ (GCC) 13.0.0 20220720 (experimental)
>>>>>> ...
>>>>>>
>>>>>> $ g++ -c -I/path/to/glibc-char8_t/include -std=c++17 -Werror=c++20-compat t.cpp
>>>>>> In file included from t.cpp:1:
>>>>>> /home/tom/products/glibc-char8_t/include/uchar.h:38:23: error: identifier ‘char8_t’ is a keyword in C++20 [-Werror=c++20-compat]
>>>>>>      38 | typedef unsigned char char8_t;
>>>>>>         |                       ^~~~~~~
>>>>>> cc1plus: some warnings being treated as errors
>>>>>>
>>>>>> The char8_t typedef is currently guarded by:
>>>>>>
>>>>>> /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
>>>>>>     __cpp_char8_t feature test macro is not defined.  */
>>>>>> #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
>>>>>> /* Define the 8-bit character type.  */
>>>>>> typedef unsigned char char8_t;
>>>>>> #endif
>>>>>>
>>>>>> __GLIBC_USE (ISOC2X) evaluates to true because gcc unconditionally defines _GNU_SOURCE. I believe otherwise, C++17 mode would only (or should only) imply __GLIBC_USE (ISOC11).
>>>>>>
>>>>>> Regardless, it seems that directives should be added to suppress the diagnostic. I tried prototyping such a fix, but it doesn't seem to work for me. I don't understand why.
>>>>> I have tried as well and I can't get to work either.  It would expect to work
>>>>> as we have done bits/stdlib-bsearch.h, could it be a gcc issue?
>>>> Yes, this appears to be a gcc issue. I spent some time looking at gcc source code, but didn't find anything obvious. I verified the same technique does work to suppress the similar warning issued for use of, e.g., constexpr, as an identifier when -Wc++11-compat is enabled. I found tests that exercise #pragma GCC diagnostic ignored "-Wc++-compat", but none for -Wc++20-compat (or -Wc++11-compat).
>>>>
>>>> Tom.
>>>>
>>> In any case I think the fix below is the correct way (in fact I don't see
>>> another way so I am assuming a compiler issue here).
>> I agree. I debugged gcc tonight and discovered what the problem was. I'll submit a patch to gcc.
>>> We also need to avoid
>>> declare the typedef for __cplusplus >= 202002L.
>> The typedef is already avoided if the __cpp_char8_t feature test macro is defined (builtin char8_t support can be enabled in previous C++ standard modes via the -fchar8_t option).
> 
> If the compiler preprocessor defined for -std=c++20? I had the impression it is
> enabled iff -fchar8_t is set.

I realized now I did not write proper english, I meant to ask if gcc always define
__cpp_char8_t for -std=c++20 and higher since I had the impression that the
define is only active iff -fchar8_t is actively used.
  
Tom Honermann July 22, 2022, 5 p.m. UTC | #15
On 7/22/22 10:15 AM, Adhemerval Zanella Netto wrote:
>
> On 22/07/22 08:21, Adhemerval Zanella Netto wrote:
>>
>> On 22/07/22 02:24, Tom Honermann wrote:
>>> On 7/21/22 4:56 PM, Adhemerval Zanella Netto wrote:
>>>> On 21/07/22 17:51, Tom Honermann wrote:
>>>>> On 7/21/22 3:22 PM, Adhemerval Zanella Netto wrote:
>>>>>> On 20/07/22 13:47, Tom Honermann wrote:
>>>>>>> Confirmed that this issue can be easily reproduced outside the testsuite.
>>>>>>>
>>>>>>> $ cat t.cpp
>>>>>>> #include <uchar.h>
>>>>>>>
>>>>>>> $ g++ --version
>>>>>>> g++ (GCC) 13.0.0 20220720 (experimental)
>>>>>>> ...
>>>>>>>
>>>>>>> $ g++ -c -I/path/to/glibc-char8_t/include -std=c++17 -Werror=c++20-compat t.cpp
>>>>>>> In file included from t.cpp:1:
>>>>>>> /home/tom/products/glibc-char8_t/include/uchar.h:38:23: error: identifier ‘char8_t’ is a keyword in C++20 [-Werror=c++20-compat]
>>>>>>>       38 | typedef unsigned char char8_t;
>>>>>>>          |                       ^~~~~~~
>>>>>>> cc1plus: some warnings being treated as errors
>>>>>>>
>>>>>>> The char8_t typedef is currently guarded by:
>>>>>>>
>>>>>>> /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
>>>>>>>      __cpp_char8_t feature test macro is not defined.  */
>>>>>>> #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
>>>>>>> /* Define the 8-bit character type.  */
>>>>>>> typedef unsigned char char8_t;
>>>>>>> #endif
>>>>>>>
>>>>>>> __GLIBC_USE (ISOC2X) evaluates to true because gcc unconditionally defines _GNU_SOURCE. I believe otherwise, C++17 mode would only (or should only) imply __GLIBC_USE (ISOC11).
>>>>>>>
>>>>>>> Regardless, it seems that directives should be added to suppress the diagnostic. I tried prototyping such a fix, but it doesn't seem to work for me. I don't understand why.
>>>>>> I have tried as well and I can't get to work either.  It would expect to work
>>>>>> as we have done bits/stdlib-bsearch.h, could it be a gcc issue?
>>>>> prereqYes, this appears to be a gcc issue. I spent some time looking at gcc source code, but didn't find anything obvious. I verified the same technique does work to suppress the similar warning issued for use of, e.g., constexpr, as an identifier when -Wc++11-compat is enabled. I found tests that exercise #pragma GCC diagnostic ignored "-Wc++-compat", but none for -Wc++20-compat (or -Wc++11-compat).
>>>>>
>>>>> Tom.
>>>>>
>>>> In any case I think the fix below is the correct way (in fact I don't see
>>>> another way so I am assuming a compiler issue here).
>>> I agree. I debugged gcc tonight and discovered what the problem was. I'll submit a patch to gcc.
>>>> We also need to avoid
>>>> declare the typedef for __cplusplus >= 202002L.
>>> The typedef is already avoided if the __cpp_char8_t feature test macro is defined (builtin char8_t support can be enabled in previous C++ standard modes via the -fchar8_t option).
>> If the compiler preprocessor defined for -std=c++20? I had the impression it is
>> enabled iff -fchar8_t is set.
> I realized now I did not write proper english, I meant to ask if gcc always define
> __cpp_char8_t for -std=c++20 and higher since I had the impression that the
> define is only active iff -fchar8_t is actively used.

English is hard :)

For gcc, clang, and MSVC, -std=c++20 (/std:c++20 for MSVC) implies 
-fchar8_t (/Zc:char8_t), but that feature can be disabled with 
-fno-char8_t (/Zc:char8_t-). For example:

$ gcc -E -dM -x c++ -std=c++17 /dev/null | grep __cpp_char8_t
$ gcc -E -dM -x c++ -std=c++17 -fchar8_t /dev/null | grep __cpp_char8_t
#define __cpp_char8_t 201811L
$ gcc -E -dM -x c++ -std=c++20 /dev/null | grep __cpp_char8_t
#define __cpp_char8_t 201811L
$ gcc -E -dM -x c++ -std=c++20 -fno-char8_t /dev/null | grep __cpp_char8_t

Tom.
  
Adhemerval Zanella July 22, 2022, 5:01 p.m. UTC | #16
On 22/07/22 14:00, Tom Honermann wrote:
> On 7/22/22 10:15 AM, Adhemerval Zanella Netto wrote:
>>
>> On 22/07/22 08:21, Adhemerval Zanella Netto wrote:
>>>
>>> On 22/07/22 02:24, Tom Honermann wrote:
>>>> On 7/21/22 4:56 PM, Adhemerval Zanella Netto wrote:
>>>>> On 21/07/22 17:51, Tom Honermann wrote:
>>>>>> On 7/21/22 3:22 PM, Adhemerval Zanella Netto wrote:
>>>>>>> On 20/07/22 13:47, Tom Honermann wrote:
>>>>>>>> Confirmed that this issue can be easily reproduced outside the testsuite.
>>>>>>>>
>>>>>>>> $ cat t.cpp
>>>>>>>> #include <uchar.h>
>>>>>>>>
>>>>>>>> $ g++ --version
>>>>>>>> g++ (GCC) 13.0.0 20220720 (experimental)
>>>>>>>> ...
>>>>>>>>
>>>>>>>> $ g++ -c -I/path/to/glibc-char8_t/include -std=c++17 -Werror=c++20-compat t.cpp
>>>>>>>> In file included from t.cpp:1:
>>>>>>>> /home/tom/products/glibc-char8_t/include/uchar.h:38:23: error: identifier ‘char8_t’ is a keyword in C++20 [-Werror=c++20-compat]
>>>>>>>>       38 | typedef unsigned char char8_t;
>>>>>>>>          |                       ^~~~~~~
>>>>>>>> cc1plus: some warnings being treated as errors
>>>>>>>>
>>>>>>>> The char8_t typedef is currently guarded by:
>>>>>>>>
>>>>>>>> /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
>>>>>>>>      __cpp_char8_t feature test macro is not defined.  */
>>>>>>>> #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
>>>>>>>> /* Define the 8-bit character type.  */
>>>>>>>> typedef unsigned char char8_t;
>>>>>>>> #endif
>>>>>>>>
>>>>>>>> __GLIBC_USE (ISOC2X) evaluates to true because gcc unconditionally defines _GNU_SOURCE. I believe otherwise, C++17 mode would only (or should only) imply __GLIBC_USE (ISOC11).
>>>>>>>>
>>>>>>>> Regardless, it seems that directives should be added to suppress the diagnostic. I tried prototyping such a fix, but it doesn't seem to work for me. I don't understand why.
>>>>>>> I have tried as well and I can't get to work either.  It would expect to work
>>>>>>> as we have done bits/stdlib-bsearch.h, could it be a gcc issue?
>>>>>> prereqYes, this appears to be a gcc issue. I spent some time looking at gcc source code, but didn't find anything obvious. I verified the same technique does work to suppress the similar warning issued for use of, e.g., constexpr, as an identifier when -Wc++11-compat is enabled. I found tests that exercise #pragma GCC diagnostic ignored "-Wc++-compat", but none for -Wc++20-compat (or -Wc++11-compat).
>>>>>>
>>>>>> Tom.
>>>>>>
>>>>> In any case I think the fix below is the correct way (in fact I don't see
>>>>> another way so I am assuming a compiler issue here).
>>>> I agree. I debugged gcc tonight and discovered what the problem was. I'll submit a patch to gcc.
>>>>> We also need to avoid
>>>>> declare the typedef for __cplusplus >= 202002L.
>>>> The typedef is already avoided if the __cpp_char8_t feature test macro is defined (builtin char8_t support can be enabled in previous C++ standard modes via the -fchar8_t option).
>>> If the compiler preprocessor defined for -std=c++20? I had the impression it is
>>> enabled iff -fchar8_t is set.
>> I realized now I did not write proper english, I meant to ask if gcc always define
>> __cpp_char8_t for -std=c++20 and higher since I had the impression that the
>> define is only active iff -fchar8_t is actively used.
> 
> English is hard :)
> 
> For gcc, clang, and MSVC, -std=c++20 (/std:c++20 for MSVC) implies -fchar8_t (/Zc:char8_t), but that feature can be disabled with -fno-char8_t (/Zc:char8_t-). For example:
> 
> $ gcc -E -dM -x c++ -std=c++17 /dev/null | grep __cpp_char8_t
> $ gcc -E -dM -x c++ -std=c++17 -fchar8_t /dev/null | grep __cpp_char8_t
> #define __cpp_char8_t 201811L
> $ gcc -E -dM -x c++ -std=c++20 /dev/null | grep __cpp_char8_t
> #define __cpp_char8_t 201811L
> $ gcc -E -dM -x c++ -std=c++20 -fno-char8_t /dev/null | grep __cpp_char8_t
> 
> Tom.
> 

Ok, thanks.
  
Tom Honermann July 24, 2022, 4:46 a.m. UTC | #17
On 7/22/22 1:24 AM, Tom Honermann via Libc-alpha wrote:
> On 7/21/22 4:56 PM, Adhemerval Zanella Netto wrote:
>>
>> On 21/07/22 17:51, Tom Honermann wrote:
>>> On 7/21/22 3:22 PM, Adhemerval Zanella Netto wrote:
>>>> On 20/07/22 13:47, Tom Honermann wrote:
>>>>> Confirmed that this issue can be easily reproduced outside the 
>>>>> testsuite.
>>>>>
>>>>> $ cat t.cpp
>>>>> #include <uchar.h>
>>>>>
>>>>> $ g++ --version
>>>>> g++ (GCC) 13.0.0 20220720 (experimental)
>>>>> ...
>>>>>
>>>>> $ g++ -c -I/path/to/glibc-char8_t/include -std=c++17 
>>>>> -Werror=c++20-compat t.cpp
>>>>> In file included from t.cpp:1:
>>>>> /home/tom/products/glibc-char8_t/include/uchar.h:38:23: error: 
>>>>> identifier ‘char8_t’ is a keyword in C++20 [-Werror=c++20-compat]
>>>>>      38 | typedef unsigned char char8_t;
>>>>>         |                       ^~~~~~~
>>>>> cc1plus: some warnings being treated as errors
>>>>>
>>>>> The char8_t typedef is currently guarded by:
>>>>>
>>>>> /* Declare the C2x char8_t typedef in C2x modes, but only if the C++
>>>>>     __cpp_char8_t feature test macro is not defined.  */
>>>>> #if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
>>>>> /* Define the 8-bit character type.  */
>>>>> typedef unsigned char char8_t;
>>>>> #endif
>>>>>
>>>>> __GLIBC_USE (ISOC2X) evaluates to true because gcc unconditionally 
>>>>> defines _GNU_SOURCE. I believe otherwise, C++17 mode would only 
>>>>> (or should only) imply __GLIBC_USE (ISOC11).
>>>>>
>>>>> Regardless, it seems that directives should be added to suppress 
>>>>> the diagnostic. I tried prototyping such a fix, but it doesn't 
>>>>> seem to work for me. I don't understand why.
>>>> I have tried as well and I can't get to work either.  It would 
>>>> expect to work
>>>> as we have done bits/stdlib-bsearch.h, could it be a gcc issue?
>>> Yes, this appears to be a gcc issue. I spent some time looking at 
>>> gcc source code, but didn't find anything obvious. I verified the 
>>> same technique does work to suppress the similar warning issued for 
>>> use of, e.g., constexpr, as an identifier when -Wc++11-compat is 
>>> enabled. I found tests that exercise #pragma GCC diagnostic ignored 
>>> "-Wc++-compat", but none for -Wc++20-compat (or -Wc++11-compat).
>>>
>>> Tom.
>>>
>> In any case I think the fix below is the correct way (in fact I don't 
>> see
>> another way so I am assuming a compiler issue here).
> I agree. I debugged gcc tonight and discovered what the problem was. 
> I'll submit a patch to gcc.

A patch has been submitted to gcc to correct '#pragma GCC diagnostic 
ignored' based suppression for -Wc++20-compat diagnostics. See the 
thread at https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598736.html.

Tom.
  

Patch

diff --git a/NEWS b/NEWS
index b0a3d7e512..94243e2170 100644
--- a/NEWS
+++ b/NEWS
@@ -46,6 +46,15 @@  Major new features:
   to more flexibly configure and operate on filesystem mounts.  The new
   mount APIs are specifically designed to work with namespaces.
 
+* Support for the mbrtoc8 and c8rtomb multibyte/UTF-8 character conversion
+  functions has been added per the ISO C2X N2653 and C++20 P0482R6 proposals.
+  Support for the char8_t typedef has been added per the ISO C2X N2653
+  proposal.  The functions are declared in uchar.h in C2X mode or when the
+  _GNU_SOURCE macro or C++20 __cpp_char8_t feature test macro is defined.
+  The char8_t typedef is declared in uchar.h in C2X mode or when the
+  _GNU_SOURCE macro is defined and the C++20 __cpp_char8_t feature test macro
+  is not defined (if __cpp_char8_t is defined, then char8_t is a builtin type).
+
 Deprecated and removed features, and other changes affecting compatibility:
 
 * Support for prelink will be removed in the next release; this includes
diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
index 4dc87e9061..66fb0e28fa 100644
--- a/sysdeps/mach/hurd/i386/libc.abilist
+++ b/sysdeps/mach/hurd/i386/libc.abilist
@@ -2289,6 +2289,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 close_range F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 8dba065b81..b3cf9fdd70 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2616,8 +2616,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 08f4750022..2a45006462 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2713,8 +2713,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
index 75db763023..0ac6bba241 100644
--- a/sysdeps/unix/sysv/linux/arc/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
@@ -2377,8 +2377,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
index fa33f317ac..bfa763906b 100644
--- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
@@ -496,8 +496,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
index dba2e4ce42..ffcd7ca432 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -493,8 +493,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index e6ff921c29..940777b118 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2652,8 +2652,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 8a40cece83..508efe6626 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2601,8 +2601,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index a89826049f..16b91fcee9 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2785,8 +2785,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index d1d96b7469..51b646790d 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2551,8 +2551,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 63a62f267a..ddb43651f2 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -497,8 +497,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index f68325f9bc..3db7deb4d0 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2728,8 +2728,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
index 247af2075c..94afb7ad0b 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -2701,8 +2701,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
index b0ac3f9009..5873751425 100644
--- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
@@ -2698,8 +2698,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index b22cd6bf2f..f296e4edb7 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2693,8 +2693,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 12fc2cce3e..1888756819 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2691,8 +2691,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index d3e96dfd43..7dfacee25b 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2699,8 +2699,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index cb58ed4db0..53e188aafe 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2602,8 +2602,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 61ad58a599..bc6a836b1b 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2740,8 +2740,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist
index 1260dc4e2e..299fa67961 100644
--- a/sysdeps/unix/sysv/linux/or1k/libc.abilist
+++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist
@@ -2123,8 +2123,10 @@  GLIBC_2.35 wprintf F
 GLIBC_2.35 write F
 GLIBC_2.35 writev F
 GLIBC_2.35 wscanf F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 363939762c..a5a072394d 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2755,8 +2755,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index f512ad8baf..2d26fd8639 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2788,8 +2788,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index c9bdc9859c..d9f1c593ea 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2510,8 +2510,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index f091be30bd..874f33dbcc 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2812,8 +2812,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
index 7ea73f9af8..465798a56f 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
@@ -2379,8 +2379,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index 333fa62714..ecc0544c05 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2579,8 +2579,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index a867467b12..3e8d00d513 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2753,8 +2753,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index dbad5b3163..a872a3d186 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2547,8 +2547,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
index 6f755cc173..a2938ca2be 100644
--- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
@@ -2608,8 +2608,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
index 77d936aa3c..ef318251c5 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -2605,8 +2605,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 09bb4363e1..2e2fbe72e2 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2748,8 +2748,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 9df9cb6adb..e1991259cd 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2574,8 +2574,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 4829450ad0..7d0843d1d8 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2525,8 +2525,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index caea228bcb..761958f768 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2631,8 +2631,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 c8rtomb F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
+GLIBC_2.36 mbrtoc8 F
 GLIBC_2.36 move_mount F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
index df9a85f4a9..bda281ad70 100644
--- a/wcsmbs/Makefile
+++ b/wcsmbs/Makefile
@@ -42,7 +42,7 @@  routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
 	    wcsmbsload mbsrtowcs_l \
 	    isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf \
 	    isoc99_swscanf isoc99_vswscanf \
-	    mbrtoc16 c16rtomb mbrtoc32 c32rtomb
+	    mbrtoc8 c8rtomb mbrtoc16 c16rtomb mbrtoc32 c32rtomb
 
 strop-tests :=  wcscmp wcsncmp wmemcmp wcslen wcschr wcsrchr wcscpy wcsnlen \
 		wcpcpy wcsncpy wcpncpy wcscat wcsncat wcschrnul wcsspn wcspbrk \
diff --git a/wcsmbs/Versions b/wcsmbs/Versions
index 0b31c1b940..ec28acfb73 100644
--- a/wcsmbs/Versions
+++ b/wcsmbs/Versions
@@ -49,4 +49,7 @@  libc {
     wcstof32; wcstof64; wcstof32x;
     wcstof32_l; wcstof64_l; wcstof32x_l;
   }
+  GLIBC_2.36 {
+    c8rtomb; mbrtoc8;
+  }
 }
diff --git a/wcsmbs/c8rtomb.c b/wcsmbs/c8rtomb.c
new file mode 100644
index 0000000000..b564770eb5
--- /dev/null
+++ b/wcsmbs/c8rtomb.c
@@ -0,0 +1,132 @@ 
+/* UTF-8 to multibyte conversion.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <uchar.h>
+#include <wchar.h>
+
+
+/* This is the private state used if PS is NULL.  */
+static mbstate_t state;
+
+size_t
+c8rtomb (char *s, char8_t c8, mbstate_t *ps)
+{
+  /* This implementation depends on the converter invoked by wcrtomb not
+     needing to retain state in either the top most bit of ps->__count or
+     in ps->__value between invocations.  This implementation uses the
+     top most bit of ps->__count to indicate that trailing code units are
+     expected and uses ps->__value to store previously seen code units.  */
+
+  wchar_t wc;
+
+  if (ps == NULL)
+    ps = &state;
+
+  if (s == NULL)
+    {
+      /* if 's' is a null pointer, behave as if u8'\0' was passed as 'c8'.  If
+         this occurs for an incomplete code unit sequence, then an error will
+         be reported below.  */
+      c8 = u8""[0];
+    }
+
+  if (! (ps->__count & 0x80000000))
+    {
+      /* Initial state.  */
+      if ((c8 >= 0x80 && c8 <= 0xC1) || c8 >= 0xF5)
+	{
+	  /* An invalid lead code unit.  */
+	  __set_errno (EILSEQ);
+	  return -1;
+	}
+      if (c8 >= 0xC2)
+	{
+	  /* A valid lead code unit.  */
+	  ps->__count |= 0x80000000;
+	  ps->__value.__wchb[0] = c8;
+	  ps->__value.__wchb[3] = 1;
+	  return 0;
+	}
+      /* A single byte (ASCII) code unit.  */
+      wc = c8;
+    }
+  else
+    {
+      char8_t cu1 = ps->__value.__wchb[0];
+      if (ps->__value.__wchb[3] == 1)
+	{
+	  /* A single lead code unit was previously seen.  */
+	  if ((c8 < 0x80 || c8 > 0xBF)
+              || (cu1 == 0xE0 && c8 < 0xA0)
+              || (cu1 == 0xED && c8 > 0x9F)
+              || (cu1 == 0xF0 && c8 < 0x90)
+              || (cu1 == 0xF4 && c8 > 0x8F))
+	    {
+	      /* An invalid second code unit.  */
+	      __set_errno (EILSEQ);
+	      return -1;
+	    }
+	  if (cu1 >= 0xE0)
+	    {
+	      /* A three or four code unit sequence.  */
+	      ps->__value.__wchb[1] = c8;
+	      ++ps->__value.__wchb[3];
+	      return 0;
+	    }
+	  wc = ((cu1 & 0x1F) << 6)
+	       + (c8 & 0x3F);
+	}
+      else
+	{
+	  char8_t cu2 = ps->__value.__wchb[1];
+	  /* A three or four byte code unit sequence.  */
+	  if (c8 < 0x80 || c8 > 0xBF)
+	    {
+	      /* An invalid third or fourth code unit.  */
+	      __set_errno (EILSEQ);
+	      return -1;
+	    }
+	  if (ps->__value.__wchb[3] == 2 && cu1 >= 0xF0)
+	    {
+	      /* A four code unit sequence.  */
+	      ps->__value.__wchb[2] = c8;
+	      ++ps->__value.__wchb[3];
+	      return 0;
+	    }
+	  if (cu1 < 0xF0)
+	    {
+	      wc = ((cu1 & 0x0F) << 12)
+		   + ((cu2 & 0x3F) << 6)
+		   + (c8 & 0x3F);
+	    }
+	  else
+	    {
+	      char8_t cu3 = ps->__value.__wchb[2];
+	      wc = ((cu1 & 0x07) << 18)
+		   + ((cu2 & 0x3F) << 12)
+		   + ((cu3 & 0x3F) << 6)
+		   + (c8 & 0x3F);
+	    }
+	}
+      ps->__count &= 0x7fffffff;
+      ps->__value.__wch = 0;
+    }
+
+  return wcrtomb (s, wc, ps);
+}
diff --git a/wcsmbs/mbrtoc8.c b/wcsmbs/mbrtoc8.c
new file mode 100644
index 0000000000..f2fab3b6a7
--- /dev/null
+++ b/wcsmbs/mbrtoc8.c
@@ -0,0 +1,126 @@ 
+/* Multibyte to UTF-8 conversion.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <gconv.h>
+#include <uchar.h>
+#include <wcsmbsload.h>
+
+#include <sysdep.h>
+
+#ifndef EILSEQ
+# define EILSEQ EINVAL
+#endif
+
+
+/* This is the private state used if PS is NULL.  */
+static mbstate_t state;
+
+size_t
+mbrtoc8 (char8_t *pc8, const char *s, size_t n, mbstate_t *ps)
+{
+  /* This implementation depends on the converter invoked by mbrtowc() not
+     needing to retain state in either the top most bit of ps->__count or
+     in ps->__value between invocations.  This implementation uses the
+     top most bit of ps->__count to indicate that trailing code units are
+     yet to be written and uses ps->__value to store those code units.  */
+
+  if (ps == NULL)
+    ps = &state;
+
+  /* If state indicates that trailing code units are yet to be written, write
+     those first regardless of whether 's' is a null pointer.  */
+  if (ps->__count & 0x80000000)
+    {
+      /* ps->__value.__wchb[3] stores the index of the next code unit to
+         write.  Code units are stored in reverse order.  */
+      size_t i = ps->__value.__wchb[3];
+      if (pc8 != NULL)
+	{
+	  *pc8 = ps->__value.__wchb[i];
+	}
+      if (i == 0)
+	{
+	  ps->__count &= 0x7fffffff;
+	  ps->__value.__wch = 0;
+	}
+      else
+	--ps->__value.__wchb[3];
+      return -3;
+    }
+
+  if (s == NULL)
+    {
+      /* if 's' is a null pointer, behave as if a null pointer was passed for
+         'pc8', an empty string was passed for 's', and 1 passed for 'n'.  */
+      pc8 = NULL;
+      s = "";
+      n = 1;
+    }
+
+  wchar_t wc;
+  size_t result;
+
+  result = mbrtowc (&wc, s, n, ps);
+  if (result <= n)
+    {
+      if (wc <= 0x7F)
+	{
+	  if (pc8 != NULL)
+	    *pc8 = wc;
+	}
+      else if (wc <= 0x7FF)
+	{
+	  if (pc8 != NULL)
+	    *pc8 = 0xC0 + ((wc >> 6) & 0x1F);
+	  ps->__value.__wchb[0] = 0x80 + (wc & 0x3F);
+	  ps->__value.__wchb[3] = 0;
+	  ps->__count |= 0x80000000;
+	}
+      else if (wc <= 0xFFFF)
+	{
+	  if (pc8 != NULL)
+	    *pc8 = 0xE0 + ((wc >> 12) & 0x0F);
+	  ps->__value.__wchb[1] = 0x80 + ((wc >> 6) & 0x3F);
+	  ps->__value.__wchb[0] = 0x80 + (wc & 0x3F);
+	  ps->__value.__wchb[3] = 1;
+	  ps->__count |= 0x80000000;
+	}
+      else if (wc <= 0x10FFFF)
+	{
+	  if (pc8 != NULL)
+	    *pc8 = 0xF0 + ((wc >> 18) & 0x07);
+	  ps->__value.__wchb[2] = 0x80 + ((wc >> 12) & 0x3F);
+	  ps->__value.__wchb[1] = 0x80 + ((wc >> 6) & 0x3F);
+	  ps->__value.__wchb[0] = 0x80 + (wc & 0x3F);
+	  ps->__value.__wchb[3] = 2;
+	  ps->__count |= 0x80000000;
+	}
+    }
+  if (result == 0 && wc != 0)
+    {
+      /* mbrtowc() never returns -3.  When a MB sequence converts to multiple
+         WCs, no input is consumed when writing the subsequent WCs resulting
+         in a result of 0 even if a null character wasn't written.  */
+      result = -3;
+    }
+
+  return result;
+}
diff --git a/wcsmbs/uchar.h b/wcsmbs/uchar.h
index 051cdcbeb5..c37e8619a0 100644
--- a/wcsmbs/uchar.h
+++ b/wcsmbs/uchar.h
@@ -31,6 +31,13 @@ 
 #include <bits/types.h>
 #include <bits/types/mbstate_t.h>
 
+/* Declare the C2x char8_t typedef in C2x modes, but only if the C++
+  __cpp_char8_t feature test macro is not defined.  */
+#if __GLIBC_USE (ISOC2X) && !defined __cpp_char8_t
+/* Define the 8-bit character type.  */
+typedef unsigned char char8_t;
+#endif
+
 #ifndef __USE_ISOCXX11
 /* Define the 16-bit and 32-bit character types.  */
 typedef __uint_least16_t char16_t;
@@ -40,6 +47,20 @@  typedef __uint_least32_t char32_t;
 
 __BEGIN_DECLS
 
+/* Declare the C2x mbrtoc8() and c8rtomb() functions in C2x modes or if
+   the C++ __cpp_char8_t feature test macro is defined.  */
+#if __GLIBC_USE (ISOC2X) || defined __cpp_char8_t
+/* Write char8_t representation of multibyte character pointed
+   to by S to PC8.  */
+extern size_t mbrtoc8  (char8_t *__restrict __pc8,
+			const char *__restrict __s, size_t __n,
+			mbstate_t *__restrict __p) __THROW;
+
+/* Write multibyte representation of char8_t C8 to S.  */
+extern size_t c8rtomb  (char *__restrict __s, char8_t __c8,
+			mbstate_t *__restrict __ps) __THROW;
+#endif
+
 /* Write char16_t representation of multibyte character pointed
    to by S to PC16.  */
 extern size_t mbrtoc16 (char16_t *__restrict __pc16,