Paul Eggert wrote:
> > I propose to change the gradual underflow behaviour of xstrtod
> 
> Sounds good. The current behavior with MSVC does make more sense.

Done:


2024-07-24  Bruno Haible  <br...@clisp.org>

        xstrtod, xstrtold: Don't treat gradual underflow as an error.
        * lib/xstrtod.c (XSTRTOD): Upon gradual underflow, return true with
        errno = 0.
        * lib/xstrtod.h (xstrtod, xstrtold): Update specification.
        * tests/test-xstrtod.c (main): For gradual underflow, expect ok &&
        errno == 0.
        * tests/test-xstrtold.c (main): Likewise.

diff --git a/lib/xstrtod.c b/lib/xstrtod.c
index a9ca7e8d10..7565658e4d 100644
--- a/lib/xstrtod.c
+++ b/lib/xstrtod.c
@@ -57,11 +57,18 @@ XSTRTOD (char const *str, char const **ptr, DOUBLE *result,
   else
     {
       /* Flag overflow as an error.
-         Flag gradual underflow as an error.
+         Flag gradual underflow as no error.
          Flag flush-to-zero underflow as no error.
          In either case, the caller can inspect *RESULT to get more details.  
*/
       if (val != 0 && errno == ERANGE)
-        ok = false;
+        {
+          if (val >= 1 || val <= -1)
+            /* Overflow.  */
+            ok = false;
+          else
+            /* Gradual underflow.  */
+            errno = 0;
+        }
     }
 
   if (ptr != NULL)
diff --git a/lib/xstrtod.h b/lib/xstrtod.h
index 8ceca6c433..f6a1ed888a 100644
--- a/lib/xstrtod.h
+++ b/lib/xstrtod.h
@@ -42,8 +42,7 @@ extern "C" {
    NaN                                                true    NaN         0
    ±Infinity                                          true    ±HUGE_VAL   0
    overflow                                           false   ±HUGE_VAL   
ERANGE
-   gradual underflow [!MSVC]                          false   near zero   
ERANGE
-   gradual underflow [MSVC]                           true    near zero   0
+   gradual underflow                                  true    near zero   0
    flush-to-zero underflow                            true    ±0.0        
ERANGE
    other finite value                                 true    value       0
 
@@ -68,8 +67,7 @@ bool xstrtod (const char *str, const char **ptr, double 
*result,
    NaN                                                true    NaN         0
    ±Infinity                                          true    ±HUGE_VALL  0
    overflow                                           false   ±HUGE_VALL  
ERANGE
-   gradual underflow [!MSVC]                          false   near zero   
ERANGE
-   gradual underflow [MSVC]                           true    near zero   0
+   gradual underflow                                  true    near zero   0
    flush-to-zero underflow                            true    ±0.0L       
ERANGE
    other finite value                                 true    value       0
 
diff --git a/tests/test-xstrtod.c b/tests/test-xstrtod.c
index 3464120f1e..e02d97203a 100644
--- a/tests/test-xstrtod.c
+++ b/tests/test-xstrtod.c
@@ -658,36 +658,20 @@ main ()
     const char *ptr;
     double result = UNINIT;
     bool ok = xstrtod (input, &ptr, &result, strtod);
-#if defined _MSC_VER
     ASSERT (ok);
-#else
-    ASSERT (!ok);
-#endif
     ASSERT (0.0 < result && result <= DBL_MIN);
     ASSERT (ptr == input + 6);
-#if defined _MSC_VER
     ASSERT (errno == 0);
-#else
-    ASSERT (errno == ERANGE);
-#endif
   }
   {
     const char input[] = "-1e-320";
     const char *ptr;
     double result = UNINIT;
     bool ok = xstrtod (input, &ptr, &result, strtod);
-#if defined _MSC_VER
     ASSERT (ok);
-#else
-    ASSERT (!ok);
-#endif
     ASSERT (-DBL_MIN <= result && result < 0.0);
     ASSERT (ptr == input + 7);
-#if defined _MSC_VER
     ASSERT (errno == 0);
-#else
-    ASSERT (errno == ERANGE);
-#endif
   }
 
   /* Flush-to-zero underflow.  */
diff --git a/tests/test-xstrtold.c b/tests/test-xstrtold.c
index b83e78067b..a8788ca100 100644
--- a/tests/test-xstrtold.c
+++ b/tests/test-xstrtold.c
@@ -662,18 +662,10 @@ main ()
     const char *ptr;
     long double result = UNINIT;
     bool ok = xstrtold (input, &ptr, &result, strtold);
-#if defined _MSC_VER
     ASSERT (ok);
-#else
-    ASSERT (!ok);
-#endif
     ASSERT (0.0L < result && result <= LDBL_MIN);
     ASSERT (ptr == input + strlen (input));
-#if defined _MSC_VER
     ASSERT (errno == 0);
-#else
-    ASSERT (errno == ERANGE);
-#endif
   }
   {
 #if LDBL_MAX_EXP > 10000
@@ -684,18 +676,10 @@ main ()
     const char *ptr;
     long double result = UNINIT;
     bool ok = xstrtold (input, &ptr, &result, strtold);
-#if defined _MSC_VER
     ASSERT (ok);
-#else
-    ASSERT (!ok);
-#endif
     ASSERT (-LDBL_MIN <= result && result < 0.0L);
     ASSERT (ptr == input + strlen (input));
-#if defined _MSC_VER
     ASSERT (errno == 0);
-#else
-    ASSERT (errno == ERANGE);
-#endif
   }
 
   /* Flush-to-zero underflow.  */




Reply via email to