Hi Collin,

> On AIX 7.3 (cfarm119) you can see the following warning:
> 
>     $ gnulib-tool --create-testdir --dir testdir1 thrd
>     $ cd testdir1 && ./configure && make
>     [...]
>     depbase=`echo thrd.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
>     gcc -DHAVE_CONFIG_H -I. -I..  -DGNULIB_STRICT_CHECKING=1 -D_THREAD_SAFE  
> -g -O2 -MT thrd.o -MD -MP -MF $depbase.Tpo -c -o thrd.o thrd.c &&\
>     mv -f $depbase.Tpo $depbase.Po
>     thrd.c: In function 'rpl_thrd_create':
>     thrd.c:116:51: warning: passing argument 2 of 'thrd_create' from 
> incompatible pointer type [-Wincompatible-pointer-types]
>       116 |         thrd_create ((thrd_t *) &main_arg->t.tid, thrd_main_func, 
> main_arg);
>           |                                                   ^~~~~~~~~~~~~~
>           |                                                   |
>           |                                                   void * (*)(void 
> *)
>     In file included from ./threads.h:43,
>                      from thrd.c:22:
>     /usr/include/threads.h:100:39: note: expected 'thrd_start_t' {aka 'int 
> (*)(void *)'} but argument is of type 'void * (*)(void *)'
>       100 | thrd_create(thrd_t *thr, thrd_start_t func,void *arg);
>           |                          ~~~~~~~~~~~~~^~~~
> 
> Since this becomes an error by default in newer versions of GCC than are
> on this machine (GCC 14, IIRC), I think it should be fixed.

Good point! Thanks for the report.

> How about the attached patch to fix it? Maybe you can think of a cleaner
> way to do it without the function cast.

Yep, this patch would fix the compilation error, but would still have
undefined behaviour (and the clang UBSAN actually crashes upon function
pointer type conversion).

I'm committing this patch instead. It's a little more ugly, but no undefined
behaviour. Tested on both AIX 7.1 and AIX 7.3.

Bruno


2025-07-23  Bruno Haible  <br...@clisp.org>

        thrd: Avoid conversion between different function pointer types.
        Reported by Collin Funk in
        <https://lists.gnu.org/archive/html/bug-gnulib/2025-07/msg00170.html>.
        * m4/thrd.m4 (gl_FUNC_THRD_JOIN): Define BROKEN_THRD_START_T or
        BROKEN_THRD_JOIN. Don't define BROKEN_THRD_START_T_OR_JOIN.
        * lib/thrd.c (thrd_main_func): Define with the right return type,
        depending on BROKEN_THRD_START_T.

diff --git a/lib/thrd.c b/lib/thrd.c
index ea7f0f5397..b8ddb3fd52 100644
--- a/lib/thrd.c
+++ b/lib/thrd.c
@@ -26,7 +26,7 @@
 #if HAVE_THREADS_H
 /* Provide workarounds.  */
 
-# if BROKEN_THRD_START_T_OR_JOIN
+# if BROKEN_THRD_START_T || BROKEN_THRD_JOIN
 
 #  undef thrd_t
 
@@ -70,7 +70,12 @@ typedef union
         }
         main_arg_t;
 
-static void *
+static
+#  if BROKEN_THRD_START_T
+void *
+#  else /* BROKEN_THRD_JOIN */
+int
+#  endif
 thrd_main_func (void *pmarg)
 {
   /* Unpack the object that combines mainfunc and arg.  */
@@ -91,7 +96,11 @@ thrd_main_func (void *pmarg)
         /* Clean up the thread, like thrd_join would do.  */
         free (&main_arg->t);
       }
+#  if BROKEN_THRD_START_T
     return NULL;
+#  else /* BROKEN_THRD_JOIN */
+    return 0;
+#  endif
   }
 }
 
diff --git a/m4/thrd.m4 b/m4/thrd.m4
index 18298dadb7..a79e186ed2 100644
--- a/m4/thrd.m4
+++ b/m4/thrd.m4
@@ -1,5 +1,5 @@
 # thrd.m4
-# serial 6
+# serial 7
 dnl Copyright (C) 2019-2025 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -39,8 +39,13 @@ AC_DEFUN([gl_FUNC_THRD_JOIN]
       REPLACE_THRD_EQUAL=1
       REPLACE_THRD_EXIT=1
       REPLACE_THRD_JOIN=1
-      AC_DEFINE([BROKEN_THRD_START_T_OR_JOIN], [1],
-        [Define if the thrd_start_t type is not as described in ISO C 11 or if 
thrd_join discards the thread's exit code.])
+      if test $BROKEN_THRD_START_T = 1; then
+        AC_DEFINE([BROKEN_THRD_START_T], [1],
+          [Define if the thrd_start_t type is not as described in ISO C 11.])
+      else
+        AC_DEFINE([BROKEN_THRD_JOIN], [1],
+          [Define if thrd_start_t is OK but thrd_join discards the thread's 
exit code.])
+      fi
       dnl The thrd_exit replacement relies on pthread_exit, which on AIX is in
       dnl libpthread.
       LIBSTDTHREAD="$LIBSTDTHREAD $LIBPTHREAD"




Reply via email to