On Mon, Oct 13, 2025 at 6:50 AM Bruno Haible via Gnulib discussion list <[email protected]> wrote: > > Collin Funk wrote: > > Thanks for the review. I pushed the patches with that change to the > > manual and Bruno's formatting suggestions. > > Unfortunately, the CI reports a compilation error on glibc systems > and musl libc systems. It can be reproduced with a testdir: > > $ ./gnulib-tool --create-testdir --dir=../testdir --symlink --with-c++-tests > nullptr getline > > This is the error: > > g++ -DHAVE_CONFIG_H -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 -Wno-error -Wno-error -g -O2 -MT test-nullptr-c++.o -MD -MP -MF > .deps/test-nullptr-c++.Tpo -c -o test-nullptr-c++.o > ../../gltests/test-nullptr-c++.cc > In file included from /gnu-inst-gcc/15.2.0/include/c++/15.2.0/cstdio:47, > from > /gnu-inst-gcc/15.2.0/include/c++/15.2.0/ext/string_conversions.h:47, > from > /gnu-inst-gcc/15.2.0/include/c++/15.2.0/bits/basic_string.h:4444, > from /gnu-inst-gcc/15.2.0/include/c++/15.2.0/string:56, > from > /gnu-inst-gcc/15.2.0/include/c++/15.2.0/bits/locale_classes.h:42, > from > /gnu-inst-gcc/15.2.0/include/c++/15.2.0/bits/ios_base.h:43, > from /gnu-inst-gcc/15.2.0/include/c++/15.2.0/ios:46, > from > /gnu-inst-gcc/15.2.0/include/c++/15.2.0/bits/ostream.h:43, > from /gnu-inst-gcc/15.2.0/include/c++/15.2.0/ostream:42, > from /gnu-inst-gcc/15.2.0/include/c++/15.2.0/iostream:43, > from ../../gltests/test-nullptr-c++.cc:25: > /gnu-inst-gcc/15.2.0/include/c++/15.2.0/bits/basic_string.tcc:1032:5: error: > template-id ‘rpl_getline<>’ for ‘std::basic_istream<char>& > std::rpl_getline(basic_istream<char>&, string&)’ does not match any template > declaration > 1032 | getline(basic_istream<char>&, string&); > | ^~~~~~~ > > The cause is a std::basic_istream::getline member function, that > is visible in <string> or <istream>. > > The usual workaround to #include <string> and/or #include <istream> > does not work here, because some definitions from <stdio.h> would not > be available. > > So, the fix is to define getline as an inline function rather than as a > macro. But additionally, this gets complicated by an inline function in > glibc's <bits/stdio.h>: > > __STDIO_INLINE __ssize_t > getline (char **__lineptr, size_t *__n, FILE *__stream) > { > return __getdelim (__lineptr, __n, '\n', __stream); > } > > We can't override an inline function with an inline function. The > workaround therefore gets complicated: > > > 2025-10-13 Bruno Haible <[email protected]> > > getline: Fix compilation error in C++ mode (regression 2025-10-10). > * lib/stdio.in.h (getdelim): On glibc, define __getdelim instead of > rpl_getdelim. > (getline): In C++ mode, define getline as an inline function instead > of > as a macro. > * lib/getdelim.c (getdelim): On glibc, don't test whether fp is NULL. > > diff --git a/lib/stdio.in.h b/lib/stdio.in.h > index f3ab7969d1..2c70bc049f 100644 > --- a/lib/stdio.in.h > +++ b/lib/stdio.in.h > @@ -1044,6 +1044,11 @@ _GL_CXXALIASWARN (getchar); > # undef getdelim > # define getdelim rpl_getdelim > # endif > +# if __GLIBC__ >= 2 > +/* Arrange for the inline definition of getline() in <bits/stdio.h> > + to call our getdelim() override. */ > +# define rpl_getdelim __getdelim > +# endif > _GL_FUNCDECL_RPL (getdelim, ssize_t, > (char **restrict lineptr, size_t *restrict linesize, > int delimiter, > @@ -1085,14 +1090,27 @@ _GL_WARN_ON_USE (getdelim, "getdelim is unportable - " > Return the number of bytes read and stored at *LINEPTR (not including the > NUL terminator), or -1 on error or EOF. */ > # if @REPLACE_GETLINE@ > -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) > -# undef getline > -# define getline rpl_getline > -# endif > _GL_FUNCDECL_RPL (getline, ssize_t, > (char **restrict lineptr, size_t *restrict linesize, > FILE *restrict stream), > _GL_ARG_NONNULL ((1, 2, 3)) _GL_ATTRIBUTE_NODISCARD); > +# if defined __cplusplus > +/* The C++ standard library defines std::basic_istream::getline in <istream> > + or <string>. */ > +# if !(__GLIBC__ >= 2) > +extern "C" { > +inline ssize_t > +getline (char **restrict lineptr, size_t *restrict linesize, > + FILE *restrict stream) > +{ > + return rpl_getline (lineptr, linesize, stream); > +} > +} > +# endif > +# else > +# undef getline > +# define getline rpl_getline > +# endif > _GL_CXXALIAS_RPL (getline, ssize_t, > (char **restrict lineptr, size_t *restrict linesize, > FILE *restrict stream)); > diff --git a/lib/getdelim.c b/lib/getdelim.c > index 2576d376f0..4cd5eca189 100644 > --- a/lib/getdelim.c > +++ b/lib/getdelim.c > @@ -65,7 +65,13 @@ getdelim (char **lineptr, size_t *n, int delimiter, FILE > *fp) > ssize_t result; > size_t cur_len = 0; > > - if (lineptr == NULL || n == NULL || fp == NULL) > + if (lineptr == NULL || n == NULL > + /* glibc already declares this function as __nonnull ((4)). > + Avoid a gcc warning "‘nonnull’ argument ‘fp’ compared to NULL". */ > +#if !(__GLIBC__ >= 2) > + || fp == NULL > +#endif > + ) > { > errno = EINVAL; > return -1;
Based on "> /gnu-inst-gcc/15.2.0/include/c++/15.2.0/bits/basic_string.tcc:1032:5: error: template-id ‘rpl_getline<>’ for ‘std::basic_istream<char>& std::rpl_getline(basic_istream<char>&, string&)’ does not match any template declaration". Notice the "std::rpl_getline(basic_istream<char>&, string&)". I don't think Gnulib is allowed to override symbols in the C++ std:: namespace. I think the only symbol that can be overridden is std::swap. Jeff
