The CI reported today a compilation error on macOS 15 with Xcode 16.4:
/Users/runner/work/ci-testdir-check/ci-testdir-check/macos-compile
clang++ -DHAVE_CONFIG_H -DEXEEXT=\"\" -DEXEEXT=\"\" -I. -I../../gltests -I..
-DGNULIB_STRICT_CHECKING=1 -DIN_GNULIB_TESTS=1 -I. -I../../gltests -I..
-I../../gltests/.. -I../gllib -I../../gltests/../gllib -I/Users/runner/include
-I/opt/homebrew/opt/gettext/include -I/opt/homebrew/opt/libiconv/include -Wall
-DCONTINUE_AFTER_ASSERT -Wno-error -g -O2 -MT test-uchar-h-c++2.o -MD -MP -MF
$depbase.Tpo -c -o test-uchar-h-c++2.o ../../gltests/test-uchar-h-c++2.cc &&\
mv -f $depbase.Tpo $depbase.Po
In file included from ../../gltests/test-uchar-h-c++2.cc:22:
/Applications/Xcode_16.4.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/cuchar:45:5:
error: <cuchar> tried including <uchar.h> but didn't find libc++'s <uchar.h>
header. This usually means that your header search paths are not
configured properly. The header search paths should contain the C++
Standard Library headers before any C Standard Library, and you are
probably using compiler flags that make that not be the case.
45 | # error <cuchar> tried including <uchar.h> but didn't find libc++'s
<uchar.h> header. \
| ^
1 error generated.
make[4]: *** [test-uchar-h-c++2.o] Error 1
The cause is that on this platform <uchar.h> exists in C++ mode but not in
C mode; however <cuchar> now requires that Gnulib's <uchar.h> override includes
the macOS C++ <uchar.h>.
This patch fixes it.
2025-09-01 Bruno Haible <[email protected]>
uchar-h: Fix compilation error of <cuchar> in C++ mode on macOS 15.
* lib/uchar.in.h: In C++ mode, use CXX_HAVE_UCHAR_H instead of
HAVE_UCHAR_H.
* m4/uchar_h.m4 (gl_UCHAR_H): Set CXX_HAVE_UCHAR_H.
* modules/uchar-h (Makefile.am): Substitute CXX_HAVE_UCHAR_H.
diff --git a/lib/uchar.in.h b/lib/uchar.in.h
index a0f43c18ab..9a65ac3774 100644
--- a/lib/uchar.in.h
+++ b/lib/uchar.in.h
@@ -28,7 +28,7 @@
@PRAGMA_COLUMNS@
/* The include_next requires a split double-inclusion guard. */
-#if @HAVE_UCHAR_H@
+#if (defined __cplusplus ? @CXX_HAVE_UCHAR_H@ : @HAVE_UCHAR_H@)
# if defined __HAIKU__
/* Work around <https://dev.haiku-os.org/ticket/17040>. */
# include <stdint.h>
@@ -83,7 +83,7 @@
_GL_INLINE_HEADER_BEGIN
-#if !(@HAVE_UCHAR_H@ || (defined __cplusplus && @CXX_HAS_CHAR8_TYPE@))
+#if !(defined __cplusplus ? @CXX_HAVE_UCHAR_H@ || @CXX_HAS_CHAR8_TYPE@ :
@HAVE_UCHAR_H@)
/* An 8-bit variant of wchar_t.
Note: This type is only mandated by ISO C 23 or newer, and it does
@@ -97,7 +97,7 @@ typedef unsigned char gl_char8_t;
#endif
-#if !(@HAVE_UCHAR_H@ || (defined __cplusplus && @CXX_HAS_UCHAR_TYPES@))
+#if !(defined __cplusplus ? @CXX_HAVE_UCHAR_H@ || @CXX_HAS_UCHAR_TYPES@ :
@HAVE_UCHAR_H@)
/* A 16-bit variant of wchar_t.
Note: This type is only mandated by ISO C 11 or newer. In ISO C 23
@@ -112,7 +112,7 @@ typedef uint_least16_t gl_char16_t;
#endif
-#if !(@HAVE_UCHAR_H@ || (defined __cplusplus && @CXX_HAS_UCHAR_TYPES@))
+#if !(defined __cplusplus ? @CXX_HAVE_UCHAR_H@ || @CXX_HAS_UCHAR_TYPES@ :
@HAVE_UCHAR_H@)
/* A 32-bit variant of wchar_t.
Note: This type is only mandated by ISO C 11 or newer. In ISO C 23
diff --git a/m4/uchar_h.m4 b/m4/uchar_h.m4
index 358a097111..b2309385eb 100644
--- a/m4/uchar_h.m4
+++ b/m4/uchar_h.m4
@@ -1,5 +1,5 @@
# uchar_h.m4
-# serial 31
+# serial 32
dnl Copyright (C) 2019-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -21,6 +21,34 @@ AC_DEFUN_ONCE([gl_UCHAR_H]
fi
AC_SUBST([HAVE_UCHAR_H])
+ dnl On macOS 15, in C mode, <uchar.h> does not exist. But in C++ mode,
+ dnl it exists, and we need to #include_next it, otherwise we get an error
+ dnl "<cuchar> tried including <uchar.h> but didn't find libc++'s <uchar.h>
+ dnl header."
+ m4_ifdef([gl_ANSI_CXX], [AC_REQUIRE([gl_ANSI_CXX])])
+ CXX_HAVE_UCHAR_H=0
+ if test "$CXX" != no; then
+ AC_CACHE_CHECK([whether the C++ compiler has <uchar.h>],
+ [gl_cv_cxx_have_uchar_h],
+ [dnl We can't use AC_LANG_PUSH([C++]) and AC_LANG_POP([C++]) here, due to
+ dnl an autoconf bug <https://savannah.gnu.org/support/?110294>.
+ cat > conftest.cpp <<\EOF
+#include <uchar.h>
+EOF
+ gl_command="$CXX $CXXFLAGS $CPPFLAGS -c conftest.cpp"
+ if AC_TRY_EVAL([gl_command]); then
+ gl_cv_cxx_have_uchar_h=yes
+ else
+ gl_cv_cxx_have_uchar_h=no
+ fi
+ rm -fr conftest*
+ ])
+ if test $gl_cv_cxx_have_uchar_h = yes; then
+ CXX_HAVE_UCHAR_H=1
+ fi
+ fi
+ AC_SUBST([CXX_HAVE_UCHAR_H])
+
gl_TYPE_CHAR8_T
gl_TYPE_CHAR16_T
gl_TYPE_CHAR32_T
@@ -60,7 +88,7 @@ AC_DEFUN_ONCE([gl_UCHAR_H]
CXX_HAS_CHAR8_TYPE=0
if test $HAVE_UCHAR_H = 0; then
if test "$CXX" != no; then
- AC_CACHE_CHECK([whether the C++ compiler predefines the char8_t types],
+ AC_CACHE_CHECK([whether the C++ compiler predefines the char8_t type],
[gl_cv_cxx_has_char8_type],
[dnl We can't use AC_LANG_PUSH([C++]) and AC_LANG_POP([C++]) here, due
to
dnl an autoconf bug <https://savannah.gnu.org/support/?110294>.
diff --git a/modules/uchar-h b/modules/uchar-h
index 70998d5d75..6360859857 100644
--- a/modules/uchar-h
+++ b/modules/uchar-h
@@ -31,6 +31,7 @@ uchar.h: uchar.in.h $(top_builddir)/config.status
$(CXXDEFS_H) $(ARG_NONNULL_H)
$(gl_V_at)$(SED_HEADER_STDOUT) \
-e 's|@''GUARD_PREFIX''@|${gl_include_guard_prefix}|g' \
-e 's/@''HAVE_UCHAR_H''@/$(HAVE_UCHAR_H)/g' \
+ -e 's/@''CXX_HAVE_UCHAR_H''@/$(CXX_HAVE_UCHAR_H)/g' \
-e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
-e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
-e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \