Tom Tromey wrote: > Hi. gdb recently updated gnulib to > > GNULIB_COMMIT_SHA1="0cda5beb7962f6567f0c4e377df870fa05c6d681" > > This caused a build failure here at AdaCore, where we are using a > relatively recent GCC (11.2) on an rhES 7 host: > > CC libgnu_a-openat-proc.o > In file included from /usr/include/string.h:633, > from ./string.h:41, > from ../../../binutils-gdb/gnulib/import/openat-proc.c:30: > ./string.h:1105:1: error: expected identifier or '(' before '__extension__' > 1105 | _GL_FUNCDECL_SYS (strndup, char *, > | ^~~~~~~~~~~~~~~~ > > We worked around this locally by reverting gnulib commit cbdb5ea63. > > Today I looked into it a bit more and found that, after preprocessing, > the line in question looks like: > > extern char * (__extension__ (__builtin_constant_p (char const *__s) && > ((size_t)(const void *)((char const *__s) + 1) - (size_t)(const void *)(char > const *__s) == 1) ? (((const char *) (char const *__s))[0] == '\0' ? (char *) > calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (char const *__s) > + 1; size_t __n = (size_t __n); char *__retval; if (__n < __len) __len = __n > + 1; __retval = (char *) malloc (__len); if (__retval != ((void *)0)) { > __retval[__len - 1] = '\0'; __retval = (char *) memcpy (__retval, char const > *__s, __len - 1); } __retval; })) : __strndup (char const *__s, size_t __n))) > __attribute__ ((__nonnull__ (1))) > > > That is, there's an unexpected macro expansion coming from glibc: > > # 1314 "/usr/include/bits/string2.h" 3 4 > [...] > #define __strndup(s,n) (__extension__ (__builtin_constant_p (s) && > __string2_1bptr_p (s) ? (((const char *) (s))[0] == '\0' ? (char *) calloc > ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (s) + 1; size_t __n = > (n); char *__retval; if (__n < __len) __len = __n + 1; __retval = (char *) > malloc (__len); if (__retval != NULL) { __retval[__len - 1] = '\0'; __retval > = (char *) memcpy (__retval, s, __len - 1); } __retval; })) : __strndup (s, > n))) > # 1342 "/usr/include/bits/string2.h" 3 4 > #define strndup(s,n) __strndup (s, n)
Thanks for the report and the details; that explains it. It occurs only with a glibc from 2017 or older, in combination with GCC 11 or newer. > I'm not 100% sure of the best way to fix this in gnulib, as I'm not > familiar with all the ins and outs of working on it, but I can report > that the appended works. There are two possible fixes: - #undef strndup. This reverts the optimization done in the glibc headers. - Omit the redeclaration line if strndup is a macro. This is less intrusive. Since the expansion invokes calloc, malloc, or __strndup, and the first two are already associated with free or rpl_free. In the worst case, you may get a warning about a use of __strndup. But since most people who use a GCC ≥ 11 also use a recent glibc, I think this is bearable. 2022-04-30 Bruno Haible <br...@clisp.org> string: Avoid syntax error on glibc systems with GCC 11. Reported by Tom Tromey <tro...@adacore.com> in <https://lists.gnu.org/archive/html/bug-gnulib/2022-04/msg00075.html> and by Satadru Pramanik <sata...@umich.edu> in <https://lists.gnu.org/archive/html/bug-gnulib/2022-04/msg00076.html>. * lib/string.in.h (strndup): Don't rededeclare strndup if it is defined as a macro. diff --git a/lib/string.in.h b/lib/string.in.h index b6840fa912..33160b2525 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -583,7 +583,7 @@ _GL_FUNCDECL_RPL (strndup, char *, _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); _GL_CXXALIAS_RPL (strndup, char *, (char const *__s, size_t __n)); # else -# if !@HAVE_DECL_STRNDUP@ || __GNUC__ >= 11 +# if !@HAVE_DECL_STRNDUP@ || (__GNUC__ >= 11 && !defined strndup) _GL_FUNCDECL_SYS (strndup, char *, (char const *__s, size_t __n) _GL_ARG_NONNULL ((1)) @@ -593,7 +593,7 @@ _GL_CXXALIAS_SYS (strndup, char *, (char const *__s, size_t __n)); # endif _GL_CXXALIASWARN (strndup); #else -# if __GNUC__ >= 11 +# if __GNUC__ >= 11 && !defined strndup /* For -Wmismatched-dealloc: Associate strndup with free or rpl_free. */ _GL_FUNCDECL_SYS (strndup, char *, (char const *__s, size_t __n)