The tests should also verify that the $(FENV_..._LIBM) variables contain
the necessary -l options for a successful link. This patch does it.


2023-11-07  Bruno Haible  <br...@clisp.org>

        fenv-environment tests: Add a test of the link dependencies.
        * tests/test-fenv-env-6.c: Renamed from tests/test-fenv-env-5.c.
        * tests/test-fenv-env-5.c: Renamed from tests/test-fenv-env-4.c.
        * tests/test-fenv-env-4.c: Renamed from tests/test-fenv-env-3.c.
        * tests/test-fenv-env-3.c: Renamed from tests/test-fenv-env-2.c.
        * tests/test-fenv-env-2.c: Renamed from tests/test-fenv-env-1.c.
        * tests/test-fenv-env-1.c: New file.
        * tests/test-fenv-env-6.sh: Renamed from tests/test-fenv-env-5.sh. 
Update.
        * modules/fenv-environment-tests: Update. Add test-fenv-env-1 unit test.

2023-11-07  Bruno Haible  <br...@clisp.org>

        fenv-exceptions-state-c99 tests: Add a test of the link dependencies.
        * tests/test-fenv-except-state-4.c: Renamed from
        tests/test-fenv-except-state-3.c.
        * tests/test-fenv-except-state-3.c: Renamed from
        tests/test-fenv-except-state-2.c.
        * tests/test-fenv-except-state-2.c: Renamed from
        tests/test-fenv-except-state-1.c.
        * tests/test-fenv-except-state-1.c: New file.
        * modules/fenv-exceptions-state-c23-tests: Update.
        * modules/fenv-exceptions-state-c99-tests: Update. Add
        test-fenv-except-state-1 unit test.

>From 12dbfc91fb0ef24727d071d4ed4a54dc912d1122 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Tue, 7 Nov 2023 21:56:34 +0100
Subject: [PATCH 1/2] fenv-exceptions-state-c99 tests: Add a test of the link
 dependencies.

* tests/test-fenv-except-state-4.c: Renamed from
tests/test-fenv-except-state-3.c.
* tests/test-fenv-except-state-3.c: Renamed from
tests/test-fenv-except-state-2.c.
* tests/test-fenv-except-state-2.c: Renamed from
tests/test-fenv-except-state-1.c.
* tests/test-fenv-except-state-1.c: New file.
* modules/fenv-exceptions-state-c23-tests: Update.
* modules/fenv-exceptions-state-c99-tests: Update. Add
test-fenv-except-state-1 unit test.
---
 ChangeLog                               |  14 +++
 modules/fenv-exceptions-state-c23-tests |   8 +-
 modules/fenv-exceptions-state-c99-tests |  12 ++-
 tests/test-fenv-except-state-1.c        |  97 +-----------------
 tests/test-fenv-except-state-2.c        | 126 +++++++++++++++---------
 tests/test-fenv-except-state-3.c        |  75 +++++++++-----
 tests/test-fenv-except-state-4.c        |  70 +++++++++++++
 7 files changed, 228 insertions(+), 174 deletions(-)
 create mode 100644 tests/test-fenv-except-state-4.c

diff --git a/ChangeLog b/ChangeLog
index 0f665556d4..2754d32003 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2023-11-07  Bruno Haible  <br...@clisp.org>
+
+	fenv-exceptions-state-c99 tests: Add a test of the link dependencies.
+	* tests/test-fenv-except-state-4.c: Renamed from
+	tests/test-fenv-except-state-3.c.
+	* tests/test-fenv-except-state-3.c: Renamed from
+	tests/test-fenv-except-state-2.c.
+	* tests/test-fenv-except-state-2.c: Renamed from
+	tests/test-fenv-except-state-1.c.
+	* tests/test-fenv-except-state-1.c: New file.
+	* modules/fenv-exceptions-state-c23-tests: Update.
+	* modules/fenv-exceptions-state-c99-tests: Update. Add
+	test-fenv-except-state-1 unit test.
+
 2023-11-07  Bruno Haible  <br...@clisp.org>
 
 	fenv-exceptions-trapping tests: Comments.
diff --git a/modules/fenv-exceptions-state-c23-tests b/modules/fenv-exceptions-state-c23-tests
index 3d92a4714f..399908f2ce 100644
--- a/modules/fenv-exceptions-state-c23-tests
+++ b/modules/fenv-exceptions-state-c23-tests
@@ -1,5 +1,5 @@
 Files:
-tests/test-fenv-except-state-3.c
+tests/test-fenv-except-state-4.c
 tests/macros.h
 
 Depends-on:
@@ -8,6 +8,6 @@ fenv-exceptions-tracking-c99
 configure.ac:
 
 Makefile.am:
-TESTS += test-fenv-except-state-3
-check_PROGRAMS += test-fenv-except-state-3
-test_fenv_except_state_3_LDADD = $(LDADD) @FENV_EXCEPTIONS_STATE_LIBM@ $(FENV_EXCEPTIONS_TRACKING_LIBM)
+TESTS += test-fenv-except-state-4
+check_PROGRAMS += test-fenv-except-state-4
+test_fenv_except_state_4_LDADD = $(LDADD) @FENV_EXCEPTIONS_STATE_LIBM@ $(FENV_EXCEPTIONS_TRACKING_LIBM)
diff --git a/modules/fenv-exceptions-state-c99-tests b/modules/fenv-exceptions-state-c99-tests
index 7fd4e24aa1..f737aa6737 100644
--- a/modules/fenv-exceptions-state-c99-tests
+++ b/modules/fenv-exceptions-state-c99-tests
@@ -1,6 +1,7 @@
 Files:
 tests/test-fenv-except-state-1.c
 tests/test-fenv-except-state-2.c
+tests/test-fenv-except-state-3.c
 tests/macros.h
 m4/musl.m4
 
@@ -14,9 +15,12 @@ gl_MUSL_LIBC
 Makefile.am:
 TESTS += \
   test-fenv-except-state-1 \
-  test-fenv-except-state-2
+  test-fenv-except-state-2 \
+  test-fenv-except-state-3
 check_PROGRAMS += \
   test-fenv-except-state-1 \
-  test-fenv-except-state-2
-test_fenv_except_state_1_LDADD = $(LDADD) @FENV_EXCEPTIONS_STATE_LIBM@ $(FENV_EXCEPTIONS_TRACKING_LIBM)
-test_fenv_except_state_2_LDADD = $(LDADD) @FENV_EXCEPTIONS_STATE_LIBM@ $(FENV_EXCEPTIONS_TRACKING_LIBM) @FPE_TRAPPING_LIBM@
+  test-fenv-except-state-2 \
+  test-fenv-except-state-3
+test_fenv_except_state_1_LDADD = $(LDADD) @FENV_EXCEPTIONS_STATE_LIBM@
+test_fenv_except_state_2_LDADD = $(LDADD) @FENV_EXCEPTIONS_STATE_LIBM@ $(FENV_EXCEPTIONS_TRACKING_LIBM)
+test_fenv_except_state_3_LDADD = $(LDADD) @FENV_EXCEPTIONS_STATE_LIBM@ $(FENV_EXCEPTIONS_TRACKING_LIBM) @FPE_TRAPPING_LIBM@
diff --git a/tests/test-fenv-except-state-1.c b/tests/test-fenv-except-state-1.c
index 3b01418d3a..06a7b63d9e 100644
--- a/tests/test-fenv-except-state-1.c
+++ b/tests/test-fenv-except-state-1.c
@@ -21,103 +21,16 @@
 /* Specification.  */
 #include <fenv.h>
 
-#include "macros.h"
+/* Test the link dependencies: that $(FENV_EXCEPTIONS_STATE_LIBM) is
+   sufficient.  */
 
 int
 main ()
 {
-  fexcept_t saved_flags_1;
-  fexcept_t saved_flags_2;
+  fexcept_t saved_flags;
 
-  /* Test setting all exception flags.  */
-  if (feraiseexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) != 0)
-    {
-      fputs ("Skipping test: floating-point exceptions are not supported on this machine.\n", stderr);
-      return 77;
-    }
-
-  /* Fill saved_flags_1.  */
-  ASSERT (fegetexceptflag (&saved_flags_1,
-                           FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
-          == 0);
-
-  /* Clear some of the exception flags.  */
-  ASSERT (feclearexcept (FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) == 0);
-  /* Here, the set exception flags are FE_INVALID | FE_DIVBYZERO.  */
-  ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
-  ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
-  ASSERT (fetestexcept (FE_OVERFLOW) == 0);
-  ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
-  ASSERT (fetestexcept (FE_INEXACT) == 0);
-
-  /* Fill saved_flags_2.  */
-  ASSERT (fegetexceptflag (&saved_flags_2, FE_INVALID | FE_OVERFLOW) == 0);
-
-  /* Restore some of the exception flags.  */
-  ASSERT (fesetexceptflag (&saved_flags_1,
-                           FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) == 0);
-  /* Here, the set exception flags are FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW.  */
-  ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
-  ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
-  ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW);
-  ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
-  ASSERT (fetestexcept (FE_INEXACT) == 0);
-
-  /* Clear some more exception flags.  */
-  ASSERT (feclearexcept (FE_INVALID) == 0);
-  /* Here, the set exception flags are FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW.  */
-  ASSERT (fetestexcept (FE_INVALID) == 0);
-  ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
-  ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW);
-  ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
-  ASSERT (fetestexcept (FE_INEXACT) == 0);
-
-  /* Restore some more exception flags.  */
-  ASSERT (fesetexceptflag (&saved_flags_2, FE_OVERFLOW) == 0);
-  /* Here, the set exception flags are FE_DIVBYZERO | FE_UNDERFLOW.  */
-  ASSERT (fetestexcept (FE_INVALID) == 0);
-  ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
-  ASSERT (fetestexcept (FE_OVERFLOW) == 0);
-  ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
-  ASSERT (fetestexcept (FE_INEXACT) == 0);
-
-  /* Restore some more exception flags.  */
-  ASSERT (fesetexceptflag (&saved_flags_2, FE_INVALID) == 0);
-  /* Here, the set exception flags are FE_INVALID | FE_DIVBYZERO | FE_UNDERFLOW.  */
-  ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
-  ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
-  ASSERT (fetestexcept (FE_OVERFLOW) == 0);
-  ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
-  ASSERT (fetestexcept (FE_INEXACT) == 0);
-
-  /* ======================================================================== */
-  /* Check that fesetexceptflag clears exception flags in both the 387 unit
-     and the SSE unit, on i386 and x86_64 CPUs.  */
-
-  fexcept_t saved_flags_3;
-
-  ASSERT (feclearexcept (FE_INVALID) == 0);
-
-  ASSERT (fegetexceptflag (&saved_flags_3, FE_INVALID) == 0);
-
-  /* Set the FE_INVALID flag in the SSE unit.  */
-  {
-    static volatile double a, b;
-    _GL_UNUSED volatile double c;
-    a = 0.0; b = 0.0; c = a / b;
-  }
-  /* Set the FE_INVALID flag in the 387 unit.  */
-  {
-    static volatile long double al, bl;
-    _GL_UNUSED volatile long double cl;
-    al = 0.0L; bl = 0.0L; cl = al / bl;
-  }
-
-  /* Use fesetexceptflag to clear the FE_INVALID flag.  */
-  ASSERT (fesetexceptflag (&saved_flags_3, FE_INVALID) == 0);
-
-  /* Check that it's clear in both units.  */
-  ASSERT (fetestexcept (FE_INVALID) == 0);
+  fegetexceptflag (&saved_flags, FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT);
+  fesetexceptflag (&saved_flags, FE_OVERFLOW | FE_UNDERFLOW);
 
   return 0;
 }
diff --git a/tests/test-fenv-except-state-2.c b/tests/test-fenv-except-state-2.c
index bebcf5f590..3b01418d3a 100644
--- a/tests/test-fenv-except-state-2.c
+++ b/tests/test-fenv-except-state-2.c
@@ -21,25 +21,13 @@
 /* Specification.  */
 #include <fenv.h>
 
-#include <stdio.h>
-
-#include "fpe-trapping.h"
 #include "macros.h"
 
-/* musl libc does not support floating-point exception trapping, even where
-   the hardware supports it.  See
-   <https://wiki.musl-libc.org/functional-differences-from-glibc.html>  */
-#if HAVE_FPE_TRAPPING && (!MUSL_LIBC || GNULIB_FEENABLEEXCEPT)
-
-/* Check that fesetexceptflag() does not trigger a trap.  */
-
-static volatile double a, b;
-static volatile long double al, bl;
-
 int
 main ()
 {
   fexcept_t saved_flags_1;
+  fexcept_t saved_flags_2;
 
   /* Test setting all exception flags.  */
   if (feraiseexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) != 0)
@@ -53,41 +41,83 @@ main ()
                            FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
           == 0);
 
