[2/3] : C++20 P0482R6 and C2X N2653: Implement mbrtoc8, c8rtomb, char8_t

Message ID 40868945-29d9-3099-fb11-260796a2a022@honermann.net
State New
Headers show
Series
  • : C++20 P0482R6 and C2X N2653: support for char8_t, mbrtoc8(), and c8rtomb().
Related show

Commit Message

Adhemerval Zanella via Libc-alpha June 7, 2021, 2:08 a.m.
This patch provides implementations for the mbrtoc8 and c8rtomb 
functions adopted for C++20 via WG21 P0482R6 [1] and proposed for C2X 
via WG14 N2653 [2].  It also provides the char8_t typedef from WG14 
N2653 [2] and introduces a _CHAR8_T_SOURCE feature test macro to opt-in 
to the new declarations.

The mbrtoc8 and c8rtomb functions are declared in uchar.h if either the 
C++20 __cpp_char8_t feature test macro or the _CHAR8_T_SOURCE feature 
test macro are defined.

The char8_t typedef is declared in uchar.h if _CHAR8_T_SOURCE is defined 
and __cpp_char8_t is not defined (if __cpp_char8_t is defined, then 
char8_t is a builtin type).

Additionally, in features.h, missing comments for the 
__GLIBC_USE_ISOC2X, __GLIBC_USE_DEPRECATED_GETS, and 
__GLIBC_USE_DEPRECATED_SCANF macros are added.

Tested on Linux x86_64.

Tom.

[1]: WG21 P0482R6
      "char8_t: A type for UTF-8 characters and strings (Revision 6)"
      https://wg21.link/p0482r6

[2]: WG14 N2653
      "char8_t: A type for UTF-8 characters and strings (Revision 1)"
      http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2653.htm

Comments

Joseph Myers June 7, 2021, 6:53 p.m. | #1
On Sun, 6 Jun 2021, Tom Honermann via Libc-alpha wrote:

> This patch provides implementations for the mbrtoc8 and c8rtomb functions

> adopted for C++20 via WG21 P0482R6 [1] and proposed for C2X via WG14 N2653

> [2].  It also provides the char8_t typedef from WG14 N2653 [2] and introduces

> a _CHAR8_T_SOURCE feature test macro to opt-in to the new declarations.


What's the reason for adding _CHAR8_T_SOURCE?  We don't normally have 
feature test macros for such narrow features (_ATFILE_SOURCE is not a good 
example to follow).

Any new feature test macro needs documenting in creature.texi - but I 
think it would be better not to add a new feature test macro in the first 
place.  _GNU_SOURCE is suitable for a proposed-but-not-yet-adopted (or a 
feature in a future standard version for which we don't yet have feature 
test macro support), if in a particular case we get consensus to add the 
feature without it having been accepted for the standard.

> Additionally, in features.h, missing comments for the __GLIBC_USE_ISOC2X,

> __GLIBC_USE_DEPRECATED_GETS, and __GLIBC_USE_DEPRECATED_SCANF macros are

> added.


These are covered by the description of __GLIBC_USE (F).  I don't think 
the __GLIBC_USE_* forms should have their own comments, since the version 
calling __GLIBC_USE is what should be tested everywhere in the headers.

