From fddec5c13299e0aa3651d53fb0faeb4789e3d396 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Fri, 30 Sep 2011 21:07:43 +0200 Subject: [PATCH] float, math: Fix 'int' to 'long double' conversion on Linux/SPARC64. * m4/float_h.m4 (gl_FLOAT_H): Test conversion from 'int' to 'long double'. Set REPLACE_ITOLD. * lib/float.in.h (_Qp_itoq, _gl_float_fix_itold): New declarations. * lib/math.in.h (_Qp_itoq, _gl_math_fix_itold): New declarations. * lib/itold.c: New file. * modules/float (Files): Add lib/itold.c. (configure.ac): When REPLACE_ITOLD is 1, arrange to compile itold.c. (Makefile.am): Substitute REPLACE_ITOLD. * modules/math (Depends-on): Add float. (Makefile.am): Substitute REPLACE_ITOLD. * doc/posix-headers/float.texi: Mention problem on Linux/SPARC64. * doc/posix-headers/math.texi: Likewise. * doc/posix-functions/logl.texi: Likewise. --- ChangeLog | 17 +++++++++++++++++ doc/posix-functions/logl.texi | 3 +++ doc/posix-headers/float.texi | 4 ++++ doc/posix-headers/math.texi | 5 +++++ lib/float.in.h | 11 +++++++++++ lib/math.in.h | 8 ++++++++ m4/float_h.m4 | 44 ++++++++++++++++++++++++++++++++++++++++++- modules/float | 5 +++++ modules/math | 2 ++ 9 files changed, 98 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f4858d513..2c13f7878 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,22 @@ 2011-09-30 Bruno Haible + float, math: Fix 'int' to 'long double' conversion on Linux/SPARC64. + * m4/float_h.m4 (gl_FLOAT_H): Test conversion from 'int' to + 'long double'. Set REPLACE_ITOLD. + * lib/float.in.h (_Qp_itoq, _gl_float_fix_itold): New declarations. + * lib/math.in.h (_Qp_itoq, _gl_math_fix_itold): New declarations. + * lib/itold.c: New file. + * modules/float (Files): Add lib/itold.c. + (configure.ac): When REPLACE_ITOLD is 1, arrange to compile itold.c. + (Makefile.am): Substitute REPLACE_ITOLD. + * modules/math (Depends-on): Add float. + (Makefile.am): Substitute REPLACE_ITOLD. + * doc/posix-headers/float.texi: Mention problem on Linux/SPARC64. + * doc/posix-headers/math.texi: Likewise. + * doc/posix-functions/logl.texi: Likewise. + +2011-09-30 Bruno Haible + nonblocking tests: Fix test failure on Linux/SPARC (32-bit and 64-bit). * tests/test-nonblocking-pipe.h (PIPE_DATA_BLOCK_SIZE) [Linux/SPARC]: Set to 140000. diff --git a/doc/posix-functions/logl.texi b/doc/posix-functions/logl.texi index bdaf6ec28..93fc86115 100644 --- a/doc/posix-functions/logl.texi +++ b/doc/posix-functions/logl.texi @@ -17,6 +17,9 @@ MSVC 9. @item This function is not declared on some platforms: MacOS X 10.3. +@item +This function returns wrong results on some platforms: +glibc 2.7 on Linux/SPARC64. @end itemize Portability problems not fixed by Gnulib: diff --git a/doc/posix-headers/float.texi b/doc/posix-headers/float.texi index f2e0e9b2d..e6a78d72e 100644 --- a/doc/posix-headers/float.texi +++ b/doc/posix-headers/float.texi @@ -8,6 +8,10 @@ Gnulib module: float Portability problems fixed by Gnulib: @itemize @item +The conversion from @code{int} to @code{long double} in incorrect on some +platforms: +glibc 2.7 on Linux/SPARC64. +@item The values of @code{LDBL_*} macros are incorrect on some platforms: On OpenBSD 4.0, MirBSD 10, and BeOS, they are the same as the values of the @code{DBL_*} macros, although @samp{long double} is a larger type than diff --git a/doc/posix-headers/math.texi b/doc/posix-headers/math.texi index d0de2bae4..12d547ce0 100644 --- a/doc/posix-headers/math.texi +++ b/doc/posix-headers/math.texi @@ -8,6 +8,11 @@ Gnulib module: math Portability problems fixed by Gnulib: @itemize @item +The conversion from @code{int} to @code{long double} in incorrect on some +platforms: +glibc 2.7 on Linux/SPARC64. + +@item The macro @code{NAN} is not defined on some platforms: OpenBSD 4.0, AIX 5.1, IRIX 6.5, OSF/1 5.1. diff --git a/lib/float.in.h b/lib/float.in.h index b132035d8..d5b22584f 100644 --- a/lib/float.in.h +++ b/lib/float.in.h @@ -173,5 +173,16 @@ extern const union gl_long_double_union gl_LDBL_MAX; # endif #endif +#if @REPLACE_ITOLD@ +/* Pull in a function that fixes the 'int' to 'long double' conversion + of glibc 2.7. */ +extern +# ifdef __cplusplus +"C" +# endif +void _Qp_itoq (long double *, int); +static void (*_gl_float_fix_itold) (long double *, int) = _Qp_itoq; +#endif + #endif /* _@GUARD_PREFIX@_FLOAT_H */ #endif /* _@GUARD_PREFIX@_FLOAT_H */ diff --git a/lib/math.in.h b/lib/math.in.h index afbc9cbd2..f82d03c2f 100644 --- a/lib/math.in.h +++ b/lib/math.in.h @@ -67,6 +67,14 @@ _GL_WARN_ON_USE (rpl_ ## func ## l, #func " is unportable - " \ : rpl_ ## func ## l (value)) +#if @REPLACE_ITOLD@ +/* Pull in a function that fixes the 'int' to 'long double' conversion + of glibc 2.7. */ +_GL_EXTERN_C void _Qp_itoq (long double *, int); +static void (*_gl_math_fix_itold) (long double *, int) = _Qp_itoq; +#endif + + /* POSIX allows platforms that don't support NAN. But all major machines in the past 15 years have supported something close to IEEE NaN, so we define this unconditionally. We also must define diff --git a/m4/float_h.m4 b/m4/float_h.m4 index da11c0e2d..0420e0692 100644 --- a/m4/float_h.m4 +++ b/m4/float_h.m4 @@ -1,4 +1,4 @@ -# float_h.m4 serial 8 +# float_h.m4 serial 9 dnl Copyright (C) 2007, 2009-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -48,9 +48,51 @@ changequote([,])dnl fi ;; esac + + dnl Test against glibc-2.7 Linux/SPARC64 bug. + REPLACE_ITOLD=0 + AC_CACHE_CHECK([whether conversion from 'int' to 'long double' works], + [gl_cv_func_itold_works], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +int i = -1; +volatile long double ld; +int main () +{ + ld += i * 1.0L; + if (ld > 0) + return 1; + return 0; +}]])], + [gl_cv_func_itold_works=yes], + [gl_cv_func_itold_works=no], + [case "$host" in + sparc*-*-linux*) + AC_EGREP_CPP([yes], + [#if defined __LP64__ || defined __arch64__ + yes + #endif], + [gl_cv_func_itold_works="guessing no"], + [gl_cv_func_itold_works="guessing yes"]) + ;; + *) gl_cv_func_itold_works="guessing yes" ;; + esac + ]) + ]) + case "$gl_cv_func_itold_works" in + *no) + REPLACE_ITOLD=1 + dnl We add the workaround to but also to , + dnl to increase the chances that the fix function gets pulled in. + FLOAT_H=float.h + ;; + esac + if test -n "$FLOAT_H"; then gl_NEXT_HEADERS([float.h]) fi AC_SUBST([FLOAT_H]) AM_CONDITIONAL([GL_GENERATE_FLOAT_H], [test -n "$FLOAT_H"]) + AC_SUBST([REPLACE_ITOLD]) ]) diff --git a/modules/float b/modules/float index 2a7975003..a24e80d05 100644 --- a/modules/float +++ b/modules/float @@ -4,6 +4,7 @@ A correct . Files: lib/float.in.h lib/float.c +lib/itold.c m4/float_h.m4 Depends-on: @@ -14,6 +15,9 @@ gl_FLOAT_H if test $REPLACE_FLOAT_LDBL = 1; then AC_LIBOBJ([float]) fi +if test $REPLACE_ITOLD = 1; then + AC_LIBOBJ([itold]) +fi Makefile.am: BUILT_SOURCES += $(FLOAT_H) @@ -29,6 +33,7 @@ float.h: float.in.h $(top_builddir)/config.status -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_FLOAT_H''@|$(NEXT_FLOAT_H)|g' \ + -e 's|@''REPLACE_ITOLD''@|$(REPLACE_ITOLD)|g' \ < $(srcdir)/float.in.h; \ } > $@-t && \ mv $@-t $@ diff --git a/modules/math b/modules/math index bc3d34c35..8062d2da5 100644 --- a/modules/math +++ b/modules/math @@ -10,6 +10,7 @@ include_next snippet/arg-nonnull snippet/c++defs snippet/warn-on-use +float configure.ac: gl_MATH_H @@ -107,6 +108,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $( -e 's|@''REPLACE_ISFINITE''@|$(REPLACE_ISFINITE)|g' \ -e 's|@''REPLACE_ISINF''@|$(REPLACE_ISINF)|g' \ -e 's|@''REPLACE_ISNAN''@|$(REPLACE_ISNAN)|g' \ + -e 's|@''REPLACE_ITOLD''@|$(REPLACE_ITOLD)|g' \ -e 's|@''REPLACE_LDEXPL''@|$(REPLACE_LDEXPL)|g' \ -e 's|@''REPLACE_NAN''@|$(REPLACE_NAN)|g' \ -e 's|@''REPLACE_ROUND''@|$(REPLACE_ROUND)|g' \ -- 2.11.0