-  /* Clear exceptions from past operations.  */
-  feclearexcept (FE_ALL_EXCEPT);
-
-  /* An FE_INVALID exception shall trigger a SIGFPE signal, which by default
-     terminates the program.  */
-  if (sigfpe_on_invalid () < 0)
-    {
-      fputs ("Skipping test: trapping floating-point exceptions are not supported on this machine.\n", stderr);
-      return 77;
-    }
-
-  /* Attempt to set the FE_INVALID exception flag.  */
-  _GL_UNUSED int rc = fesetexceptflag (&saved_flags_1, FE_INVALID);
-  /* On older i386 and on PowerPC, there is no way to implement
-     fesetexceptflag() such that it does not trigger a trap.  fesetexceptflag()
-     is expected to fail in this case.  */
-# if !((defined __i386 || defined _M_IX86) || defined __powerpc__)
-  ASSERT (rc == 0);
-# endif
-
-  /* Do a harmless floating-point operation (since on some CPUs, floating-point
-     exceptions trigger a trap only at the next floating-point operation).  */
-  a = 1.0; b = a + a;
-  al = 1.0L; bl = al + al;
+  /* Clear some of the exception flags.  */
+  ASSERT (feclearexcept (FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) == 0);
+  /* Here, the set exception flags are FE_INVALID | FE_DIVBYZERO.  */
+  ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
+  ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
+  ASSERT (fetestexcept (FE_OVERFLOW) == 0);
+  ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
+  ASSERT (fetestexcept (FE_INEXACT) == 0);
+
+  /* Fill saved_flags_2.  */
+  ASSERT (fegetexceptflag (&saved_flags_2, FE_INVALID | FE_OVERFLOW) == 0);
+
+  /* Restore some of the exception flags.  */
+  ASSERT (fesetexceptflag (&saved_flags_1,
+                           FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) == 0);
+  /* Here, the set exception flags are FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW.  */
+  ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
+  ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
+  ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW);
+  ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
+  ASSERT (fetestexcept (FE_INEXACT) == 0);
+
+  /* Clear some more exception flags.  */
+  ASSERT (feclearexcept (FE_INVALID) == 0);
+  /* Here, the set exception flags are FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW.  */
+  ASSERT (fetestexcept (FE_INVALID) == 0);
+  ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
+  ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW);
+  ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
+  ASSERT (fetestexcept (FE_INEXACT) == 0);
+
+  /* Restore some more exception flags.  */
+  ASSERT (fesetexceptflag (&saved_flags_2, FE_OVERFLOW) == 0);
+  /* Here, the set exception flags are FE_DIVBYZERO | FE_UNDERFLOW.  */
+  ASSERT (fetestexcept (FE_INVALID) == 0);
+  ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
+  ASSERT (fetestexcept (FE_OVERFLOW) == 0);
+  ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
+  ASSERT (fetestexcept (FE_INEXACT) == 0);
+
+  /* Restore some more exception flags.  */
+  ASSERT (fesetexceptflag (&saved_flags_2, FE_INVALID) == 0);
+  /* Here, the set exception flags are FE_INVALID | FE_DIVBYZERO | FE_UNDERFLOW.  */
+  ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
+  ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
+  ASSERT (fetestexcept (FE_OVERFLOW) == 0);
+  ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
+  ASSERT (fetestexcept (FE_INEXACT) == 0);
+
+  /* ======================================================================== */
+  /* Check that fesetexceptflag clears exception flags in both the 387 unit
+     and the SSE unit, on i386 and x86_64 CPUs.  */
+
+  fexcept_t saved_flags_3;
+
+  ASSERT (feclearexcept (FE_INVALID) == 0);
+
+  ASSERT (fegetexceptflag (&saved_flags_3, FE_INVALID) == 0);
+
+  /* Set the FE_INVALID flag in the SSE unit.  */
+  {
+    static volatile double a, b;
+    _GL_UNUSED volatile double c;
+    a = 0.0; b = 0.0; c = a / b;
+  }
+  /* Set the FE_INVALID flag in the 387 unit.  */
+  {
+    static volatile long double al, bl;
+    _GL_UNUSED volatile long double cl;
+    al = 0.0L; bl = 0.0L; cl = al / bl;
+  }
+
+  /* Use fesetexceptflag to clear the FE_INVALID flag.  */
+  ASSERT (fesetexceptflag (&saved_flags_3, FE_INVALID) == 0);
+
+  /* Check that it's clear in both units.  */
+  ASSERT (fetestexcept (FE_INVALID) == 0);
 
   return 0;
 }
-
-#else
-
-int
-main ()
-{
-  fputs ("Skipping test: feenableexcept not available\n", stderr);
-  return 77;
-}
-
-#endif
diff --git a/tests/test-fenv-except-state-3.c b/tests/test-fenv-except-state-3.c
index b1f72e6b9c..bebcf5f590 100644
--- a/tests/test-fenv-except-state-3.c
+++ b/tests/test-fenv-except-state-3.c
@@ -21,13 +21,25 @@
 /* Specification.  */
 #include <fenv.h>
 
+#include <stdio.h>
+
+#include "fpe-trapping.h"
 #include "macros.h"
 
+/* musl libc does not support floating-point exception trapping, even where
+   the hardware supports it.  See
+   <https://wiki.musl-libc.org/functional-differences-from-glibc.html>  */
+#if HAVE_FPE_TRAPPING && (!MUSL_LIBC || GNULIB_FEENABLEEXCEPT)
+
+/* Check that fesetexceptflag() does not trigger a trap.  */
+
+static volatile double a, b;
+static volatile long double al, bl;
+
 int
 main ()
 {
   fexcept_t saved_flags_1;
-  fexcept_t saved_flags_2;
 
   /* Test setting all exception flags.  */
   if (feraiseexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) != 0)
