From 423119a9f2a1549cbb9ef941fd76cf7cf5bfe1ea Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Tue, 23 Jul 2024 12:40:58 +0200 Subject: [PATCH] strtold: Revisit underflow behaviour. * doc/posix-functions/strtold.texi: Mention broken mingw 5.0. Mention that gradual underflow does not count as an error on MSVC. * tests/test-strtold.h (test_function): Add a gradual underflow test. Check the sign in case of flush-to-zero underflow. --- ChangeLog | 6 ++++ doc/posix-functions/strtold.texi | 12 ++++++++ tests/test-strtold.h | 48 +++++++++++++++++++++++++++----- 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3f086d2a9f..b4d5b8f9f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2024-07-23 Bruno Haible + strtold: Revisit underflow behaviour. + * doc/posix-functions/strtold.texi: Mention broken mingw 5.0. Mention + that gradual underflow does not count as an error on MSVC. + * tests/test-strtold.h (test_function): Add a gradual underflow test. + Check the sign in case of flush-to-zero underflow. + strtod: Revisit underflow behaviour. * doc/posix-functions/strtod.texi: Mention the macOS bug. Mention that gradual underflow does not count as an error on Cygwin 2.9 and MSVC. diff --git a/doc/posix-functions/strtold.texi b/doc/posix-functions/strtold.texi index cafcead911..3aada2c405 100644 --- a/doc/posix-functions/strtold.texi +++ b/doc/posix-functions/strtold.texi @@ -16,6 +16,10 @@ NetBSD 3.0, OpenBSD 3.8, Minix 3.1.8, Solaris 9, older Cygwin 1.7.x, MSVC 9, And This function returns a struct, not a @code{long double}, on some platforms: HP-UX 11.31/hppa. +@item +This function always returns a wrong value on some platforms: +mingw 5.0. + @item This function allows whitespace between @samp{e} and the exponent on some platforms: @@ -50,6 +54,9 @@ and the exponent on some platforms: HP-UX 11.31/ia64. @item +@c The term "underflow", as defined by ISO C23 § 7.12.1.(6), includes both +@c "gradual underflow" (result is a denormalized number) and "flush-to-zero +@c underflow" (result is zero). This function fails to set @code{errno} upon underflow on some platforms: @c https://cygwin.com/ml/cygwin/2019-12/msg00072.html Cygwin 2.9. @@ -61,6 +68,11 @@ and allocates an unbounded amount of stack on mingw 9.0. Portability problems not fixed by Gnulib: @itemize +@item +This function fails to set @code{errno} upon gradual underflow (resulting +in a denormalized number) on some platforms: +MSVC 14. + @item The replacement function does not always return correctly rounded results. @end itemize diff --git a/tests/test-strtold.h b/tests/test-strtold.h index b5d79dc07b..bd12988c4c 100644 --- a/tests/test-strtold.h +++ b/tests/test-strtold.h @@ -481,7 +481,7 @@ test_function (long double (*my_strtold) (const char *, char **)) ASSERT (errno == 0); } - /* Overflow/underflow. */ + /* Overflow. */ { const char input[] = "1E1000000"; char *ptr; @@ -502,6 +502,42 @@ test_function (long double (*my_strtold) (const char *, char **)) ASSERT (ptr == input + 10); ASSERT (errno == ERANGE); } + + /* Gradual underflow, resulting in a denormalized number. */ + { +#if LDBL_MAX_EXP > 10000 + const char input[] = "1e-4950"; +#else + const char input[] = "1e-320"; +#endif + char *ptr; + long double result; + errno = 0; + result = my_strtold (input, &ptr); + ASSERT (0.0L < result && result <= LDBL_MIN); + ASSERT (ptr == input + strlen (input)); +#if !defined _MSC_VER + ASSERT (errno == ERANGE); +#endif + } + { +#if LDBL_MAX_EXP > 10000 + const char input[] = "-1e-4950"; +#else + const char input[] = "-1e-320"; +#endif + char *ptr; + long double result; + errno = 0; + result = my_strtold (input, &ptr); + ASSERT (-LDBL_MIN <= result && result < 0.0L); + ASSERT (ptr == input + strlen (input)); +#if !defined _MSC_VER + ASSERT (errno == ERANGE); +#endif + } + + /* Flush-to-zero underflow. */ { const char input[] = "1E-100000"; char *ptr; @@ -520,16 +556,14 @@ test_function (long double (*my_strtold) (const char *, char **)) errno = 0; result = my_strtold (input, &ptr); ASSERT (-LDBL_MIN <= result && result <= 0.0L); -#if 0 - /* FIXME - this is glibc bug 5995; POSIX allows returning positive - 0 on negative underflow, even though quality of implementation - demands preserving the sign. Disable this test until fixed - glibc is more prevalent. */ + /* Negative underflow. Expect a negative sign, although POSIX allows +0.0L. + See also . */ ASSERT (!!signbit (result) == !!signbit (minus_zerol)); /* glibc-2.3.2, Haiku */ -#endif ASSERT (ptr == input + 10); ASSERT (errno == ERANGE); } + + /* Space before the exponent. */ { const char input[] = "1E 1000000"; char *ptr; -- 2.39.5