On a recent Linux/powerpc64le system, the test-roundl program fails to link:
gcc -Wno-error -g -O2 -L/media/guest-homedirs/haible/prefix-powerpc64le/lib -o test-roundl test-roundl.o libtests.a ../gllib/libgnu.a libtests.a ../gllib/libgnu.a libtests.a /usr/lib/gcc/powerpc64le-unknown-linux-gnu/13/../../../../powerpc64le-unknown-linux-gnu/bin/ld: test-roundl.o: in function `main': /media/guest-homedirs/haible/testdir3/build-powerpc64le/gltests/../../gltests/test-roundl.c:45:(.text.startup+0x2c): undefined reference to `__roundieee128' /usr/lib/gcc/powerpc64le-unknown-linux-gnu/13/../../../../powerpc64le-unknown-linux-gnu/bin/ld: /media/guest-homedirs/haible/testdir3/build-powerpc64le/gltests/../../gltests/test-roundl.c:73:(.text.startup+0x68): undefined reference to `__roundieee128' /usr/lib/gcc/powerpc64le-unknown-linux-gnu/13/../../../../powerpc64le-unknown-linux-gnu/bin/ld: /media/guest-homedirs/haible/testdir3/build-powerpc64le/gltests/../../gltests/test-roundl.c:74:(.text.startup+0xa0): undefined reference to `__roundieee128' /usr/lib/gcc/powerpc64le-unknown-linux-gnu/13/../../../../powerpc64le-unknown-linux-gnu/bin/ld: /media/guest-homedirs/haible/testdir3/build-powerpc64le/gltests/../../gltests/test-roundl.c:76:(.text.startup+0xd0): undefined reference to `__roundieee128' collect2: error: ld returned 1 exit status make[2]: *** [Makefile:1858: test-roundl] Error 1 The cause is that the value of the ROUNDL_LIBM variable is empty; it should be '-lm'. Why is that? Because the configure test, which essentially looks like this: ------------------------------------------------------------ #ifndef __NO_MATH_INLINES # define __NO_MATH_INLINES 1 /* for glibc */ #endif #include <math.h> extern #ifdef __cplusplus "C" #endif long double roundl (long double); double x; int main (void) { x = roundl (x); ; return 0; } ------------------------------------------------------------ can be compiled and linked without -lm. The compiler (gcc -O2) recognizes that the roundl argument x is a 'double', not a 'long double', thus it transforms the roundl() call to a round() call, which it then inlines — using the powerpc64le instruction 'frin'. The fix is to declare x as a 'long double'. Done as follows. 2024-04-05 Bruno Haible <br...@clisp.org> roundl: Fix a link error on Linux/powerpc64le. * m4/check-math-lib.m4 (gl_CHECK_MATH_LIB): Accept an additional TYPE argument. * m4/isfinite.m4 (gl_ISFINITE): Use the type 'double'. * m4/isinf.m4 (gl_ISINF): Likewise. * m4/round.m4 (gl_FUNC_ROUND): Likewise. * m4/roundf.m4 (gl_FUNC_ROUNDF): Use the type 'float'. * m4/roundl.m4 (gl_FUNC_ROUNDL): Use the type 'long double'. diff --git a/m4/check-math-lib.m4 b/m4/check-math-lib.m4 index 4f4eb5a346..1fc248dbbd 100644 --- a/m4/check-math-lib.m4 +++ b/m4/check-math-lib.m4 @@ -1,18 +1,18 @@ # check-math-lib.m4 -# serial 5 +# serial 6 dnl Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl -dnl gl_CHECK_MATH_LIB (VARIABLE, EXPRESSION [, EXTRA-CODE]) +dnl gl_CHECK_MATH_LIB (VARIABLE, TYPE, EXPRESSION [, EXTRA-CODE]) dnl dnl Sets the shell VARIABLE according to the libraries needed by EXPRESSION -dnl to compile and link: to the empty string if no extra libraries are needed, -dnl to "-lm" if -lm is needed, or to "missing" if it does not compile and -dnl link either way. +dnl (that operates on a variable x of type TYPE) to compile and link: to the +dnl empty string if no extra libraries are needed, to "-lm" if -lm is needed, +dnl or to "missing" if it does not compile and link either way. dnl -dnl Example: gl_CHECK_MATH_LIB([ROUNDF_LIBM], [x = roundf (x);]) +dnl Example: gl_CHECK_MATH_LIB([ROUNDF_LIBM], [float], [x = roundf (x);]) AC_DEFUN([gl_CHECK_MATH_LIB], [ saved_LIBS="$LIBS" $1=missing @@ -23,9 +23,9 @@ AC_DEFUN([gl_CHECK_MATH_LIB] # define __NO_MATH_INLINES 1 /* for glibc */ #endif #include <math.h> - $3 - double x;]], - [$2])], + $4 + $2 x;]], + [$3])], [$1=$libm break]) done diff --git a/m4/isfinite.m4 b/m4/isfinite.m4 index 1e30a93a9e..c14a9e51f3 100644 --- a/m4/isfinite.m4 +++ b/m4/isfinite.m4 @@ -1,5 +1,5 @@ # isfinite.m4 -# serial 19 +# serial 20 dnl Copyright (C) 2007-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -13,8 +13,8 @@ AC_DEFUN([gl_ISFINITE] AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) AC_CHECK_DECLS([isfinite], , , [[#include <math.h>]]) if test "$ac_cv_have_decl_isfinite" = yes; then - gl_CHECK_MATH_LIB([ISFINITE_LIBM], - [x = isfinite (x) + isfinite ((float) x);]) + gl_CHECK_MATH_LIB([ISFINITE_LIBM], [double], + [x = isfinite (x) + isfinite ((float) x);]) if test "$ISFINITE_LIBM" != missing; then dnl Test whether isfinite() on 'long double' works. gl_ISFINITEL_WORKS diff --git a/m4/isinf.m4 b/m4/isinf.m4 index 000a6aa008..03dc1c19a2 100644 --- a/m4/isinf.m4 +++ b/m4/isinf.m4 @@ -1,5 +1,5 @@ # isinf.m4 -# serial 14 +# serial 15 dnl Copyright (C) 2007-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -18,7 +18,8 @@ AC_DEFUN([gl_ISINF] #endif ]]) if test "$ac_cv_have_decl_isinf" = yes; then - gl_CHECK_MATH_LIB([ISINF_LIBM], [x = isinf (x) + isinf ((float) x);]) + gl_CHECK_MATH_LIB([ISINF_LIBM], [double], + [x = isinf (x) + isinf ((float) x);]) if test "$ISINF_LIBM" != missing; then dnl Test whether isinf() on 'long double' works. gl_ISINFL_WORKS diff --git a/m4/round.m4 b/m4/round.m4 index 299c79d0da..7b419a42e7 100644 --- a/m4/round.m4 +++ b/m4/round.m4 @@ -1,5 +1,5 @@ # round.m4 -# serial 27 +# serial 28 dnl Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -13,7 +13,7 @@ AC_DEFUN([gl_FUNC_ROUND] dnl Persuade glibc <math.h> to declare round(). AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) - gl_CHECK_MATH_LIB([ROUND_LIBM], [x = round (x);], + gl_CHECK_MATH_LIB([ROUND_LIBM], [double], [x = round (x);], [extern #ifdef __cplusplus "C" diff --git a/m4/roundf.m4 b/m4/roundf.m4 index 5899a6b02f..bb97813442 100644 --- a/m4/roundf.m4 +++ b/m4/roundf.m4 @@ -1,5 +1,5 @@ # roundf.m4 -# serial 28 +# serial 29 dnl Copyright (C) 2007-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -13,7 +13,7 @@ AC_DEFUN([gl_FUNC_ROUNDF] dnl Persuade glibc <math.h> to declare roundf(). AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) - gl_CHECK_MATH_LIB([ROUNDF_LIBM], [x = roundf (x);], + gl_CHECK_MATH_LIB([ROUNDF_LIBM], [float], [x = roundf (x);], [extern #ifdef __cplusplus "C" diff --git a/m4/roundl.m4 b/m4/roundl.m4 index 7f87e769a9..f845f6b078 100644 --- a/m4/roundl.m4 +++ b/m4/roundl.m4 @@ -1,5 +1,5 @@ # roundl.m4 -# serial 23 +# serial 24 dnl Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -14,7 +14,7 @@ AC_DEFUN([gl_FUNC_ROUNDL] dnl Persuade glibc <math.h> to declare roundl(). AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) - gl_CHECK_MATH_LIB([ROUNDL_LIBM], [x = roundl (x);], + gl_CHECK_MATH_LIB([ROUNDL_LIBM], [long double], [x = roundl (x);], [extern #ifdef __cplusplus "C"