@@ -40,31 +52,42 @@ main ()
   ASSERT (fegetexceptflag (&saved_flags_1,
                            FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
           == 0);
-  /* Check its contents.  */
-  ASSERT (fetestexceptflag (&saved_flags_1,
-                            FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
-          == (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT));
-  ASSERT (fetestexceptflag (&saved_flags_1, FE_INVALID) == FE_INVALID);
-  ASSERT (fetestexceptflag (&saved_flags_1, FE_DIVBYZERO) == FE_DIVBYZERO);
-  ASSERT (fetestexceptflag (&saved_flags_1, FE_OVERFLOW) == FE_OVERFLOW);
-  ASSERT (fetestexceptflag (&saved_flags_1, FE_UNDERFLOW) == FE_UNDERFLOW);
-  ASSERT (fetestexceptflag (&saved_flags_1, FE_INEXACT) == FE_INEXACT);
-
-  /* Clear some of the exception flags.  */
-  ASSERT (feclearexcept (FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) == 0);
-  /* Here, the set exception flags are FE_INVALID | FE_DIVBYZERO.  */
-  ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
-  ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
-  ASSERT (fetestexcept (FE_OVERFLOW) == 0);
-  ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
-  ASSERT (fetestexcept (FE_INEXACT) == 0);
-
-  /* Fill saved_flags_2.  */
-  ASSERT (fegetexceptflag (&saved_flags_2, FE_INVALID | FE_OVERFLOW) == 0);
-  /* Check its contents.  */
-  ASSERT (fetestexceptflag (&saved_flags_2, FE_INVALID | FE_OVERFLOW) == FE_INVALID);
-  ASSERT (fetestexceptflag (&saved_flags_2, FE_INVALID) == FE_INVALID);
-  ASSERT (fetestexceptflag (&saved_flags_2, FE_OVERFLOW) == 0);
+
+  /* Clear exceptions from past operations.  */
+  feclearexcept (FE_ALL_EXCEPT);
+
+  /* An FE_INVALID exception shall trigger a SIGFPE signal, which by default
+     terminates the program.  */
+  if (sigfpe_on_invalid () < 0)
+    {
+      fputs ("Skipping test: trapping floating-point exceptions are not supported on this machine.\n", stderr);
+      return 77;
+    }
+
+  /* Attempt to set the FE_INVALID exception flag.  */
+  _GL_UNUSED int rc = fesetexceptflag (&saved_flags_1, FE_INVALID);
+  /* On older i386 and on PowerPC, there is no way to implement
+     fesetexceptflag() such that it does not trigger a trap.  fesetexceptflag()
+     is expected to fail in this case.  */
+# if !((defined __i386 || defined _M_IX86) || defined __powerpc__)
+  ASSERT (rc == 0);
+# endif
+
+  /* Do a harmless floating-point operation (since on some CPUs, floating-point
+     exceptions trigger a trap only at the next floating-point operation).  */
+  a = 1.0; b = a + a;
+  al = 1.0L; bl = al + al;
 
   return 0;
 }
+
+#else
+
+int
+main ()
+{
+  fputs ("Skipping test: feenableexcept not available\n", stderr);
+  return 77;
+}
+
+#endif
diff --git a/tests/test-fenv-except-state-4.c b/tests/test-fenv-except-state-4.c
new file mode 100644
index 0000000000..b1f72e6b9c
--- /dev/null
+++ b/tests/test-fenv-except-state-4.c
@@ -0,0 +1,70 @@
+/* Test of saving the floating-point exception status flags.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <br...@clisp.org>, 2023.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <fenv.h>
+
+#include "macros.h"
+
+int
+main ()
+{
+  fexcept_t saved_flags_1;
+  fexcept_t saved_flags_2;
+
+  /* Test setting all exception flags.  */
+  if (feraiseexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) != 0)
+    {
+      fputs ("Skipping test: floating-point exceptions are not supported on this machine.\n", stderr);
+      return 77;
+    }
+
+  /* Fill saved_flags_1.  */
+  ASSERT (fegetexceptflag (&saved_flags_1,
+                           FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
+          == 0);
+  /* Check its contents.  */
+  ASSERT (fetestexceptflag (&saved_flags_1,
+                            FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
+          == (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT));
+  ASSERT (fetestexceptflag (&saved_flags_1, FE_INVALID) == FE_INVALID);
+  ASSERT (fetestexceptflag (&saved_flags_1, FE_DIVBYZERO) == FE_DIVBYZERO);
+  ASSERT (fetestexceptflag (&saved_flags_1, FE_OVERFLOW) == FE_OVERFLOW);
+  ASSERT (fetestexceptflag (&saved_flags_1, FE_UNDERFLOW) == FE_UNDERFLOW);
+  ASSERT (fetestexceptflag (&saved_flags_1, FE_INEXACT) == FE_INEXACT);
+
+  /* Clear some of the exception flags.  */
+  ASSERT (feclearexcept (FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) == 0);
+  /* Here, the set exception flags are FE_INVALID | FE_DIVBYZERO.  */
+  ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
+  ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
+  ASSERT (fetestexcept (FE_OVERFLOW) == 0);
+  ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
+  ASSERT (fetestexcept (FE_INEXACT) == 0);
+
+  /* Fill saved_flags_2.  */
+  ASSERT (fegetexceptflag (&saved_flags_2, FE_INVALID | FE_OVERFLOW) == 0);
+  /* Check its contents.  */
+  ASSERT (fetestexceptflag (&saved_flags_2, FE_INVALID | FE_OVERFLOW) == FE_INVALID);
+  ASSERT (fetestexceptflag (&saved_flags_2, FE_INVALID) == FE_INVALID);
+  ASSERT (fetestexceptflag (&saved_flags_2, FE_OVERFLOW) == 0);
+
+  return 0;
+}
-- 
2.34.1

>From 740191015f849891fb582728cd5163562b65cf12 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Tue, 7 Nov 2023 22:08:02 +0100
Subject: [PATCH 2/2] fenv-environment tests: Add a test of the link
 dependencies.

* tests/test-fenv-env-6.c: Renamed from tests/test-fenv-env-5.c.
* tests/test-fenv-env-5.c: Renamed from tests/test-fenv-env-4.c.
* tests/test-fenv-env-4.c: Renamed from tests/test-fenv-env-3.c.
* tests/test-fenv-env-3.c: Renamed from tests/test-fenv-env-2.c.
* tests/test-fenv-env-2.c: Renamed from tests/test-fenv-env-1.c.
* tests/test-fenv-env-1.c: New file.
* tests/test-fenv-env-6.sh: Renamed from tests/test-fenv-env-5.sh. Update.
* modules/fenv-environment-tests: Update. Add test-fenv-env-1 unit test.
---
 ChangeLog                                     |  12 ++
 modules/fenv-environment-tests                |  14 +-
 tests/test-fenv-env-1.c                       | 103 +------------
 tests/test-fenv-env-2.c                       |  40 ++----
 tests/test-fenv-env-3.c                       |  80 ++++++-----
 tests/test-fenv-env-4.c                       |  32 ++---
 tests/test-fenv-env-5.c                       | 136 +++++++++++++-----
 tests/test-fenv-env-6.c                       |  75 ++++++++++
 ...{test-fenv-env-5.sh => test-fenv-env-6.sh} |   4 +-
 9 files changed, 274 insertions(+), 222 deletions(-)
 create mode 100644 tests/test-fenv-env-6.c
 rename tests/{test-fenv-env-5.sh => test-fenv-env-6.sh} (68%)

diff --git a/ChangeLog b/ChangeLog
index 2754d32003..46c4229ca6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2023-11-07  Bruno Haible  <br...@clisp.org>
+
+	fenv-environment tests: Add a test of the link dependencies.
+	* tests/test-fenv-env-6.c: Renamed from tests/test-fenv-env-5.c.
+	* tests/test-fenv-env-5.c: Renamed from tests/test-fenv-env-4.c.
+	* tests/test-fenv-env-4.c: Renamed from tests/test-fenv-env-3.c.
+	* tests/test-fenv-env-3.c: Renamed from tests/test-fenv-env-2.c.
+	* tests/test-fenv-env-2.c: Renamed from tests/test-fenv-env-1.c.
+	* tests/test-fenv-env-1.c: New file.
+	* tests/test-fenv-env-6.sh: Renamed from tests/test-fenv-env-5.sh. Update.
+	* modules/fenv-environment-tests: Update. Add test-fenv-env-1 unit test.
+
 2023-11-07  Bruno Haible  <br...@clisp.org>
 
 	fenv-exceptions-state-c99 tests: Add a test of the link dependencies.
diff --git a/modules/fenv-environment-tests b/modules/fenv-environment-tests
index ecb7b327f3..845979b5a3 100644
--- a/modules/fenv-environment-tests
+++ b/modules/fenv-environment-tests
@@ -3,8 +3,9 @@ tests/test-fenv-env-1.c
 tests/test-fenv-env-2.c
 tests/test-fenv-env-3.c
 tests/test-fenv-env-4.c
-tests/test-fenv-env-5.sh
 tests/test-fenv-env-5.c
+tests/test-fenv-env-6.sh
+tests/test-fenv-env-6.c
 tests/macros.h
 m4/musl.m4
 
@@ -23,15 +24,18 @@ TESTS += \
   test-fenv-env-2 \
   test-fenv-env-3 \
   test-fenv-env-4 \
-  test-fenv-env-5.sh
+  test-fenv-env-5 \
+  test-fenv-env-6.sh
 check_PROGRAMS += \
   test-fenv-env-1 \
   test-fenv-env-2 \
   test-fenv-env-3 \
   test-fenv-env-4 \
-  test-fenv-env-5
-test_fenv_env_1_LDADD = $(LDADD) @FENV_ENVIRONMENT_LIBM@ $(FENV_EXCEPTIONS_TRACKING_LIBM) $(FENV_ROUNDING_LIBM) $(FPE_TRAPPING_LIBM)
+  test-fenv-env-5 \
+  test-fenv-env-6
+test_fenv_env_1_LDADD = $(LDADD) @FENV_ENVIRONMENT_LIBM@
 test_fenv_env_2_LDADD = $(LDADD) @FENV_ENVIRONMENT_LIBM@ $(FENV_EXCEPTIONS_TRACKING_LIBM) $(FENV_ROUNDING_LIBM) $(FPE_TRAPPING_LIBM)
 test_fenv_env_3_LDADD = $(LDADD) @FENV_ENVIRONMENT_LIBM@ $(FENV_EXCEPTIONS_TRACKING_LIBM) $(FENV_ROUNDING_LIBM) $(FPE_TRAPPING_LIBM)
 test_fenv_env_4_LDADD = $(LDADD) @FENV_ENVIRONMENT_LIBM@ $(FENV_EXCEPTIONS_TRACKING_LIBM) $(FENV_ROUNDING_LIBM) $(FPE_TRAPPING_LIBM)
-test_fenv_env_5_LDADD = $(LDADD) @FENV_ENVIRONMENT_LIBM@ $(FENV_EXCEPTIONS_TRACKING_LIBM) $(FPE_TRAPPING_LIBM)
+test_fenv_env_5_LDADD = $(LDADD) @FENV_ENVIRONMENT_LIBM@ $(FENV_EXCEPTIONS_TRACKING_LIBM) $(FENV_ROUNDING_LIBM) $(FPE_TRAPPING_LIBM)
+test_fenv_env_6_LDADD = $(LDADD) @FENV_ENVIRONMENT_LIBM@ $(FENV_EXCEPTIONS_TRACKING_LIBM) $(FPE_TRAPPING_LIBM)
diff --git a/tests/test-fenv-env-1.c b/tests/test-fenv-env-1.c
index 95c37ad6ac..6c6c702219 100644
--- a/tests/test-fenv-env-1.c
+++ b/tests/test-fenv-env-1.c
@@ -21,109 +21,16 @@
 /* Specification.  */
 #include <fenv.h>
 
-#include "macros.h"
-
-/* Test the combination of fegetenv() with fesetenv().  */
+/* Test the link dependencies: that $(FENV_ENVIRONMENT_LIBM) is sufficient.  */
 
 int
 main ()
 {
-#if defined __GLIBC__ && defined __arm__ && defined __SOFTFP__
-  fputs ("Skipping test: no floating-point environment exists on this machine\n", stderr);
-  return 77;
-#else
-  fenv_t env1, env2;
-
-  /* Get to a known initial state.  */
-  ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
-
-  /* Save the current environment in env1.  */
-  ASSERT (fegetenv (&env1) == 0);
-
-  /* Modify the current environment.  */
-  fesetround (FE_UPWARD);
-  int supports_tracking = (feraiseexcept (FE_INVALID | FE_OVERFLOW | FE_INEXACT) == 0);
-  int supports_trapping = (feenableexcept (FE_DIVBYZERO) != -1);
-
-  /* Save the current environment in env2.  */
-  ASSERT (fegetenv (&env2) == 0);
-
-  /* Check that the exception flags are unmodified.  */
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_INEXACT : 0));
-  /* Check that the exception trap bits are unmodified.  */
-  ASSERT (fegetexcept () == (supports_trapping ? FE_DIVBYZERO : 0));
-
-  /* Go back to env1.  */
-  ASSERT (fesetenv (&env1) == 0);
-
-  /* Check that the rounding direction has been restored.  */
-  ASSERT (fegetround () == FE_TONEAREST);
-  /* Check that the exception flags have been restored.  */
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
-  /* Check that the exception trap bits have been restored.  */
-  ASSERT (fegetexcept () == 0);
-
-  /* Modify the rounding direction, the exception flags, and the exception
-     trap bits again.  */
-  fesetround (FE_DOWNWARD);
-  ASSERT (fegetround () == FE_DOWNWARD);
-  feclearexcept (FE_OVERFLOW);
-  feraiseexcept (FE_UNDERFLOW | FE_INEXACT);
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_UNDERFLOW | FE_INEXACT : 0));
-  feenableexcept (FE_INVALID);
-  ASSERT (fegetexcept () == (supports_trapping ? FE_INVALID : 0));
-
-  /* Go back to env2.  */
-  ASSERT (fesetenv (&env2) == 0);
-
-  /* Check that the rounding direction has been restored.  */
-  ASSERT (fegetround () == FE_UPWARD);
-  /* Check that the exception flags have been restored.  */
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_INEXACT : 0));
-  /* Check that the exception trap bits have been restored.  */
-  ASSERT (fegetexcept () == (supports_trapping ? FE_DIVBYZERO : 0));
-
-  /* ======================================================================== */
-  /* FE_DFL_ENV */
-
-  /* Enable trapping on FE_INVALID.  */
-  feclearexcept (FE_INVALID);
-  feenableexcept (FE_INVALID);
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_INEXACT : 0));
-
-  /* Go back to the default environment.  */
-  ASSERT (fesetenv (FE_DFL_ENV) == 0);
-
-  /* Check its contents.  */
-  ASSERT (fegetround () == FE_TONEAREST);
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
-
-  /* Check that it has trapping on FE_INVALID disabled.  */
-  ASSERT (fegetexcept () == 0);
-  {
-    double volatile a;
-    _GL_UNUSED double volatile b;
-    a = 0; b = a / a;
-  }
-
-  /* ======================================================================== */
-  /* Check that fesetenv restores the trapping behaviour.  */
-
-  /* Enable trapping on FE_INVALID.  */
-  feclearexcept (FE_INVALID);
-  feenableexcept (FE_INVALID);
-
-  /* Go back to env1.  */
-  ASSERT (fesetenv (&env1) == 0);
+  fenv_t env;
 
