Hi Collin, > The warnings say: > > > ../gllib/string.h:809:20: error: declaration of 'memchr' has a > > different language linkage > > 809 | _GL_CXXALIASWARN1 (memchr, void *, > > | ^ > > /usr/include/string.h:94:1: note: previous definition is here > > 94 | memchr (void *__s, int __c, size_t __n) __THROW > > | ^ > > Initially looking at glibc's string.h on my system I had suspicions of > the following code in string.h: > > /* Tell the caller that we provide correct C++ prototypes. */ > #if defined __cplusplus && (__GNUC_PREREQ (4, 4) \ > || __glibc_clang_prereq (3, 5)) > # define __CORRECT_ISO_CPP_STRING_H_PROTO > #endif > [...] > #ifdef __CORRECT_ISO_CPP_STRING_H_PROTO > extern "C++" > { > extern void *memchr (void *__s, int __c, size_t __n) > __THROW __asm ("memchr") __attribute_pure__ __nonnull ((1)); > extern const void *memchr (const void *__s, int __c, size_t __n) > __THROW __asm ("memchr") __attribute_pure__ __nonnull ((1)); > [...] > > Upon looking further I see that someone else ran into errors like this > using clang++ in 2021 [1]. AFAIK it was never resolved but the archives > split replies by month I think. So maybe I am wrong.
It was never resolved, correct. Alexandre's mail from 2021 is still unresolved on my side. But when I try the testdir4 recipe from that thread today, with all versions from clang 18 down to clang 11, it all compiles fine. I therefore believe that Alexandre's problem was fixed through https://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=commitdiff;h=0b3f5d1b4c0b13bb51b4b6aa63392aa5231da3fc But it was a different situation, without <sys/un.h>. > I have attached a patch that should > fix the testdir of all modules while using clang++. The patch does not look right, no. AFAIU, __CORRECT_ISO_CPP_STRING_H_PROTO is defined for all modern versions of clang, and what your patch does is to disable the _GL_CXXALIASWARN / _GL_CXXALIASWARN1 code in this situation. What I see is that if I move the '#include <string.h>' from inside to outside the __BEGIN_DECLS / __END_DECLS block in <sys/un.h>, the errors go away. This suggests that the fix is to make sure <string.h> is included first, outside an 'extern "C++" { ... }' block. So, we need the idioms for a header file with GL_GENERATE_... and #@INCLUDE_NEXT@ ... The following header files have these idioms: lib/assert.in.h lib/endian.in.h lib/errno.in.h lib/float.in.h lib/fnmatch.in.h lib/getopt.in.h lib/glob.in.h lib/iconv.in.h lib/inttypes.in.h lib/limits.in.h lib/monetary.in.h lib/net_if.in.h lib/netinet_in.in.h lib/stdalign.in.h lib/stdarg.in.h lib/stddef.in.h lib/stdint.in.h lib/sysexits.in.h lib/sys_msg.in.h lib/sys_sem.in.h lib/sys_shm.in.h lib/sys_socket.in.h Among these, let me pick lib/netinet_in.in.h. This patch fixes the problem. 2024-07-26 Bruno Haible <br...@clisp.org> sys_un: Avoid compilation error in C++ <string.h> on glibc systems. * m4/sys_un_h.m4 (gl_SYS_UN_H): Require AC_CANONICAL_HOST. Set GL_GENERATE_SYS_UN_H to true on glibc systems. Invoke gl_CHECK_NEXT_HEADERS. Initialize HAVE_SYS_UN_H. * lib/sys_un.in.h: Use include_next and a split double-inclusion guard. In C++ mode, include <stddef.h> and <string.h> first. * modules/sys_un (Depends-on): Add include_next. (Makefile.am): Substitute INCLUDE_NEXT, PRAGMA_SYSTEM_HEADER, PRAGMA_COLUMNS, NEXT_SYS_UN_H, HAVE_SYS_UN_H. Arrange to remove 'sys' directory at "make mostlyclean". diff --git a/lib/sys_un.in.h b/lib/sys_un.in.h index 52993d65f5..c137e7cef4 100644 --- a/lib/sys_un.in.h +++ b/lib/sys_un.in.h @@ -18,17 +18,47 @@ /* Written by Collin Funk. */ #ifndef _@GUARD_PREFIX@_SYS_UN_H -#define _@GUARD_PREFIX@_SYS_UN_H 1 -/* Windows requires <winsock2.h> to be included before <afunix.h>. */ -#if @HAVE_WINSOCK2_H@ -# include <winsock2.h> +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ #endif -#if @HAVE_AFUNIX_H@ -# include <afunix.h> +@PRAGMA_COLUMNS@ + +#if @HAVE_SYS_UN_H@ + +/* On glibc, in C++ mode with clang, <stddef.h> and <string.h> need to be + included before <sys/un.h>, because otherwise <sys/un.h> includes them inside + an 'extern "C" { ... }' block, which leads to compilation errors in gnulib's + <string.h> override. */ +# if defined __cplusplus +# include <stddef.h> +# include <string.h> +# endif + +/* The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_SYS_UN_H@ + #endif +#ifndef _@GUARD_PREFIX@_SYS_UN_H +#define _@GUARD_PREFIX@_SYS_UN_H 1 + +#if !@HAVE_SYS_UN_H@ + +/* A platform that lacks <sys/un.h>. */ + +/* Windows requires <winsock2.h> to be included before <afunix.h>. */ +# if @HAVE_WINSOCK2_H@ +# include <winsock2.h> +# endif +# if @HAVE_AFUNIX_H@ +# include <afunix.h> +# endif + /* If a platform does not support AF_UNIX sockets 'struct sockaddr_un' will not be defined. You may use HAVE_UNIXSOCKET after including <config.h>. */ #endif + +#endif /* _@GUARD_PREFIX@_SYS_UN_H */ +#endif /* _@GUARD_PREFIX@_SYS_UN_H */ diff --git a/m4/sys_un_h.m4 b/m4/sys_un_h.m4 index ed19b70cb5..959cd86c0a 100644 --- a/m4/sys_un_h.m4 +++ b/m4/sys_un_h.m4 @@ -1,5 +1,5 @@ # sys_un_h.m4 -# serial 1 +# serial 2 dnl Copyright 2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -7,26 +7,43 @@ AC_DEFUN_ONCE([gl_SYS_UN_H], [ + AC_REQUIRE([AC_CANONICAL_HOST]) + dnl Check if UNIX domain sockets are supported. AC_REQUIRE([gl_SOCKET_FAMILY_UNIX]) GL_GENERATE_SYS_UN_H=false - if test $gl_cv_socket_unix = yes; then - dnl Check if using a Windows version that supports AF_UNIX. dnl See <https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/>. if test "$ac_cv_header_winsock2_h" = yes \ && test "$ac_cv_header_afunix_h" = yes; then GL_GENERATE_SYS_UN_H=true fi + case "$host_os" in + dnl On glibc systems, we need to include <string.h> before <sys/un.h>, + dnl at least in C++ mode with clang. + *-gnu* | gnu*) GL_GENERATE_SYS_UN_H=true ;; + esac fi - dnl Checked in gl_SOCKET_FAMILY_UNIX. - if test "$ac_cv_header_afunix_h" = yes; then - HAVE_AFUNIX_H=1 - else - HAVE_AFUNIX_H=0 + if $GL_GENERATE_SYS_UN_H; then + AC_CHECK_HEADERS([sys/un.h]) + gl_CHECK_NEXT_HEADERS([sys/un.h]) + + if test $ac_cv_header_sys_un_h = yes; then + HAVE_SYS_UN_H=1 + else + HAVE_SYS_UN_H=0 + fi + AC_SUBST([HAVE_SYS_UN_H]) + + dnl Checked in gl_SOCKET_FAMILY_UNIX. + if test "$ac_cv_header_afunix_h" = yes; then + HAVE_AFUNIX_H=1 + else + HAVE_AFUNIX_H=0 + fi + AC_SUBST([HAVE_AFUNIX_H]) fi - AC_SUBST([HAVE_AFUNIX_H]) ]) diff --git a/modules/sys_un b/modules/sys_un index af72a80aab..21505946a8 100644 --- a/modules/sys_un +++ b/modules/sys_un @@ -7,6 +7,7 @@ m4/sys_un_h.m4 Depends-on: gen-header +include_next sys_socket configure.ac: @@ -24,15 +25,21 @@ sys/un.h: sys_un.in.h $(top_builddir)/config.status @NMD@ $(AM_V_GEN)$(MKDIR_P) '%reldir%' $(gl_V_at)$(SED_HEADER_STDOUT) \ -e 's|@''GUARD_PREFIX''@|${gl_include_guard_prefix}|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_SYS_UN_H''@|$(NEXT_SYS_UN_H)|g' \ + -e 's|@''HAVE_SYS_UN_H''@|$(HAVE_SYS_UN_H)|g' \ -e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \ -e 's|@''HAVE_AFUNIX_H''@|$(HAVE_AFUNIX_H)|g' \ - $(srcdir)/sys_un.in.h > $@-t + $(srcdir)/sys_un.in.h > $@-t $(AM_V_at)mv $@-t $@ else sys/un.h: $(top_builddir)/config.status rm -f $@ endif MOSTLYCLEANFILES += sys/un.h sys/un.h-t +MOSTLYCLEANDIRS += sys Include: <sys/un.h>