Hi

This email is to report somewhat convoluted bug,
as it is related to the libc function replacements
and how they breaks under specific circumstances
(C++, GNULIB_NAMESPACE, without optimization, including sys/un.h).
By breaking I mean it will not compile due to declarations
with conflicting linkages (C vs C++).

While testing this there was a problem related to some M4 stuff,
when importing open module. I will come back to this later.

Minimal project to reproduce the bug is shown fully
at the end of this email. In essence there is configure.ac,
Makefile.am and main.cpp. There is also a script that copies
those files to new directory, imports given modules, runs autoreconf -i,
creates build directory, configures it and builds the project.

Now depending on which modules are imported, there is different outcomes.
Here is summary of the results from my testing:

full-read      |x|x| | | | | | | |x| | | | |
full-write     |x|x| | | | | | | |x| | | | |
pipe2-safer    |x|x| | | | | | | |x| | | | |
mkfifo         |x|x| | | | | | | |x| | | | |
socket         |x|x| | | | | | | |x| | | | |
connect        |x|x| | | | | | | |x| | | | |
open           |x| |x|x| | | | | |x|x| |x| |
close          |x| |x|x| | | | | |x|x| | |x|
ftruncate      |x| |x|x| | | | | |x| |x| | |
passfd         |x| |x| |x|x| | | |x| | | | |
pipe-filter-ii |x| |x| |x| |x|x| | | | | | |
pipe-filter-gi |x| |x| |x| |x| |x| | | | | |
--------------------------------------------
result         |x|?|x|?|x| |x|x|x|?|?| |?| |

x = conflicting declarations
? = m4 related error
  = ok

So the conflicting deceleration seems to boil down pipe-filter-* modules.
Here is a snipped of the error from gcc (error is given for many functions).

```
g++ -DHAVE_CONFIG_H -I. -I..  -I./lib -I../lib   -O0 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o ../main.cpp
In file included from /usr/include/sys/un.h:38,
                 from ../main.cpp:4:
./lib/string.h:829:1: error: conflicting declaration of ‘void* memchr(void*, int, size_t)’ with ‘C’ linkage
  829 | _GL_CXXALIASWARN1 (memchr, void *,
      | ^~~~~~~~~~~~~~~~~
In file included from ./lib/string.h:41:
/usr/include/string.h:87:14: note: previous declaration with ‘C++’ linkage
   87 | extern void *memchr (void *__s, int __c, size_t __n)
      |              ^~~~~~
```

It seems that in ./lib/string.h _GL_CXXALIASWARN1
uses _GL_WARN_ON_USE_CXX when NOT optimizing,
which is important for reproducing this.
However I could not really figure out why _GL_WARN_ON_USE_CXX would declare
functions with C linkage. Only lead I have is when preprocessing
main.cpp with -E, there is this one extern "C" block which seems to be closed
too late as there is many nested extern "C" blocks, but I'm not really sure:

```
# 28 "/usr/include/bits/sockaddr.h" 3 4
typedef unsigned short int sa_family_t;
# 25 "/usr/include/sys/un.h" 2 3 4

extern "C" {
...
extern "C" {
...
}
...
}
```

This is as far I can debug this, as I am not familiar with Gnulib implementation
and how it should work.

By product when I was testing this I got these m4 errors when running
autoreconf -i when open module is imported:

```
configure.ac:16: warning: gl_STDLIB_H_DEFAULTS is m4_require'd but not m4_defun'd
m4/malloc.m4:74: gl_FUNC_MALLOC_GNU is expanded from...
m4/malloca.m4:10: gl_MALLOCA is expanded from...
m4/gnulib-comp.m4:98: gl_INIT is expanded from...
configure.ac:16: the top level
configure.ac:16: warning: gl_STDLIB_H_DEFAULTS is m4_require'd but not m4_defun'd
m4/malloc.m4:143: gl_FUNC_MALLOC_POSIX is expanded from...
m4/malloc.m4:74: gl_FUNC_MALLOC_GNU is expanded from...
m4/malloca.m4:10: gl_MALLOCA is expanded from...
m4/gnulib-comp.m4:98: gl_INIT is expanded from...
configure.ac:16: the top level
configure.ac:16: warning: gl_STDLIB_H_DEFAULTS is m4_require'd but not m4_defun'd
m4/malloc.m4:91: gl_FUNC_MALLOC_PTRDIFF is expanded from...
m4/malloc.m4:143: gl_FUNC_MALLOC_POSIX is expanded from...
m4/malloc.m4:74: gl_FUNC_MALLOC_GNU is expanded from...
m4/malloca.m4:10: gl_MALLOCA is expanded from...
m4/gnulib-comp.m4:98: gl_INIT is expanded from...
configure.ac:16: the top level
configure:9639: error: possibly undefined macro: gl_STDLIB_H_DEFAULTS
      If this token and others are legitimate, please use m4_pattern_allow.
      See the Autoconf documentation.
autoreconf: error: /usr/bin/autoconf failed with exit status: 1
```

I do not really know what goes wrong as gl_STDLIB_H_DEFAULTS is never
mentioned in Gnulib manual.

I suspect that these might be due to misconfiguration or misuse of Gnulib,
so I am also open to a feedback on what I'm doing wrong.

Miro Palmu


Appendix:

Test setup:

6.12.7-arch1-1
gcc 14.2.1 20240910
Gnulib at commit: dd8057e53a

Files used:

```
.
├── proto
│   ├── configure.ac
│   ├── main.cpp
│   └── Makefile.am
└── setup_test.bash
```

./proto/configure.ac
```
AC_PREREQ([2.72])
AC_INIT([gnulib-bug], [0.0.1], [em...@miropalmu.cc])

AC_CONFIG_SRCDIR([main.cpp])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_FILES([Makefile lib/Makefile])
AC_CONFIG_MACRO_DIRS([m4])

AM_INIT_AUTOMAKE([-Wall -Werror foreign])

AC_PROG_CC
AC_PROG_CXX

gl_EARLY
gl_INIT

AC_OUTPUT
```

./proto/main.cpp
```
#define GNULIB_NAMESPACE gnulib
#include <config.h>

#include <sys/un.h>

int main() { return 42; }
```

./proto/Makefile.am
```
# Gnulib manual section 3.2 Initial import.
AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib

SUBDIRS = lib

bin_PROGRAMS = main
main_SOURCES = main.cpp
main_LDADD = $(top_builddir)/lib/libgnu.a
```

./setup_test.bash
```
#!/usr/bin/bash

# usage: ./setup_test.bash [moduleA [moduleB ...]]

name="test"
gnulibtool="/path/to/gnulib-tool"

cp -r "./proto" "$name"
pushd "$name"
"$gnulibtool" --import "$@"
autoreconf -i
mkdir build
cd build
CXXFLAGS="-O0" ../configure
make
popd
rm -r "$name"
```


Reply via email to