-  /* Check that it has disabled trapping on FE_INVALID.  */
-  ASSERT (fegetexcept () == 0);
-  {
-    double volatile a;
-    _GL_UNUSED double volatile b;
-    a = 0; b = a / a;
-  }
+  fegetenv (&env);
+  fesetenv (FE_DFL_ENV);
+  fesetenv (&env);
 
   return 0;
-#endif
 }
diff --git a/tests/test-fenv-env-2.c b/tests/test-fenv-env-2.c
index fa9dec78af..95c37ad6ac 100644
--- a/tests/test-fenv-env-2.c
+++ b/tests/test-fenv-env-2.c
@@ -23,7 +23,7 @@
 
 #include "macros.h"
 
-/* Test the combination of fegetenv() with feupdateenv().  */
+/* Test the combination of fegetenv() with fesetenv().  */
 
 int
 main ()
@@ -54,14 +54,12 @@ main ()
   ASSERT (fegetexcept () == (supports_trapping ? FE_DIVBYZERO : 0));
 
   /* Go back to env1.  */
-  ASSERT (feupdateenv (&env1) == 0);
+  ASSERT (fesetenv (&env1) == 0);
 
   /* Check that the rounding direction has been restored.  */
   ASSERT (fegetround () == FE_TONEAREST);
