]> Savannah Git Hosting - gnulib.git/commitdiff
fenv-environment tests: Add a test of the link dependencies.
authorBruno Haible <bruno@clisp.org>
Tue, 7 Nov 2023 21:08:02 +0000 (22:08 +0100)
committerBruno Haible <bruno@clisp.org>
Tue, 7 Nov 2023 21:08:02 +0000 (22:08 +0100)
* 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
modules/fenv-environment-tests
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.c
tests/test-fenv-env-5.sh [deleted file]
tests/test-fenv-env-6.c [new file with mode: 0644]
tests/test-fenv-env-6.sh [new file with mode: 0755]

index 2754d320031c97b0438a982286bf629daad71655..46c4229ca688e16911430b6a3661391d16637238 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2023-11-07  Bruno Haible  <bruno@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  <bruno@clisp.org>
 
        fenv-exceptions-state-c99 tests: Add a test of the link dependencies.
index ecb7b327f3bf58eeaf4b0c9747e66c74a657094c..845979b5a3bccfdadcde81b55e816495d7e9a655 100644 (file)
@@ -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)
index 95c37ad6ac64ef3ef89ac9538019a8acc1f166b4..6c6c70221909ab3ea5b59031bbe0bc333f596f05 100644 (file)
 /* 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
 }
index fa9dec78af6527490813b80ba1b3f1d0da9570bb..95c37ad6ac64ef3ef89ac9538019a8acc1f166b4 100644 (file)
@@ -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);
index 5cd094a61606bbefb9e23b4e6159a77881173311..fa9dec78af6527490813b80ba1b3f1d0da9570bb 100644 (file)
@@ -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
index 9e669f2af5b94e678e05d7522039cb64589a4c46..5cd094a61606bbefb9e23b4e6159a77881173311 100644 (file)
@@ -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);
index b54db767917cf285766a22baca9be613777afa95..9e669f2af5b94e678e05d7522039cb64589a4c46 100644 (file)
 /* 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-5.sh b/tests/test-fenv-env-5.sh
deleted file mode 100755 (executable)
index 5f81a49..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/sh
-
-# Test that feupdateenv() can trigger a trap.
-
-final_rc=0
-
-${CHECKER} ./test-fenv-env-5${EXEEXT}
-rc=$?
-if test $rc = 77; then
-  final_rc=77
-else
-  if test $rc = 0; then
-    echo "Failed: ./test-fenv-env-5" 1>&2
-    exit 1
-  fi
-fi
-
-exit $final_rc
diff --git a/tests/test-fenv-env-6.c b/tests/test-fenv-env-6.c
new file mode 100644 (file)
index 0000000..b54db76
--- /dev/null
@@ -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 <bruno@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-6.sh b/tests/test-fenv-env-6.sh
new file mode 100755 (executable)
index 0000000..0695cba
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Test that feupdateenv() can trigger a trap.
+
+final_rc=0
+
+${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-6" 1>&2
+    exit 1
+  fi
+fi
+
+exit $final_rc