> +/* Copyright (C) 2020 Free Software Foundation, Inc.


Copyright dates should include 2021.  Each file should have a line before 
the copyright notice describing its contents.

+   Contributed by Tom Honermann <tom@honermann.net>, 2020.

We don't use "Contributed by" any more in glibc.

-- 
Joseph S. Myers
joseph@codesourcery.com
Adhemerval Zanella via Libc-alpha June 11, 2021, 11:25 a.m. | #2
On 6/7/21 2:53 PM, Joseph Myers wrote:
> On Sun, 6 Jun 2021, Tom Honermann via Libc-alpha wrote:

>

>> This patch provides implementations for the mbrtoc8 and c8rtomb functions

>> adopted for C++20 via WG21 P0482R6 [1] and proposed for C2X via WG14 N2653

>> [2].  It also provides the char8_t typedef from WG14 N2653 [2] and introduces

>> a _CHAR8_T_SOURCE feature test macro to opt-in to the new declarations.

> What's the reason for adding _CHAR8_T_SOURCE?  We don't normally have

> feature test macros for such narrow features (_ATFILE_SOURCE is not a good

> example to follow).


Thank you for the review.

There are three motivations for the feature test macro:

1) Enabling pre-C2x compatibility with C++20.

2) Enabling conditional code sensitive to the change of type of u8 
string literals.

3) Avoiding clashes with existing uses of the char8_t identifier in code 
that may be compiled with _GNU_SOURCE.

I agree that this is a narrow feature, but I think the feature test 
macro is beneficial for compatibility reasons.  Assuming the proposal is 
adopted for C23, some programmers may need to opt-out of the feature by 
compiling with -fno-char8_t during a migration period; as some C++20 
projects have done.

>

> Any new feature test macro needs documenting in creature.texi - but I

> think it would be better not to add a new feature test macro in the first

> place.  _GNU_SOURCE is suitable for a proposed-but-not-yet-adopted (or a

> feature in a future standard version for which we don't yet have feature

> test macro support), if in a particular case we get consensus to add the

> feature without it having been accepted for the standard.


Thanks for the pointer to creature.texi; I'll provide an update.

I understand the motivation for avoiding new feature test macros, but I 
think one is warranted in this case.

>

>> Additionally, in features.h, missing comments for the __GLIBC_USE_ISOC2X,

>> __GLIBC_USE_DEPRECATED_GETS, and __GLIBC_USE_DEPRECATED_SCANF macros are

>> added.

> These are covered by the description of __GLIBC_USE (F).  I don't think

> the __GLIBC_USE_* forms should have their own comments, since the version

> calling __GLIBC_USE is what should be tested everywhere in the headers.


Ok, I'll remove them.

I see I also neglected to update the comment for _CHAR8_T_SOURCE to 
reference the current paper number; will fix.

>

>> +/* Copyright (C) 2020 Free Software Foundation, Inc.

> Copyright dates should include 2021.  Each file should have a line before

> the copyright notice describing its contents.

Yes, a copy-and-forgot-to-update issue; will fix.
>

> +   Contributed by Tom Honermann <tom@honermann.net>, 2020.

>

> We don't use "Contributed by" any more in glibc.


Ok, good to know, I'll remove.

Tom.
Joseph Myers June 11, 2021, 4:28 p.m. | #3
On Fri, 11 Jun 2021, Tom Honermann via Libc-alpha wrote:

> 1) Enabling pre-C2x compatibility with C++20.


Where a feature in a header should be enabled for a particular C++ 
version, we can have an internal __GLIBC_USE (CXX20) which is enabled 
based on the value of __cplusplus, just like the existing __USE_ISOCXX11.  
(Though that doesn't make much practical difference until we provide a way 
for C++ library headers to get all the features they need without defining 
_GNU_SOURCE.)

You'd then have

#if defined __USE_GNU || __GLIBC_USE (CXX20)

in uchar.h, with appropriate !defined __cpp_char8_t for defining the 
typedef itself.  And the defined __USE_GNU would become __GLIBC_USE 
(ISOC2X) if the feature is accepted for C2x.

> 2) Enabling conditional code sensitive to the change of type of u8 string

> literals.


That might be a reason for a compiler option (I don't think it's a 
sufficient reason, I expect -std=c11 or -Wno-pointer-sign or pointer casts 
to suffice in practice), but it has nothing to do with the use of feature 
test macros in glibc since the library headers don't care at all what the 
type of u8 string literals is (there are no u8 string literals anywhere in 
glibc).

> 3) Avoiding clashes with existing uses of the char8_t identifier in code that

> may be compiled with _GNU_SOURCE.


It's a universal feature in glibc that all non-obsolescent, 
non-conflicting features are enabled with _GNU_SOURCE, including features 
from future standard versions - all feature test macros are subsets of 
_GNU_SOURCE, except where the features actually conflict in some way (a 
few cases where a POSIX function has semantics incompatible with a GNU 
function of the same name), and features from future standards with no 
feature test macro support in glibc (e.g. some features proposed for the 
next POSIX version) are also enabled by _GNU_SOURCE.

So char8_t and these functions should be enabled by _GNU_SOURCE, 
regardless of what other options enable them.

Users of _GNU_SOURCE are expected to deal with possible naming conflicts 
with features added to _GNU_SOURCE.  Likewise people building with 
-std=gnu2x / -std=c2x, which would enable these declarations if char8_t 
and these functions are added to C2x, or users of _ISOC2X_SOURCE (which 
isn't expected to be used much).

> I agree that this is a narrow feature, but I think the feature test macro is

> beneficial for compatibility reasons.  Assuming the proposal is adopted for

> C23, some programmers may need to opt-out of the feature by compiling with

> -fno-char8_t during a migration period; as some C++20 projects have done.


We don't provide a way to opt out of any other library additions when 
compiling in C2x mode; compiling with -std=c2x or -std=gnu2x or 
-D_GNU_SOURCE unconditionally enables all other C2x additions in headers 
(including e.g. the iszero macro, although the issues seen with that were 
mainly for C++ code and we addressed that by making it a template instead 
of a macro for C++), compiling with e.g. -std=c11 or -std=gnu11 (and not 
using _GNU_SOURCE) is how you opt out of all such additions at the same 
time.  Likewise for previous C standard versions.  And _GNU_SOURCE is the 
universal way to opt in to features that might or might not be in a future 
standard version.  If such a feature has its own TS, we may support the 
__STDC_WANT_* macros from such a TS, but that's not a basis for creating 
our own feature test macro for a handful of new identifiers.

-- 
Joseph S. Myers
joseph@codesourcery.com
Adhemerval Zanella via Libc-alpha June 13, 2021, 3:35 p.m. | #4
On 6/11/21 12:28 PM, Joseph Myers wrote:
> On Fri, 11 Jun 2021, Tom Honermann via Libc-alpha wrote:

>

>> 1) Enabling pre-C2x compatibility with C++20.

> Where a feature in a header should be enabled for a particular C++

> version, we can have an internal __GLIBC_USE (CXX20) which is enabled

> based on the value of __cplusplus, just like the existing __USE_ISOCXX11.

> (Though that doesn't make much practical difference until we provide a way

> for C++ library headers to get all the features they need without defining

> _GNU_SOURCE.)

>

> You'd then have

>

> #if defined __USE_GNU || __GLIBC_USE (CXX20)

>

> in uchar.h, with appropriate !defined __cpp_char8_t for defining the

> typedef itself.  And the defined __USE_GNU would become __GLIBC_USE

> (ISOC2X) if the feature is accepted for C2x.


Sounds good for C.

For C++ though, the declarations of mbrtoc8() and c8rtomb() need to be 
aligned with libstdc++ expectations since they are redeclared in the std 
namespace if available.  The corresponding libstdc++ patch 
<https://gcc.gnu.org/pipermail/libstdc++/2021-June/052685.html> probes 
whether these functions are available through an autoconf probe that 
runs g++ -fchar8_t; the redeclarations are then dependent only on 
whether char8_t support is enabled (for C++, the corresponding library 
support is dependent on the core language changes).  Restricting the 
declarations as you suggest would result in compilation errors for 
invocations like g++ -std=c++17 -fchar8_t and g++ -std=c++2x -fchar8_t.  
The char8_t dialect already exists for C++, and I think the glibc 
changes should align with that for C++.  I think it is fine if the new 
functions are declared for modes like g++ -std=gnu++17; there is no need 
to disable them with -fno-char8_t.  I therefore suggest:

#if defined __USE_GNU || /* __GLIBC_USE (ISOC2X) || */ defined __cpp_char8_t

