Hi Lasse,
Lasse Collin wrote:
> test-strndup fails on AIX (cfarm119) with ibm-clang
Yes, I reproduce this: With CC="gcc -m64" config.cache contains
gl_cv_func_strndup_works=${gl_cv_func_strndup_works=no}
whereas with CC="ibm-clang -m64" it contains
gl_cv_func_strndup_works=${gl_cv_func_strndup_works=yes}
> because
> strndup(NULL, 0) == NULL isn't true. I had configured with CC=ibm-clang
> CFLAGS=-O2. With -O0 it works.
I confirm.
> The problem is that the strndup(NULL, 0) check in strndup.m4 is
> optimized away
Yup.
> This seems to work:
>
> char *volatile ptr;
> if ((ptr = strndup (NULL, 0)) == NULL)
> result |= 2;
In our experience, marking the result variable as 'volatile' defeats some
compiler optimizations but not others. It is more reliable and future-proof
to mark the function pointer as 'volatile'. Done through this patch:
2026-07-31 Bruno Haible <[email protected]>
strndup: Fix configure test for "ibm-clang -O2".
Reported by Lasse Collin <[email protected]> in
<https://lists.gnu.org/archive/html/bug-gnulib/2026-07/msg00221.html>.
* m4/strndup.m4 (gl_FUNC_STRNDUP): Do the strndup (NULL, 0) test
through a volatile function pointer.
diff --git a/m4/strndup.m4 b/m4/strndup.m4
index dc9a6eb4a2..8de423a5e9 100644
--- a/m4/strndup.m4
+++ b/m4/strndup.m4
@@ -1,5 +1,5 @@
# strndup.m4
-# serial 24
+# serial 25
dnl Copyright (C) 2002-2003, 2005-2026 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -25,8 +25,12 @@ AC_DEFUN([gl_FUNC_STRNDUP]
dnl AIX 7.3 has a function that does not support a zero length.
AC_CACHE_CHECK([for working strndup], [gl_cv_func_strndup_works],
[AC_RUN_IFELSE([
- AC_LANG_PROGRAM([[#include <string.h>
- #include <stdlib.h>]], [[
+ AC_LANG_SOURCE([[
+#include <string.h>
+#include <stdlib.h>
+static char *dummy (const char *x, size_t y) { return NULL; }
+int main (int argc, char *argv[])
+{
#if !HAVE_DECL_STRNDUP
extern
#ifdef __cplusplus
@@ -34,6 +38,7 @@ AC_DEFUN([gl_FUNC_STRNDUP]
#endif
char *strndup (const char *, size_t);
#endif
+ char * (* volatile my_strndup) (const char *, size_t) = argc ? strndup :
dummy;
int result = 0;
{
char *s = strndup ("some longer string", 15);
@@ -43,9 +48,10 @@ AC_DEFUN([gl_FUNC_STRNDUP]
result |= 1;
free (s);
}
- if (strndup (NULL, 0) == NULL)
+ if (my_strndup (NULL, 0) == NULL)
result |= 2;
- return result;]])],
+ return result;
+}]])],
[gl_cv_func_strndup_works=yes],
[gl_cv_func_strndup_works=no],
[case $host_os in