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 <[email protected]>
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>