>

>> 2) Enabling conditional code sensitive to the change of type of u8 string

>> literals.

> That might be a reason for a compiler option (I don't think it's a

> sufficient reason, I expect -std=c11 or -Wno-pointer-sign or pointer casts

> to suffice in practice), but it has nothing to do with the use of feature

> test macros in glibc since the library headers don't care at all what the

> type of u8 string literals is (there are no u8 string literals anywhere in

> glibc).

That's fair.  I think Jakub's suggestion on gcc-patches to use 
__CHAR8_TYPE__ to conditionalize sensitive code suffices.
>

>> 3) Avoiding clashes with existing uses of the char8_t identifier in code that

>> may be compiled with _GNU_SOURCE.

> It's a universal feature in glibc that all non-obsolescent,

> non-conflicting features are enabled with _GNU_SOURCE, including features

> from future standard versions - all feature test macros are subsets of

> _GNU_SOURCE, except where the features actually conflict in some way (a

> few cases where a POSIX function has semantics incompatible with a GNU

> function of the same name), and features from future standards with no

> feature test macro support in glibc (e.g. some features proposed for the

> next POSIX version) are also enabled by _GNU_SOURCE.

>

> So char8_t and these functions should be enabled by _GNU_SOURCE,

> regardless of what other options enable them.

>

> Users of _GNU_SOURCE are expected to deal with possible naming conflicts

> with features added to _GNU_SOURCE.  Likewise people building with

> -std=gnu2x / -std=c2x, which would enable these declarations if char8_t