-  /* Check that the exception flags are the union of the saved and of the
-     current exception flags.  (The saved exception flags happen to be none
-     in this case.)  */
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_INEXACT : 0));
+  /* Check that the exception flags have been restored.  */
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
   /* Check that the exception trap bits have been restored.  */
   ASSERT (fegetexcept () == 0);
 
@@ -69,46 +67,36 @@ main ()
      trap bits again.  */
   fesetround (FE_DOWNWARD);
   ASSERT (fegetround () == FE_DOWNWARD);
-  feclearexcept (FE_INVALID | FE_OVERFLOW);
+  feclearexcept (FE_OVERFLOW);
   feraiseexcept (FE_UNDERFLOW | FE_INEXACT);
   ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_UNDERFLOW | FE_INEXACT : 0));
   feenableexcept (FE_INVALID);
   ASSERT (fegetexcept () == (supports_trapping ? FE_INVALID : 0));
 
   /* Go back to env2.  */
-  ASSERT (feupdateenv (&env2) == 0);
+  ASSERT (fesetenv (&env2) == 0);
 
   /* Check that the rounding direction has been restored.  */
   ASSERT (fegetround () == FE_UPWARD);
-  /* Check that the exception flags are the union of the saved and of the
-     current exception flags.  */
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
+  /* Check that the exception flags have been restored.  */
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_INEXACT : 0));
   /* Check that the exception trap bits have been restored.  */
   ASSERT (fegetexcept () == (supports_trapping ? FE_DIVBYZERO : 0));
 
   /* ======================================================================== */
   /* FE_DFL_ENV */
 
-  /* Go back to the default environment.  */
-  ASSERT (feupdateenv (FE_DFL_ENV) == 0);
-
-  /* Check that the rounding direction has been restored,
-     whereas the exception flags are unmodified.  */
-  ASSERT (fegetround () == FE_TONEAREST);
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
-
   /* Enable trapping on FE_INVALID.  */
   feclearexcept (FE_INVALID);
   feenableexcept (FE_INVALID);
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_INEXACT : 0));
 
   /* Go back to the default environment.  */
-  ASSERT (feupdateenv (FE_DFL_ENV) == 0);
+  ASSERT (fesetenv (FE_DFL_ENV) == 0);
 
-  /* Check that the rounding direction has been restored,
-     whereas the exception flags are unmodified.  */
+  /* Check its contents.  */
   ASSERT (fegetround () == FE_TONEAREST);
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
 
   /* Check that it has trapping on FE_INVALID disabled.  */
   ASSERT (fegetexcept () == 0);
@@ -119,14 +107,14 @@ main ()
   }
 
   /* ======================================================================== */
-  /* Check that feupdateenv restores the trapping behaviour.  */
+  /* Check that fesetenv restores the trapping behaviour.  */
 
   /* Enable trapping on FE_INVALID.  */
   feclearexcept (FE_INVALID);
   feenableexcept (FE_INVALID);
 
   /* Go back to env1.  */
-  ASSERT (feupdateenv (&env1) == 0);
+  ASSERT (fesetenv (&env1) == 0);
 
   /* Check that it has disabled trapping on FE_INVALID.  */
   ASSERT (fegetexcept () == 0);
diff --git a/tests/test-fenv-env-3.c b/tests/test-fenv-env-3.c
index 5cd094a616..fa9dec78af 100644
--- a/tests/test-fenv-env-3.c
+++ b/tests/test-fenv-env-3.c
@@ -23,7 +23,7 @@
 
 #include "macros.h"
 
-/* Test the combination of feholdexcept() with fesetenv().  */
+/* Test the combination of fegetenv() with feupdateenv().  */
 
 int
 main ()
@@ -38,7 +38,7 @@ main ()
   ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
 
   /* Save the current environment in env1.  */
-  ASSERT (feholdexcept (&env1) == 0);
+  ASSERT (fegetenv (&env1) == 0);
 
   /* Modify the current environment.  */
   fesetround (FE_UPWARD);
@@ -46,20 +46,22 @@ main ()
   int supports_trapping = (feenableexcept (FE_DIVBYZERO) != -1);
 
   /* Save the current environment in env2.  */
-  ASSERT (feholdexcept (&env2) == 0);
+  ASSERT (fegetenv (&env2) == 0);
 
-  /* Check that the exception flags are cleared.  */
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
-  /* Check that the exception trap bits are cleared.  */
-  ASSERT (fegetexcept () == 0);
+  /* Check that the exception flags are unmodified.  */
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_INEXACT : 0));
+  /* Check that the exception trap bits are unmodified.  */
+  ASSERT (fegetexcept () == (supports_trapping ? FE_DIVBYZERO : 0));
 
   /* Go back to env1.  */
-  ASSERT (fesetenv (&env1) == 0);
+  ASSERT (feupdateenv (&env1) == 0);
 
   /* Check that the rounding direction has been restored.  */
   ASSERT (fegetround () == FE_TONEAREST);
-  /* Check that the exception flags have been restored.  */
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
+  /* Check that the exception flags are the union of the saved and of the
+     current exception flags.  (The saved exception flags happen to be none
+     in this case.)  */
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_INEXACT : 0));
   /* Check that the exception trap bits have been restored.  */
   ASSERT (fegetexcept () == 0);
 
@@ -67,36 +69,46 @@ main ()
      trap bits again.  */
   fesetround (FE_DOWNWARD);
   ASSERT (fegetround () == FE_DOWNWARD);
-  feclearexcept (FE_OVERFLOW);
+  feclearexcept (FE_INVALID | FE_OVERFLOW);
   feraiseexcept (FE_UNDERFLOW | FE_INEXACT);
   ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_UNDERFLOW | FE_INEXACT : 0));
   feenableexcept (FE_INVALID);
   ASSERT (fegetexcept () == (supports_trapping ? FE_INVALID : 0));
 
   /* Go back to env2.  */
-  ASSERT (fesetenv (&env2) == 0);
+  ASSERT (feupdateenv (&env2) == 0);
 
   /* Check that the rounding direction has been restored.  */
   ASSERT (fegetround () == FE_UPWARD);
-  /* Check that the exception flags have been restored.  */
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_INEXACT : 0));
+  /* Check that the exception flags are the union of the saved and of the
+     current exception flags.  */
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
   /* Check that the exception trap bits have been restored.  */
   ASSERT (fegetexcept () == (supports_trapping ? FE_DIVBYZERO : 0));
 
   /* ======================================================================== */
   /* FE_DFL_ENV */
 
