On Mon, Aug 3, 2026 at 6:58 PM Jonathan Wakely <[email protected]> wrote:
> The <cerrno> header is freestanding in C++26. Since we don't have to be
> compatible with a C library or a kernel for freestanding, we can just
> define the error number macros to arbitrary values.
>
> We need to provide a consistent set of definitions whether <cerrno> or
> <errno.h> is included, and whether a freestanding header is included by
> using -ffreestanding with a full hosted installation, or with a
> non-hosted (i.e. --disable-hosted-libstdcxx) installation. We do not
> want a situation where including <errno.h> uses a system libc header and
> defines one set of values, but <cerrno> provides our own freestanding
> values.
>
> The approach taken here is to install our own copy of <errno.h> which
> does #include_next <errno.h> for hosted and which defines its own values
> for freestanding. Our <cerrno> will then find our own <errno.h> and so
> <cerrno> and <errno.h> will be consistent, and the macro values will
> always be the same for the freestanding headers.
>
> libstdc++-v3/ChangeLog:
>
> * include/Makefile.am (c_base_freestanding): Move cerrno to
> here from ...
> (c_base_headers): ... here.
> (c_compatibility_headers): Add errno.h.
> * include/Makefile.in: Regenerate.
> * include/c_compatibility/errno.h: Replace include <cerrno> with
> include_next <errno.h>.
> [!_GLIBCXX_HOSTED] (E2BIG,EACCES,EADDRINUSE,EADDRNOTAVAIL)
> (EAFNOSUPPORT,EAGAIN,EALREADY,EBADF,EBADMSG,EBUSY,ECANCELED)
> (ECHILD,ECONNABORTED,ECONNREFUSED,ECONNRESET,EDEADLK)
> (EDESTADDRREQ,EDOM,EEXIST,EFAULT,EFBIG,EHOSTUNREACH,EIDRM)
> (EILSEQ,EINPROGRESS,EINTR,EINVAL,EIO,EISCONN,EISDIR,ELOOP)
> (EMFILE,EMLINK,EMSGSIZE,ENAMETOOLONG,ENETDOWN,ENETRESET)
> (ENETUNREACH,ENFILE,ENOBUFS,ENODEV,ENOENT,ENOEXEC,ENOLCK)
> (ENOLINK,ENOMEM,ENOMSG,ENOPROTOOPT,ENOSPC,ENOSYS,ENOTCONN)
> (ENOTDIR,ENOTEMPTY,ENOTRECOVERABLE,ENOTSOCK,ENOTSUP,ENOTTY)
> (ENXIO,EOPNOTSUPP,EOVERFLOW,EOWNERDEAD,EPERM,EPIPE,EPROTO)
> (EPROTONOSUPPORT,EPROTOTYPE,ERANGE,EROFS,ESPIPE,ESRCH)
> (ETIMEDOUT,ETXTBSY,EWOULDBLOCK,EXDEV): Define.
> ---
>
> I don't really like this patch, but sending it for comment.
>
> Every time we add our own <name.h> C header it complicates things, and
> we have various bug reports (and patches) related to those files causing
> problems during bootstrap of obscure canadian-cross configurations.
>
> So I'm a bit concerned that adding <errno.h> just for Freestanding would
> end up causing regressions that affect Hosted builds too.
>
We are already conditionally installing more headers for Hosted builds, so
could we conditionally install the new header only for environments that are
not hosted? This should avoid any potential impact on existing platforms.
>
>
> libstdc++-v3/include/Makefile.am | 3 +-
> libstdc++-v3/include/Makefile.in | 3 +-
> libstdc++-v3/include/c_compatibility/errno.h | 91 +++++++++++++++++++-
> 3 files changed, 94 insertions(+), 3 deletions(-)
>
> diff --git a/libstdc++-v3/include/Makefile.am
> b/libstdc++-v3/include/Makefile.am
> index 3c30aa21d6b5..18bb9f224563 100644
> --- a/libstdc++-v3/include/Makefile.am
> +++ b/libstdc++-v3/include/Makefile.am
> @@ -902,6 +902,7 @@ endif
> c_base_srcdir = $(C_INCLUDE_DIR)
> c_base_builddir = .
> c_base_freestanding = \
> + ${c_base_srcdir}/cerrno \
> ${c_base_srcdir}/cfloat \
> ${c_base_srcdir}/climits \
> ${c_base_srcdir}/cstdalign \
> @@ -919,7 +920,6 @@ c_base_headers = \
> ${c_base_srcdir}/cassert \
> ${c_base_srcdir}/ccomplex \
> ${c_base_srcdir}/cctype \
> - ${c_base_srcdir}/cerrno \
> ${c_base_srcdir}/cfenv \
> ${c_base_srcdir}/cinttypes \
> ${c_base_srcdir}/ciso646 \
> @@ -947,6 +947,7 @@ endif
> if GLIBCXX_C_HEADERS_C_GLOBAL
> c_compatibility_headers = \
> ${c_compatibility_srcdir}/complex.h \
> + ${c_compatibility_srcdir}/errno.h \
> ${c_compatibility_srcdir}/fenv.h \
> ${c_compatibility_srcdir}/tgmath.h \
> ${c_compatibility_srcdir}/math.h \
> diff --git a/libstdc++-v3/include/Makefile.in
> b/libstdc++-v3/include/Makefile.in
> index d081481293ff..feb6665ca401 100644
> --- a/libstdc++-v3/include/Makefile.in
> +++ b/libstdc++-v3/include/Makefile.in
> @@ -1250,6 +1250,7 @@ experimental_bits_headers = \
> c_base_srcdir = $(C_INCLUDE_DIR)
> c_base_builddir = .
> c_base_freestanding = \
> + ${c_base_srcdir}/cerrno \
> ${c_base_srcdir}/cfloat \
> ${c_base_srcdir}/climits \
> ${c_base_srcdir}/cstdalign \
> @@ -1265,7 +1266,6 @@ c_base_freestanding = \
> @GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/cassert \
> @GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/ccomplex \
> @GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/cctype \
> -@GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/cerrno \
> @GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/cfenv \
> @GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/cinttypes \
> @GLIBCXX_HOSTED_TRUE@ ${c_base_srcdir}/ciso646 \
> @@ -1287,6 +1287,7 @@ c_compatibility_srcdir =
> ${glibcxx_srcdir}/include/c_compatibility
> c_compatibility_builddir = .
> @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@c_compatibility_headers = \
> @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@
> ${c_compatibility_srcdir}/complex.h \
> +@GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ ${c_compatibility_srcdir}/errno.h
> \
> @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ ${c_compatibility_srcdir}/fenv.h \
> @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@
> ${c_compatibility_srcdir}/tgmath.h \
> @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ ${c_compatibility_srcdir}/math.h \
> diff --git a/libstdc++-v3/include/c_compatibility/errno.h
> b/libstdc++-v3/include/c_compatibility/errno.h
> index 07e3c17e9173..3eea20e081bb 100644
> --- a/libstdc++-v3/include/c_compatibility/errno.h
> +++ b/libstdc++-v3/include/c_compatibility/errno.h
> @@ -29,6 +29,95 @@
> #ifndef _GLIBCXX_ERRNO_H
> #define _GLIBCXX_ERRNO_H 1
>
> -#include <cerrno>
> +#include <bits/c++config.h>
> +
> +#if _GLIBCXX_HOSTED
>
Should whe use _has_include_next(<errno.h>)? So pull this header
if it is provided?
> +#include_next <errno.h>
> +// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998
> +#ifndef errno
> +#define errno errno
> +#endif
> +
> +#else
> +__thread inline int __errno_v = 0;
> +
> +#define errno __errno_v
> +
> +#define E2BIG 10007
> +#define EACCES 10013
> +#define EADDRINUSE 10098
> +#define EADDRNOTAVAIL 10099
> +#define EAFNOSUPPORT 10097
> +#define EAGAIN 10011
> +#define EALREADY 10114
> +#define EBADF 10009
> +#define EBADMSG 10074
> +#define EBUSY 10016
> +#define ECANCELED 10125
> +#define ECHILD 10010
> +#define ECONNABORTED 10103
> +#define ECONNREFUSED 10111
> +#define ECONNRESET 10104
> +#define EDEADLK 10035
> +#define EDESTADDRREQ 10089
> +#define EDOM 10033
> +#define EEXIST 10017
> +#define EFAULT 10014
> +#define EFBIG 10027
> +#define EHOSTUNREACH 10113
> +#define EIDRM 10043
> +#define EILSEQ 10084
> +#define EINPROGRESS 10115
> +#define EINTR 10004
> +#define EINVAL 10022
> +#define EIO 10005
> +#define EISCONN 10106
> +#define EISDIR 10021
> +#define ELOOP 10040
> +#define EMFILE 10024
> +#define EMLINK 10031
> +#define EMSGSIZE 10090
> +#define ENAMETOOLONG 10036
> +#define ENETDOWN 10100
> +#define ENETRESET 10102
> +#define ENETUNREACH 10101
> +#define ENFILE 10023
> +#define ENOBUFS 10105
> +#define ENODEV 10019
> +#define ENOENT 10002
> +#define ENOEXEC 10008
> +#define ENOLCK 10037
> +#define ENOLINK 10067
> +#define ENOMEM 10012
> +#define ENOMSG 10042
> +#define ENOPROTOOPT 10092
> +#define ENOSPC 10028
> +#define ENOSYS 10038
> +#define ENOTCONN 10107
> +#define ENOTDIR 10020
> +#define ENOTEMPTY 10039
> +#define ENOTRECOVERABLE 10131
> +#define ENOTSOCK 10088
> +#define ENOTSUP 10095
> +#define ENOTTY 10025
> +#define ENXIO 10006
> +#define EOPNOTSUPP 10095
> +#define EOVERFLOW 10075
> +#define EOWNERDEAD 10130
> +#define EPERM 10001
> +#define EPIPE 10032
> +#define EPROTO 10071
> +#define EPROTONOSUPPORT 10093
> +#define EPROTOTYPE 10091
> +#define ERANGE 10034
> +#define EROFS 10030
> +#define ESPIPE 10029
> +#define ESRCH 10003
> +#define ETIMEDOUT 10110
> +#define ETXTBSY 10026
> +#define EWOULDBLOCK 10011
> +#define EXDEV 10018
> +
> +#endif // HOSTED
>
> #endif
> --
> 2.55.0
>
>