[PATCH][RFC] libstdc++ Provide <cerrno> and <errno.h> for freestanding
Jonathan Wakely
jwakely.gcc@gmail.com
Tue Aug 4 16:00:57 GMT 2026
On Tue, 4 Aug 2026, 12:10 Tomasz Kaminski, <tkaminsk@redhat.com> wrote:
>
>
> On Mon, Aug 3, 2026 at 6:58 PM Jonathan Wakely <jwakely@redhat.com> 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.
>
That won't work, not consistently anyway. For freestanding, you can either
build GCC with --disable-hosted-libstdcxx or you can build a hosted
implementation but then use -ffreestanding.
If we install different headers for the non-hosted build, you would not be
able to include errno.h with -ffreestanding, or you would get the libc one
which would have different error numbers.
Maybe that's ok, and users would need to use a consistent "really
freestanding" or "hosted but used as freestanding" installation. But I
think it would be surprising.
>>
>> 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?
>
It's required for hosted implementations, and we know it's always present
because everybody can already include it today.
+#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
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260804/f3416f9d/attachment.htm>
More information about the Libstdc++
mailing list