+  /* Go back to the default environment.  */
+  ASSERT (feupdateenv (FE_DFL_ENV) == 0);
+
+  /* Check that the rounding direction has been restored,
+     whereas the exception flags are unmodified.  */
+  ASSERT (fegetround () == FE_TONEAREST);
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
+
   /* Enable trapping on FE_INVALID.  */
   feclearexcept (FE_INVALID);
   feenableexcept (FE_INVALID);
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_INEXACT : 0));
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
 
   /* Go back to the default environment.  */
-  ASSERT (fesetenv (FE_DFL_ENV) == 0);
+  ASSERT (feupdateenv (FE_DFL_ENV) == 0);
 
-  /* Check its contents.  */
+  /* Check that the rounding direction has been restored,
+     whereas the exception flags are unmodified.  */
   ASSERT (fegetround () == FE_TONEAREST);
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
 
   /* Check that it has trapping on FE_INVALID disabled.  */
   ASSERT (fegetexcept () == 0);
@@ -107,28 +119,22 @@ main ()
   }
 
   /* ======================================================================== */
-  /* Check that feholdexcept, unlike fegetenv, disables trapping.  */
+  /* Check that feupdateenv restores the trapping behaviour.  */
 
-  /* musl libc does not support floating-point exception trapping, even where
-     the hardware supports it.  See
-     <https://wiki.musl-libc.org/functional-differences-from-glibc.html>  */
-# if !MUSL_LIBC || GNULIB_FEENABLEEXCEPT
   /* Enable trapping on FE_INVALID.  */
   feclearexcept (FE_INVALID);
-  if (feenableexcept (FE_INVALID) != -1)
-    {
-      /* Call feholdexcept.  */
-      ASSERT (feholdexcept (&env1) == 0);
-
-      /* Check that it has disabled trapping on FE_INVALID.  */
-      ASSERT (fegetexcept () == 0);
-      {
-        double volatile a;
-        _GL_UNUSED double volatile b;
-        a = 0; b = a / a;
-      }
-    }
-# endif
+  feenableexcept (FE_INVALID);
+
+  /* Go back to env1.  */
+  ASSERT (feupdateenv (&env1) == 0);
+
+  /* Check that it has disabled trapping on FE_INVALID.  */
+  ASSERT (fegetexcept () == 0);
+  {
+    double volatile a;
+    _GL_UNUSED double volatile b;
+    a = 0; b = a / a;
+  }
 
   return 0;
 #endif
diff --git a/tests/test-fenv-env-4.c b/tests/test-fenv-env-4.c
index 9e669f2af5..5cd094a616 100644
--- a/tests/test-fenv-env-4.c
+++ b/tests/test-fenv-env-4.c
@@ -23,7 +23,7 @@
 
 #include "macros.h"
 
-/* Test the combination of feholdexcept() with feupdateenv().  */
+/* Test the combination of feholdexcept() with fesetenv().  */
 
 int
 main ()
@@ -54,13 +54,11 @@ main ()
   ASSERT (fegetexcept () == 0);
 
   /* Go back to env1.  */
-  ASSERT (feupdateenv (&env1) == 0);
+  ASSERT (fesetenv (&env1) == 0);
 
   /* Check that the rounding direction has been restored.  */
   ASSERT (fegetround () == FE_TONEAREST);
-  /* Check that the exception flags are the union of the saved and of the
-     current exception flags.  (The saved exception flags and the current
-     exception flags both happen to be none in this case.)  */
+  /* Check that the exception flags have been restored.  */
   ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
   /* Check that the exception trap bits have been restored.  */
   ASSERT (fegetexcept () == 0);
@@ -76,39 +74,29 @@ main ()
   ASSERT (fegetexcept () == (supports_trapping ? FE_INVALID : 0));
 
   /* Go back to env2.  */
-  ASSERT (feupdateenv (&env2) == 0);
+  ASSERT (fesetenv (&env2) == 0);
 
   /* Check that the rounding direction has been restored.  */
   ASSERT (fegetround () == FE_UPWARD);
-  /* Check that the exception flags are the union of the saved and of the
-     current exception flags.  */
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
+  /* Check that the exception flags have been restored.  */
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_INEXACT : 0));
   /* Check that the exception trap bits have been restored.  */
   ASSERT (fegetexcept () == (supports_trapping ? FE_DIVBYZERO : 0));
 
   /* ======================================================================== */
   /* FE_DFL_ENV */
 
-  /* Go back to the default environment.  */
-  ASSERT (feupdateenv (FE_DFL_ENV) == 0);
-
-  /* Check that the rounding direction has been restored,
-     whereas the exception flags are unmodified.  */
-  ASSERT (fegetround () == FE_TONEAREST);
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
-
   /* Enable trapping on FE_INVALID.  */
   feclearexcept (FE_INVALID);
   feenableexcept (FE_INVALID);
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_INEXACT : 0));
 
   /* Go back to the default environment.  */
-  ASSERT (feupdateenv (FE_DFL_ENV) == 0);
+  ASSERT (fesetenv (FE_DFL_ENV) == 0);
 
-  /* Check that the rounding direction has been restored,
-     whereas the exception flags are unmodified.  */
+  /* Check its contents.  */
   ASSERT (fegetround () == FE_TONEAREST);
-  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
 
   /* Check that it has trapping on FE_INVALID disabled.  */
   ASSERT (fegetexcept () == 0);
diff --git a/tests/test-fenv-env-5.c b/tests/test-fenv-env-5.c
index b54db76791..9e669f2af5 100644
--- a/tests/test-fenv-env-5.c
+++ b/tests/test-fenv-env-5.c
@@ -21,55 +21,127 @@
 /* Specification.  */
 #include <fenv.h>
 
-#include "fpe-trapping.h"
 #include "macros.h"
 
