* 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-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.
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
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)
/* 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
}
#include "macros.h"
-/* Test the combination of fegetenv() with feupdateenv(). */
+/* Test the combination of fegetenv() with fesetenv(). */
int
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);
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);
}
/* ======================================================================== */
- /* 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);
#include "macros.h"
-/* Test the combination of feholdexcept() with fesetenv(). */
+/* Test the combination of fegetenv() with feupdateenv(). */
int
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);
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);
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);
}
/* ======================================================================== */
- /* 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
#include "macros.h"
-/* Test the combination of feholdexcept() with feupdateenv(). */
+/* Test the combination of feholdexcept() with fesetenv(). */
int
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);
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);
/* 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
+}
+++ /dev/null
-#!/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
--- /dev/null
+/* 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
--- /dev/null
+#!/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