With clang 21, I see a compilation error in the unit test for C++:
/home/bruno/inst-clang/21.1.0/bin/clang++ -I/usr/include/c++/13
-I/usr/include/x86_64-linux-gnu/c++/11 -L/usr/lib/gcc/x86_64-linux-gnu/13
-Wl,-rpath,/home/bruno/inst-clang/21.1.0/lib -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/media/develdata/devel/inst-x86_64-64/include -Wall
-Wthread-safety -Wno-error -Wno-error -g -O2 -MT test-stdcountof-h-c++.o -MD
-MP -MF $depbase.Tpo -c -o test-stdcountof-h-c++.o
../../gltests/test-stdcountof-h-c++.cc &&\
mv -f $depbase.Tpo $depbase.Po
In file included from ../../gltests/test-stdcountof-h-c++.cc:17:
../../gltests/test-stdcountof-h.c:51:11: error: use of undeclared identifier
'_Countof'
51 | ASSERT (countof (bounded) == 10);
| ^~~~~~~
/data/bruno/inst-clang/21.1.0/lib/clang/21/include/stdcountof.h:13:17: note:
expanded from macro 'countof'
13 | #define countof _Countof
| ^~~~~~~~
In file included from ../../gltests/test-stdcountof-h-c++.cc:17:
../../gltests/test-stdcountof-h.c:52:11: error: use of undeclared identifier
'_Countof'
52 | ASSERT (countof (multidimensional) == 10);
| ^~~~~~~
/data/bruno/inst-clang/21.1.0/lib/clang/21/include/stdcountof.h:13:17: note:
expanded from macro 'countof'
13 | #define countof _Countof
| ^~~~~~~~
In file included from ../../gltests/test-stdcountof-h-c++.cc:17:
../../gltests/test-stdcountof-h.c:53:11: error: use of undeclared identifier
'_Countof'
53 | ASSERT (countof (local_bounded) == 20);
| ^~~~~~~
/data/bruno/inst-clang/21.1.0/lib/clang/21/include/stdcountof.h:13:17: note:
expanded from macro 'countof'
13 | #define countof _Countof
| ^~~~~~~~
In file included from ../../gltests/test-stdcountof-h-c++.cc:17:
../../gltests/test-stdcountof-h.c:67:13: error: use of undeclared identifier
'_Countof'
67 | ASSERT (countof (((int[]) { a, b, c })) == 3);
| ^~~~~~~
/data/bruno/inst-clang/21.1.0/lib/clang/21/include/stdcountof.h:13:17: note:
expanded from macro 'countof'
13 | #define countof _Countof
| ^~~~~~~~
4 errors generated.
make[2]: *** [Makefile:27556: test-stdcountof-h-c++.o] Error 1
The cause is that this compiler has <stdcountof.h>, but it is dysfunctional
because it relies on '_Countof' that they have implemented in the C compiler
but not in the C++ compiler.
This patch works around it.
2025-09-08 Bruno Haible <[email protected]>
stdcountof-h: Add support for C++ compilers that lack _Countof.
* lib/stdcountof.in.h: Use include_next idiom. In C++ mode, test
CXX_HAVE_STDCOUNTOF_H instead of HAVE_STDCOUNTOF_H.
* m4/stdcountof_h.m4 (gl_STDCOUNTOF_H): Invoke gl_CHECK_NEXT_HEADERS.
Set CXX_HAVE_STDCOUNTOF_H. Consider CXX_HAVE_STDCOUNTOF_H when setting
GL_GENERATE_STDCOUNTOF_H.
* modules/stdcountof-h (Depends-on): Add include_next.
(Makefile.am): Substitute GUARD_PREFIX, HAVE_STDCOUNTOF_H,
CXX_HAVE_STDCOUNTOF_H, INCLUDE_NEXT, PRAGMA_SYSTEM_HEADER,
PRAGMA_COLUMNS, NEXT_STDCOUNTOF_H.
diff --git a/lib/stdcountof.in.h b/lib/stdcountof.in.h
index d5def6bf57..93c7f6bb75 100644
--- a/lib/stdcountof.in.h
+++ b/lib/stdcountof.in.h
@@ -15,8 +15,20 @@
/* Written by Bruno Haible <[email protected]>, 2025. */
-#ifndef _GL_STDCOUNTOF_H
-#define _GL_STDCOUNTOF_H
+#ifndef _@GUARD_PREFIX@_STDCOUNTOF_H
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+/* The include_next requires a split double-inclusion guard. */
+#if (defined __cplusplus ? @CXX_HAVE_STDCOUNTOF_H@ : @HAVE_STDCOUNTOF_H@)
+# @INCLUDE_NEXT@ @NEXT_STDCOUNTOF_H@
+#else
+
+#ifndef _@GUARD_PREFIX@_STDCOUNTOF_H
+#define _@GUARD_PREFIX@_STDCOUNTOF_H
/* This file uses _GL_GNUC_PREREQ. */
#if !_GL_CONFIG_H_INCLUDED
@@ -96,4 +108,6 @@ template <typename T> _gl_array_type_test<T>
_gl_array_type_test_helper(T&);
# endif
#endif
-#endif /* _GL_STDCOUNTOF_H */
+#endif /* _@GUARD_PREFIX@_STDCOUNTOF_H */
+#endif
+#endif /* _@GUARD_PREFIX@_STDCOUNTOF_H */
diff --git a/m4/stdcountof_h.m4 b/m4/stdcountof_h.m4
index 23b31c10fb..9fa27d24c8 100644
--- a/m4/stdcountof_h.m4
+++ b/m4/stdcountof_h.m4
@@ -1,5 +1,5 @@
# stdcountof_h.m4
-# serial 1
+# serial 2
dnl Copyright 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,
@@ -9,6 +9,7 @@
AC_DEFUN_ONCE([gl_STDCOUNTOF_H],
[
AC_CHECK_HEADERS_ONCE([stdcountof.h])
+ gl_CHECK_NEXT_HEADERS([stdcountof.h])
if test $ac_cv_header_stdcountof_h = yes; then
HAVE_STDCOUNTOF_H=1
else
@@ -16,7 +17,35 @@ AC_DEFUN_ONCE([gl_STDCOUNTOF_H]
fi
AC_SUBST([HAVE_STDCOUNTOF_H])
- if test $HAVE_STDCOUNTOF_H = 1; then
+ dnl In clang 21, <stdcountof.h> exists but does not work in C++ mode, because
+ dnl it uses _Countof, which is not a compiler built-in in C++ mode.
+ m4_ifdef([gl_ANSI_CXX], [AC_REQUIRE([gl_ANSI_CXX])])
+ CXX_HAVE_STDCOUNTOF_H=1
+ if test "$CXX" != no; then
+ AC_CACHE_CHECK([whether the C++ compiler has <stdcountof.h>],
+ [gl_cv_cxx_have_stdcountof_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 <stdcountof.h>
+int a[] = { 86, 47 };
+unsigned int a_n = countof (a);
+EOF
+ gl_command="$CXX $CXXFLAGS $CPPFLAGS -c conftest.cpp"
+ if AC_TRY_EVAL([gl_command]); then
+ gl_cv_cxx_have_stdcountof_h=yes
+ else
+ gl_cv_cxx_have_stdcountof_h=no
+ fi
+ rm -fr conftest*
+ ])
+ if test $gl_cv_cxx_have_stdcountof_h != yes; then
+ CXX_HAVE_STDCOUNTOF_H=0
+ fi
+ fi
+ AC_SUBST([CXX_HAVE_STDCOUNTOF_H])
+
+ if test $HAVE_STDCOUNTOF_H = 1 && test $CXX_HAVE_STDCOUNTOF_H = 1; then
GL_GENERATE_STDCOUNTOF_H=false
else
GL_GENERATE_STDCOUNTOF_H=true
diff --git a/modules/stdcountof-h b/modules/stdcountof-h
index e8fa277597..f39d963c7b 100644
--- a/modules/stdcountof-h
+++ b/modules/stdcountof-h
@@ -7,6 +7,7 @@ m4/stdcountof_h.m4
Depends-on:
gen-header
+include_next
configure.ac:
gl_STDCOUNTOF_H
@@ -21,7 +22,15 @@ BUILT_SOURCES += $(STDCOUNTOF_H)
if GL_GENERATE_STDCOUNTOF_H
stdcountof.h: stdcountof.in.h $(top_builddir)/config.status
@NMD@ $(AM_V_GEN)$(MKDIR_P) '%reldir%'
- $(gl_V_at)$(SED_HEADER_STDOUT) $(srcdir)/stdcountof.in.h > $@-t
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|${gl_include_guard_prefix}|g' \
+ -e 's/@''HAVE_STDCOUNTOF_H''@/$(HAVE_STDCOUNTOF_H)/g' \
+ -e 's/@''CXX_HAVE_STDCOUNTOF_H''@/$(CXX_HAVE_STDCOUNTOF_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' \
+ -e 's|@''NEXT_STDCOUNTOF_H''@|$(NEXT_STDCOUNTOF_H)|g' \
+ $(srcdir)/stdcountof.in.h > $@-t
$(AM_V_at)mv $@-t $@
else
stdcountof.h: $(top_builddir)/config.status