-/* musl libc does not support floating-point exception trapping, even where
-   the hardware supports it.  See
-   <https://wiki.musl-libc.org/functional-differences-from-glibc.html>  */
-#if HAVE_FPE_TRAPPING && (!MUSL_LIBC || GNULIB_FEENABLEEXCEPT)
-
-/* Test that feupdateenv(), unlike fesetenv(), can trigger traps.  */
+/* Test the combination of feholdexcept() with feupdateenv().  */
 
 int
 main ()
 {
-  fenv_t env1;
+#if defined __GLIBC__ && defined __arm__ && defined __SOFTFP__
+  fputs ("Skipping test: no floating-point environment exists on this machine\n", stderr);
+  return 77;
+#else
+  fenv_t env1, env2;
 
   /* Get to a known initial state.  */
   ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
 
-  /* Enable trapping on FE_INVALID.  */
-  if (sigfpe_on_invalid () < 0)
-    {
-      fputs ("Skipping test: trapping floating-point exceptions are not supported on this machine.\n", stderr);
-      return 77;
-    }
-
   /* Save the current environment in env1.  */
-  ASSERT (fegetenv (&env1) == 0);
-
-  /* Go back to the default environment.  */
-  ASSERT (fesetenv (FE_DFL_ENV) == 0);
+  ASSERT (feholdexcept (&env1) == 0);
 
   /* Modify the current environment.  */
-  ASSERT (feraiseexcept (FE_INVALID) == 0);
+  fesetround (FE_UPWARD);
+  int supports_tracking = (feraiseexcept (FE_INVALID | FE_OVERFLOW | FE_INEXACT) == 0);
+  int supports_trapping = (feenableexcept (FE_DIVBYZERO) != -1);
+
+  /* Save the current environment in env2.  */
+  ASSERT (feholdexcept (&env2) == 0);
 
-  /* Go back to env1.
-     Since the exceptions flag FE_INVALID is currently set, and since
-     env1 has trapping on FE_INVALID enabled, this should trap. */
+  /* Check that the exception flags are cleared.  */
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
+  /* Check that the exception trap bits are cleared.  */
+  ASSERT (fegetexcept () == 0);
+
+  /* Go back to env1.  */
   ASSERT (feupdateenv (&env1) == 0);
 
-  return 0;
-}
+  /* Check that the rounding direction has been restored.  */
+  ASSERT (fegetround () == FE_TONEAREST);
+  /* Check that the exception flags are the union of the saved and of the
+     current exception flags.  (The saved exception flags and the current
+     exception flags both happen to be none in this case.)  */
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
+  /* Check that the exception trap bits have been restored.  */
+  ASSERT (fegetexcept () == 0);
+
+  /* Modify the rounding direction, the exception flags, and the exception
+     trap bits again.  */
+  fesetround (FE_DOWNWARD);
+  ASSERT (fegetround () == FE_DOWNWARD);
+  feclearexcept (FE_OVERFLOW);
+  feraiseexcept (FE_UNDERFLOW | FE_INEXACT);
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_UNDERFLOW | FE_INEXACT : 0));
+  feenableexcept (FE_INVALID);
+  ASSERT (fegetexcept () == (supports_trapping ? FE_INVALID : 0));
+
+  /* Go back to env2.  */
+  ASSERT (feupdateenv (&env2) == 0);
+
+  /* Check that the rounding direction has been restored.  */
+  ASSERT (fegetround () == FE_UPWARD);
+  /* Check that the exception flags are the union of the saved and of the
+     current exception flags.  */
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
+  /* Check that the exception trap bits have been restored.  */
+  ASSERT (fegetexcept () == (supports_trapping ? FE_DIVBYZERO : 0));
+
+  /* ======================================================================== */
+  /* FE_DFL_ENV */
 
-#else
+  /* Go back to the default environment.  */
+  ASSERT (feupdateenv (FE_DFL_ENV) == 0);
 
-int
-main ()
-{
-  fputs ("Skipping test: feenableexcept not available\n", stderr);
-  return 77;
-}
+  /* Check that the rounding direction has been restored,
+     whereas the exception flags are unmodified.  */
+  ASSERT (fegetround () == FE_TONEAREST);
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
+
+  /* Enable trapping on FE_INVALID.  */
+  feclearexcept (FE_INVALID);
+  feenableexcept (FE_INVALID);
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
 
+  /* Go back to the default environment.  */
+  ASSERT (feupdateenv (FE_DFL_ENV) == 0);
+
+  /* Check that the rounding direction has been restored,
+     whereas the exception flags are unmodified.  */
+  ASSERT (fegetround () == FE_TONEAREST);
+  ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
+
+  /* Check that it has trapping on FE_INVALID disabled.  */
+  ASSERT (fegetexcept () == 0);
+  {
+    double volatile a;
+    _GL_UNUSED double volatile b;
+    a = 0; b = a / a;
+  }
+
+  /* ======================================================================== */
+  /* Check that feholdexcept, unlike fegetenv, disables trapping.  */
+
+  /* musl libc does not support floating-point exception trapping, even where
+     the hardware supports it.  See
+     <https://wiki.musl-libc.org/functional-differences-from-glibc.html>  */
+# if !MUSL_LIBC || GNULIB_FEENABLEEXCEPT
+  /* Enable trapping on FE_INVALID.  */
+  feclearexcept (FE_INVALID);
+  if (feenableexcept (FE_INVALID) != -1)
+    {
+      /* Call feholdexcept.  */
+      ASSERT (feholdexcept (&env1) == 0);
+
+      /* Check that it has disabled trapping on FE_INVALID.  */
+      ASSERT (fegetexcept () == 0);
+      {
+        double volatile a;
+        _GL_UNUSED double volatile b;
+        a = 0; b = a / a;
+      }
+    }
+# endif
+
+  return 0;
 #endif
+}
diff --git a/tests/test-fenv-env-6.c b/tests/test-fenv-env-6.c
new file mode 100644
index 0000000000..b54db76791
--- /dev/null
+++ b/tests/test-fenv-env-6.c
@@ -0,0 +1,75 @@
+/* Test of controlling the floating-point environment.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <br...@clisp.org>, 2023.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <fenv.h>
+
+#include "fpe-trapping.h"
+#include "macros.h"
+
+/* musl libc does not support floating-point exception trapping, even where
+   the hardware supports it.  See
+   <https://wiki.musl-libc.org/functional-differences-from-glibc.html>  */
+#if HAVE_FPE_TRAPPING && (!MUSL_LIBC || GNULIB_FEENABLEEXCEPT)
+
+/* Test that feupdateenv(), unlike fesetenv(), can trigger traps.  */
+
+int
+main ()
+{
+  fenv_t env1;
+
+  /* Get to a known initial state.  */
+  ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
+
+  /* Enable trapping on FE_INVALID.  */
+  if (sigfpe_on_invalid () < 0)
+    {
+      fputs ("Skipping test: trapping floating-point exceptions are not supported on this machine.\n", stderr);
+      return 77;
+    }
+
+  /* Save the current environment in env1.  */
+  ASSERT (fegetenv (&env1) == 0);
+
+  /* Go back to the default environment.  */
+  ASSERT (fesetenv (FE_DFL_ENV) == 0);
+
+  /* Modify the current environment.  */
+  ASSERT (feraiseexcept (FE_INVALID) == 0);
+
+  /* Go back to env1.
+     Since the exceptions flag FE_INVALID is currently set, and since
+     env1 has trapping on FE_INVALID enabled, this should trap. */
+  ASSERT (feupdateenv (&env1) == 0);
+
+  return 0;
+}
+
+#else
+
+int
+main ()
+{
+  fputs ("Skipping test: feenableexcept not available\n", stderr);
+  return 77;
+}
+
+#endif
diff --git a/tests/test-fenv-env-5.sh b/tests/test-fenv-env-6.sh
similarity index 68%
rename from tests/test-fenv-env-5.sh
rename to tests/test-fenv-env-6.sh
index 5f81a49ba9..0695cbaa4d 100755
--- a/tests/test-fenv-env-5.sh
+++ b/tests/test-fenv-env-6.sh
@@ -4,13 +4,13 @@
 
 final_rc=0
 
-${CHECKER} ./test-fenv-env-5${EXEEXT}
+${CHECKER} ./test-fenv-env-6${EXEEXT}
 rc=$?
 if test $rc = 77; then
   final_rc=77
 else
   if test $rc = 0; then
-    echo "Failed: ./test-fenv-env-5" 1>&2
+    echo "Failed: ./test-fenv-env-6" 1>&2
     exit 1
   fi
 fi
-- 
2.34.1

Reply via email to