On Mon, Jan 5, 2026 at 6:47 PM Keith Packard <[email protected]> wrote: > > Existing toolchain builds rely on the similarity between picolibc and > newlib when building libstdc++ and use --with-newlib.
One note libstdc++ patches should also be sent to [email protected] also. Thanks, Andrew > > Switch to the picolibc 16-bit _ctype_wide array which provides > separate values for ctype_base::blank and ctype_base::space. > > This fixes a bug where libstdc++ was including '\f', '\n', '\r' and > '\v' in the set of 'blank' chars. Afterwards, only ' ' and '\t' are in > this set, as specified by C++ 11. > > Signed-off-by: Keith Packard <[email protected]> > --- > libstdc++-v3/acinclude.m4 | 4 + > libstdc++-v3/config/os/picolibc/ctype_base.h | 61 ++++++++++ > .../os/picolibc/ctype_configure_char.cc | 105 ++++++++++++++++++ > .../config/os/picolibc/ctype_inline.h | 74 ++++++++++++ > libstdc++-v3/config/os/picolibc/os_defines.h | 61 ++++++++++ > libstdc++-v3/configure.ac | 62 +++++++++++ > 6 files changed, 367 insertions(+) > create mode 100644 libstdc++-v3/config/os/picolibc/ctype_base.h > create mode 100644 libstdc++-v3/config/os/picolibc/ctype_configure_char.cc > create mode 100644 libstdc++-v3/config/os/picolibc/ctype_inline.h > create mode 100644 libstdc++-v3/config/os/picolibc/os_defines.h > > diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 > index 103515c000f..1eb575d3202 100644 > --- a/libstdc++-v3/acinclude.m4 > +++ b/libstdc++-v3/acinclude.m4 > @@ -81,6 +81,10 @@ AC_DEFUN([GLIBCXX_CONFIGURE], [ > AC_HELP_STRING([--with-newlib], > [assume newlib as a system C library])) > > + AC_ARG_WITH([picolibc], > + AC_HELP_STRING([--with-picolibc], > + [assume picolibc as a system C library])) > + > # Will set LN_S to either 'ln -s', 'ln', or 'cp -p' (if linking isn't > # available). Uncomment the next line to force a particular method. > AC_PROG_LN_S > diff --git a/libstdc++-v3/config/os/picolibc/ctype_base.h > b/libstdc++-v3/config/os/picolibc/ctype_base.h > new file mode 100644 > index 00000000000..0d73c74387f > --- /dev/null > +++ b/libstdc++-v3/config/os/picolibc/ctype_base.h > @@ -0,0 +1,61 @@ > +// Locale support -*- C++ -*- > + > +// Copyright (C) 2000-2026 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > + > +// This 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 General Public License for more details. > + > +// Under Section 7 of GPL version 3, you are granted additional > +// permissions described in the GCC Runtime Library Exception, version > +// 3.1, as published by the Free Software Foundation. > + > +// You should have received a copy of the GNU General Public License and > +// a copy of the GCC Runtime Library Exception along with this program; > +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see > +// <http://www.gnu.org/licenses/>. > + > +// > +// ISO C++ 14882: 22.1 Locales > +// > + > +// Information as gleaned from /usr/include/ctype.h > + > +namespace std _GLIBCXX_VISIBILITY(default) > +{ > +_GLIBCXX_BEGIN_NAMESPACE_VERSION > + > + /// @brief Base class for ctype. > + struct ctype_base > + { > + // Non-standard typedefs. > + typedef const int* __to_type; > + > + // NB: Offsets into ctype<char>::_M_table force a particular size > + // on the mask type. Because of this, we don't use an enum. > + typedef short mask; > + static const mask upper = mask (__CTYPE_UPPER); > + static const mask lower = mask (__CTYPE_LOWER); > + static const mask alpha = mask (__CTYPE_UPPER | __CTYPE_LOWER); > + static const mask digit = mask (__CTYPE_DIGIT); > + static const mask xdigit = mask (__CTYPE_HEX | __CTYPE_DIGIT); > + static const mask space = mask (__CTYPE_SPACE); > + static const mask print = mask (__CTYPE_PUNCT | __CTYPE_UPPER | > __CTYPE_LOWER | __CTYPE_DIGIT | __CTYPE_BLANK); > + static const mask graph = mask (__CTYPE_PUNCT | __CTYPE_UPPER | > __CTYPE_LOWER | __CTYPE_DIGIT); > + static const mask cntrl = mask (__CTYPE_CNTRL); > + static const mask punct = mask (__CTYPE_PUNCT); > + static const mask alnum = mask (__CTYPE_UPPER | __CTYPE_LOWER | > __CTYPE_DIGIT); > +#if __cplusplus >= 201103L > + static const mask blank = mask (__CTYPE_BLANK | __CTYPE_TAB); > +#endif > + }; > + > +_GLIBCXX_END_NAMESPACE_VERSION > +} // namespace > diff --git a/libstdc++-v3/config/os/picolibc/ctype_configure_char.cc > b/libstdc++-v3/config/os/picolibc/ctype_configure_char.cc > new file mode 100644 > index 00000000000..74370d4be49 > --- /dev/null > +++ b/libstdc++-v3/config/os/picolibc/ctype_configure_char.cc > @@ -0,0 +1,105 @@ > +// Locale support -*- C++ -*- > + > +// Copyright (C) 2011-2026 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > + > +// This 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 General Public License for more details. > + > +// Under Section 7 of GPL version 3, you are granted additional > +// permissions described in the GCC Runtime Library Exception, version > +// 3.1, as published by the Free Software Foundation. > + > +// You should have received a copy of the GNU General Public License and > +// a copy of the GCC Runtime Library Exception along with this program; > +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see > +// <http://www.gnu.org/licenses/>. > + > +/** @file ctype_configure_char.cc */ > + > +// > +// ISO C++ 14882: 22.1 Locales > +// > + > +#include <locale> > +#include <cstdlib> > +#include <cstring> > + > +namespace std _GLIBCXX_VISIBILITY(default) > +{ > +_GLIBCXX_BEGIN_NAMESPACE_VERSION > + > +// Information as gleaned from /usr/include/ctype.h > + > + const ctype_base::mask* > + ctype<char>::classic_table() throw() > + { return _ctype_wide + 1; } > + > + ctype<char>::ctype(__c_locale, const mask* __table, bool __del, > + size_t __refs) > + : facet(__refs), _M_del(__table != 0 && __del), > + _M_toupper(NULL), _M_tolower(NULL), > + _M_table(__table ? __table : classic_table()) > + { > + memset(_M_widen, 0, sizeof(_M_widen)); > + _M_widen_ok = 0; > + memset(_M_narrow, 0, sizeof(_M_narrow)); > + _M_narrow_ok = 0; > + } > + > + ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) > + : facet(__refs), _M_del(__table != 0 && __del), > + _M_toupper(NULL), _M_tolower(NULL), > + _M_table(__table ? __table : classic_table()) > + { > + memset(_M_widen, 0, sizeof(_M_widen)); > + _M_widen_ok = 0; > + memset(_M_narrow, 0, sizeof(_M_narrow)); > + _M_narrow_ok = 0; > + } > + > + char > + ctype<char>::do_toupper(char __c) const > + { > + int __x = __c; > + return (this->is(ctype_base::lower, __c) ? (__x - 'a' + 'A') : __x); > + } > + > + const char* > + ctype<char>::do_toupper(char* __low, const char* __high) const > + { > + while (__low < __high) > + { > + *__low = this->do_toupper(*__low); > + ++__low; > + } > + return __high; > + } > + > + char > + ctype<char>::do_tolower(char __c) const > + { > + int __x = __c; > + return (this->is(ctype_base::upper, __c) ? (__x - 'A' + 'a') : __x); > + } > + > + const char* > + ctype<char>::do_tolower(char* __low, const char* __high) const > + { > + while (__low < __high) > + { > + *__low = this->do_tolower(*__low); > + ++__low; > + } > + return __high; > + } > + > +_GLIBCXX_END_NAMESPACE_VERSION > +} // namespace > diff --git a/libstdc++-v3/config/os/picolibc/ctype_inline.h > b/libstdc++-v3/config/os/picolibc/ctype_inline.h > new file mode 100644 > index 00000000000..950983800e7 > --- /dev/null > +++ b/libstdc++-v3/config/os/picolibc/ctype_inline.h > @@ -0,0 +1,74 @@ > +// Locale support -*- C++ -*- > + > +// Copyright (C) 2000-2026 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > + > +// This 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 General Public License for more details. > + > +// Under Section 7 of GPL version 3, you are granted additional > +// permissions described in the GCC Runtime Library Exception, version > +// 3.1, as published by the Free Software Foundation. > + > +// You should have received a copy of the GNU General Public License and > +// a copy of the GCC Runtime Library Exception along with this program; > +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see > +// <http://www.gnu.org/licenses/>. > + > +/** @file bits/ctype_inline.h > + * This is an internal header file, included by other library headers. > + * Do not attempt to use it directly. @headername{locale} > + */ > + > +// > +// ISO C++ 14882: 22.1 Locales > +// > + > +// ctype bits to be inlined go here. Non-inlinable (ie virtual do_*) > +// functions go in ctype.cc > + > +namespace std _GLIBCXX_VISIBILITY(default) > +{ > +_GLIBCXX_BEGIN_NAMESPACE_VERSION > + > + bool > + ctype<char>:: > + is(mask __m, char __c) const > + { return _M_table[static_cast<unsigned char>(__c)] & __m; } > + > + const char* > + ctype<char>:: > + is(const char* __low, const char* __high, mask* __vec) const > + { > + while (__low < __high) > + *__vec++ = _M_table[static_cast<unsigned char>(*__low++)]; > + return __high; > + } > + > + const char* > + ctype<char>:: > + scan_is(mask __m, const char* __low, const char* __high) const > + { > + while (__low < __high && !this->is(__m, *__low)) > + ++__low; > + return __low; > + } > + > + const char* > + ctype<char>:: > + scan_not(mask __m, const char* __low, const char* __high) const > + { > + while (__low < __high && this->is(__m, *__low) != 0) > + ++__low; > + return __low; > + } > + > +_GLIBCXX_END_NAMESPACE_VERSION > +} // namespace > diff --git a/libstdc++-v3/config/os/picolibc/os_defines.h > b/libstdc++-v3/config/os/picolibc/os_defines.h > new file mode 100644 > index 00000000000..fa180715d9e > --- /dev/null > +++ b/libstdc++-v3/config/os/picolibc/os_defines.h > @@ -0,0 +1,61 @@ > +// Specific definitions for newlib -*- C++ -*- > + > +// Copyright (C) 2000-2026 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > + > +// This 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 General Public License for more details. > + > +// Under Section 7 of GPL version 3, you are granted additional > +// permissions described in the GCC Runtime Library Exception, version > +// 3.1, as published by the Free Software Foundation. > + > +// You should have received a copy of the GNU General Public License and > +// a copy of the GCC Runtime Library Exception along with this program; > +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see > +// <http://www.gnu.org/licenses/>. > + > +/** @file bits/os_defines.h > + * This is an internal header file, included by other library headers. > + * Do not attempt to use it directly. @headername{iosfwd} > + */ > + > +#ifndef _GLIBCXX_OS_DEFINES > +#define _GLIBCXX_OS_DEFINES 1 > + > +// System-specific #define, typedefs, corrections, etc, go here. This > +// file will come before all others. > + > +#ifdef __CYGWIN__ > +#define _GLIBCXX_GTHREAD_USE_WEAK 0 > + > +#if defined (_GLIBCXX_DLL) > +#define _GLIBCXX_PSEUDO_VISIBILITY_default __attribute__ ((__dllimport__)) > +#else > +#define _GLIBCXX_PSEUDO_VISIBILITY_default > +#endif > +#define _GLIBCXX_PSEUDO_VISIBILITY_hidden > + > +#define _GLIBCXX_PSEUDO_VISIBILITY(V) _GLIBCXX_PSEUDO_VISIBILITY_ ## V > + > +// See libstdc++/20806. > +#define _GLIBCXX_HAVE_DOS_BASED_FILESYSTEM 1 > + > +// Enable use of GetModuleHandleEx (requires Windows XP/2003) in > +// __cxa_thread_atexit to prevent modules from being unloaded before > +// their dtors are called > +#define _GLIBCXX_THREAD_ATEXIT_WIN32 1 > + > +// See libstdc++/69506 > +#define _GLIBCXX_USE_WEAK_REF 0 > + > +#endif > + > +#endif > diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac > index 339e7bb17a4..cd038ee85ac 100644 > --- a/libstdc++-v3/configure.ac > +++ b/libstdc++-v3/configure.ac > @@ -100,6 +100,7 @@ GLIBCXX_CONFIGURE > > # Libtool setup. > if test "x${with_newlib}" != "xyes" && > + test "x${with_picolibc}" != "xyes" && > test "x${with_avrlibc}" != "xyes" && > test "x$with_headers" != "xno"; then > AC_LIBTOOL_DLOPEN > @@ -428,6 +429,67 @@ dnl # rather than hardcoding that information. > glibcxx_cv_mkdir=yes > ;; > esac > + elif test "x${with_picolibc}" = "xyes"; then > + os_include_dir="os/picolibc" > + AC_DEFINE(HAVE_HYPOT) > + > + # GLIBCXX_CHECK_STDLIB_SUPPORT > + AC_DEFINE(HAVE_STRTOF) > + > + AC_DEFINE(HAVE_ACOSF) > + AC_DEFINE(HAVE_ASINF) > + AC_DEFINE(HAVE_ATAN2F) > + AC_DEFINE(HAVE_ATANF) > + AC_DEFINE(HAVE_CEILF) > + AC_DEFINE(HAVE_COSF) > + AC_DEFINE(HAVE_COSHF) > + AC_DEFINE(HAVE_EXPF) > + AC_DEFINE(HAVE_FABSF) > + AC_DEFINE(HAVE_FLOORF) > + AC_DEFINE(HAVE_FMODF) > + AC_DEFINE(HAVE_FREXPF) > + AC_DEFINE(HAVE_HYPOTF) > + AC_DEFINE(HAVE_LDEXPF) > + AC_DEFINE(HAVE_LOG10F) > + AC_DEFINE(HAVE_LOGF) > + AC_DEFINE(HAVE_MODFF) > + AC_DEFINE(HAVE_POWF) > + AC_DEFINE(HAVE_SINF) > + AC_DEFINE(HAVE_SINHF) > + AC_DEFINE(HAVE_SQRTF) > + AC_DEFINE(HAVE_TANF) > + AC_DEFINE(HAVE_TANHF) > + > + # Support for iconv in picolibc is configurable. > + AC_TRY_COMPILE([#include <picolibc.h>], [ > + #ifndef _ICONV_ENABLED > + #error > + #endif], [ac_picolibc_iconv_enabled=yes], > [ac_picolibc_iconv_enabled=no]) > + if test "$ac_picolibc_iconv_enabled" = yes; then > + AC_DEFINE(HAVE_ICONV) > + fi > + > + AC_DEFINE(HAVE_MEMALIGN) > + > + # Check for TLS > + AC_TRY_COMPILE([#include <picolibc.h>], [ > + #ifndef __THREAD_LOCAL_STORAGE > + #error > + #endif], [ac_picolibc_tls_enabled=yes], [ac_picolibc_tls_enabled=no]) > + if test "$ac_picolibc_tls_enabled" = yes; then > + AC_DEFINE(HAVE_TLS) > + fi > + > + AC_DEFINE(HAVE_ALIGNED_ALLOC) > + AC_DEFINE(HAVE_AT_QUICK_EXIT) > + AC_DEFINE(HAVE_LINK) > + AC_DEFINE(HAVE_SYS_STAT_H) > + AC_DEFINE(HAVE_SYS_TYPES_H) > + AC_DEFINE(HAVE_SETENV) > + AC_DEFINE(HAVE_STRERROR_L) > + AC_DEFINE(HAVE_S_ISREG) > + AC_DEFINE(HAVE_UNISTD_H) > + > elif test "x$with_headers" != "xno"; then > GLIBCXX_CROSSCONFIG > fi > -- > 2.51.0 >