> and these functions are added to C2x, or users of _ISOC2X_SOURCE (which

> isn't expected to be used much).

Ok, great.  I wasn't aware that _GNU_SOURCE was intended to be this 
inconclusive.
>

>> I agree that this is a narrow feature, but I think the feature test macro is

>> beneficial for compatibility reasons.  Assuming the proposal is adopted for

>> C23, some programmers may need to opt-out of the feature by compiling with

>> -fno-char8_t during a migration period; as some C++20 projects have done.

> We don't provide a way to opt out of any other library additions when

> compiling in C2x mode; compiling with -std=c2x or -std=gnu2x or

> -D_GNU_SOURCE unconditionally enables all other C2x additions in headers

> (including e.g. the iszero macro, although the issues seen with that were

> mainly for C++ code and we addressed that by making it a template instead

> of a macro for C++), compiling with e.g. -std=c11 or -std=gnu11 (and not

> using _GNU_SOURCE) is how you opt out of all such additions at the same

> time.  Likewise for previous C standard versions.  And _GNU_SOURCE is the

> universal way to opt in to features that might or might not be in a future

> standard version.  If such a feature has its own TS, we may support the

> __STDC_WANT_* macros from such a TS, but that's not a basis for creating

> our own feature test macro for a handful of new identifiers.


Perfect.

Per this and prior messages, I'll review the patch series as follows:

 1. Remove uses of the _CHAR8_T_SOURCE macro.
 2. Remove the comments added for __GLIBC_USE_ISOC2X,
    __GLIBC_USE_DEPRECATED_GETS, and __GLIBC_USE_DEPRECATED_SCANF.
 3. Remove the __GLIBC_USE_CHAR8_T macro.
 4. Conditionalize the char8_t, mbrtoc8() and c8rtomb() declarations on
    __USE_GNU and __cpp_char8_t (and perhaps __GLIBC_USE (ISOC2X)
    eventually).
 5. Transition the new tests to the support/test-driver.c driver and use
    the support/check.h interfaces.
 6. Correct the copyright statements.
 7. Remove the "contributed by" comments.

If I've forgotten anything, please let me know.

Thank you for the thorough review!

Tom.

Patch

commit 9b79320a42146cda02338941606cbf4ee0ca0db8
Author: Tom Honermann <tom@honermann.net>
Date:   Fri Feb 12 22:00:26 2021 -0500

    Implement mbrtoc8(), c8rtomb(), and the char8_t typedef.
    
    This change provides implementations for the mbrtoc8 and c8rtomb
    functions adopted for C++20 via WG21 P0482R6 and proposed for C2X
    via WG14 N2653.  It also provides the char8_t typedef from N2653
    and introduces a _CHAR8_T_SOURCE feature test macro to opt-in to
    the new declarations.
    
    The mbrtoc8 and c8rtomb functions are declared in uchar.h if
    either the C++20 __cpp_char8_t feature test macro or the
    _CHAR8_T_SOURCE feature test macro are defined.
    
    The char8_t typedef is declared in uchar.h if _CHAR8_T_SOURCE is
    defined and __cpp_char8_t is not defined (if __cpp_char8_t is
    defined, then char8_t is a builtin type).
    
    In features.h, missing comments for the __GLIBC_USE_ISOC2X,
    __GLIBC_USE_DEPRECATED_GETS, and __GLIBC_USE_DEPRECATED_SCANF
    macros are added.

diff --git a/NEWS b/NEWS
index 266837bf2d..67793fc324 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,15 @@  Major new features:
 
 * The ISO C2X function timespec_getres has been added.
 
+* The mbrtoc8 and c8rtomb functions are added for implementation of the
+  C++20 P0482R6 and C2X N2653 proposals.  These functions perform conversions
+  between multibyte sequences and the UTF-8 character encoding.  A char8_t
+  typedef is added for the C2X N2653 proposal.  The functions are declared
+  in uchar.h if the C++20 __cpp_char8_t feature test macro or the
+  _CHAR8_T_SOURCE feature test macro is defined.  The char8_t typedef is
+  declared in uchar.h if _CHAR8_T_SOURCE is defined and __cpp_char8_t is
+  not defined.
+
 Deprecated and removed features, and other changes affecting compatibility:
 
 * The function pthread_mutex_consistent_np has been deprecated; programs
diff --git a/include/features.h b/include/features.h
index eb97470afa..9437f0f0b8 100644
--- a/include/features.h
+++ b/include/features.h
@@ -60,6 +60,8 @@ 
    _REENTRANT, _THREAD_SAFE
 			Obsolete; equivalent to _POSIX_C_SOURCE=199506L.
 
+   _CHAR8_T_SOURCE	Extensions for char8_t as specified in WG14 N2231.
+
    The `-ansi' switch to the GNU C compiler, and standards conformance
    options such as `-std=c99', define __STRICT_ANSI__.  If none of
    these are defined, or if _DEFAULT_SOURCE is defined, the default is
@@ -100,6 +102,12 @@ 
 			MINSIGSTKSZ and SIGSTKSZ.
    __USE_GNU		Define GNU extensions.
    __USE_FORTIFY_LEVEL	Additional security measures used, according to level.
+   __GLIBC_USE_ISOC2X	Define ISO C2X things.
+   __GLIBC_USE_DEPRECATED_GETS
+			Define deprecated gets()
+   __GLIBC_USE_DEPRECATED_SCANF
+			Define deprecated scanf()
+   __GLIBC_USE_CHAR8_T	Define extensions for char8_t as specified in WG14 N2231.
 
    The macros `__GNU_LIBRARY__', `__GLIBC__', and `__GLIBC_MINOR__' are
    defined by this file unconditionally.  `__GNU_LIBRARY__' is provided
@@ -148,6 +156,7 @@ 
 #undef	__GLIBC_USE_ISOC2X
 #undef	__GLIBC_USE_DEPRECATED_GETS
 #undef	__GLIBC_USE_DEPRECATED_SCANF
+#undef	__GLIBC_USE_CHAR8_T
 
 /* Suppress kernel-name space pollution unless user expressedly asks
    for it.  */
@@ -457,6 +466,16 @@ 
 # define __GLIBC_USE_DEPRECATED_SCANF 0
 #endif
 
+/* The char8_t related c8rtomb and mbrtoc8 functions are declared if the
+   C++ __cpp_char8_t feature test macro is defined or if _CHAR8_T_SOURCE
+   is defined.  The char8_t typedef is declared if _CHAR8_T_SOURCE is
+   defined and the C++ __cpp_char8_t feature test macro is not defined.  */
+#if defined _CHAR8_T_SOURCE || defined __cpp_char8_t
+# define __GLIBC_USE_CHAR8_T   1
+#else
+# define __GLIBC_USE_CHAR8_T   0
+#endif
+
 /* Get definitions of __STDC_* predefined macros, if the compiler has
    not preincluded this header automatically.  */
 #include <stdc-predef.h>
diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
index 49aa809366..f536073108 100644
--- a/sysdeps/mach/hurd/i386/libc.abilist
+++ b/sysdeps/mach/hurd/i386/libc.abilist
@@ -2207,7 +2207,9 @@  GLIBC_2.33 stat64 F
 GLIBC_2.34 __isnanf128 F
 GLIBC_2.34 __libc_start_main F
 GLIBC_2.34 _hurd_libc_proc_init F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 timespec_getres F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index d22c7da7ef..54eb6473ff 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2335,6 +2335,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2343,6 +2344,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index cefff3bf36..288ed25ab1 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2427,6 +2427,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2435,6 +2436,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
index 91a90f8ca4..3ef5eaf40f 100644
--- a/sysdeps/unix/sysv/linux/arc/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
@@ -2094,6 +2094,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2102,6 +2103,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
index 120288d766..5553b89bc1 100644
--- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
@@ -200,6 +200,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -208,6 +209,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
index be987da77e..9813f6ca87 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -197,6 +197,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -205,6 +206,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index adb4e15cb8..d457c6e42a 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2278,6 +2278,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2286,6 +2287,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index bd022276e8..23ea3705ba 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2231,6 +2231,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2239,6 +2240,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 9e37e1cb38..39f6611ee0 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2415,6 +2415,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2423,6 +2424,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index b8089b0b0c..4bb6092441 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2267,6 +2267,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2275,6 +2276,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 093854ad85..63a8877c38 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -201,6 +201,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -209,6 +210,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 87554f1468..f3c8644e51 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2358,6 +2358,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2366,6 +2367,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
index e9340671c5..5897810a1f 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -2329,6 +2329,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2337,6 +2338,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
index 6ddc0e90cf..7d1672eb0d 100644
--- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
@@ -2326,6 +2326,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2334,6 +2335,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 8582c9c371..4a4a43aad7 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2323,6 +2323,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2331,6 +2332,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index b0849bec98..fa33fc92d1 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2321,6 +2321,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2329,6 +2330,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 386660a5a1..3dcdfa2b39 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2329,6 +2329,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2337,6 +2338,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 4d05128f21..e4685a7e10 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2323,6 +2323,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2331,6 +2332,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index bd305f440f..3204a54838 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2368,6 +2368,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2376,6 +2377,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index c2665624aa..b0122085c9 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2385,6 +2385,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2393,6 +2394,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 13ef6ef39e..c7e4209cf5 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2418,6 +2418,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2426,6 +2427,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index b21072e313..0e14ea72ca 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2232,6 +2232,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2240,6 +2241,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index 62af65536c..2ff5fbc8a5 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2531,6 +2531,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2539,6 +2540,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
index a63aec3379..dbe5fcf2ae 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
@@ -2096,6 +2096,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2104,6 +2105,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index b52efaf5ee..9b9afda286 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2296,6 +2296,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2304,6 +2305,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index b699dedcc1..1ca55714a6 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2383,6 +2383,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2391,6 +2392,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 94209858b1..7348c3aa2a 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2269,6 +2269,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2277,6 +2278,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
index 0fab90e1e3..279f3388ac 100644
--- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
@@ -2238,6 +2238,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2246,6 +2247,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
index 2f3a64b580..cce9c390da 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -2235,6 +2235,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2243,6 +2244,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index e6fe453f50..54e64f4654 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2376,6 +2376,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2384,6 +2385,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 4327cf5eb3..11f9bc8db2 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2288,6 +2288,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2296,6 +2297,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 318a6d50f9..b9cae9f7ab 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2247,6 +2247,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2255,6 +2256,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 0bcf898d4d..cf633eefa4 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2350,6 +2350,7 @@  GLIBC_2.34 __pthread_register_cancel_defer F
 GLIBC_2.34 __pthread_unregister_cancel F
 GLIBC_2.34 __pthread_unregister_cancel_restore F
 GLIBC_2.34 __pthread_unwind_next F
+GLIBC_2.34 c8rtomb F
 GLIBC_2.34 call_once F
 GLIBC_2.34 cnd_broadcast F
 GLIBC_2.34 cnd_destroy F
@@ -2358,6 +2359,7 @@  GLIBC_2.34 cnd_signal F
 GLIBC_2.34 cnd_timedwait F
 GLIBC_2.34 cnd_wait F
 GLIBC_2.34 execveat F
+GLIBC_2.34 mbrtoc8 F
 GLIBC_2.34 mtx_destroy F
 GLIBC_2.34 mtx_init F
 GLIBC_2.34 mtx_lock F
diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
index f38eb5cfe1..e0c8acf591 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..acf6c3b705 100644
--- a/wcsmbs/Versions
+++ b/wcsmbs/Versions
@@ -49,4 +49,7 @@  libc {
     wcstof32; wcstof64; wcstof32x;
     wcstof32_l; wcstof64_l; wcstof32x_l;
   }
+  GLIBC_2.34 {
+    c8rtomb; mbrtoc8;
+  }
 }
diff --git a/wcsmbs/c8rtomb.c b/wcsmbs/c8rtomb.c
new file mode 100644
index 0000000000..ebb1e73e5c
--- /dev/null
+++ b/wcsmbs/c8rtomb.c
@@ -0,0 +1,137 @@ 
+/* Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Tom Honermann <tom@honermann.net>, 2020.
+
+   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/>.  */
+
+/* Ensure that char8_t support is enabled so that the char8_t typedef is
+   declared.  */
+#define _CHAR8_T_SOURCE
+
+#include <features.h>
+#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..c112216de5
--- /dev/null
+++ b/wcsmbs/mbrtoc8.c
@@ -0,0 +1,131 @@ 
+/* Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Tom Honermann <tom@honermann.net>, 2020.
+
+   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/>.  */
+
+/* Ensure that char8_t support is enabled so that the char8_t typedef is
+   declared.  */
+#define _CHAR8_T_SOURCE
+
+#include <features.h>
+#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 6020f66cf6..b23ff1a5ac 100644
--- a/wcsmbs/uchar.h
+++ b/wcsmbs/uchar.h
@@ -31,6 +31,14 @@ 
 #include <bits/types.h>
 #include <bits/types/mbstate_t.h>
 
+/* Define the char8_t typedef if support is enabled, but only if the C++
+   predefined feature test macro that indicates char8_t is a builtin type
+   is not defined.  */
+#if __GLIBC_USE (CHAR8_T) && !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 +48,18 @@  typedef __uint_least32_t char32_t;
 
 __BEGIN_DECLS
 
+#if __GLIBC_USE (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,