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




Reply via email to