From e4e615e62b2746ef6a68feaeb7588f1008582e18 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 5 Nov 2023 15:21:06 +0100 Subject: [PATCH] fenv-environment: Add tests. * tests/test-fenv-env-1.c: New file. * tests/test-fenv-env-2.c: New file. * tests/test-fenv-env-3.c: New file. * tests/test-fenv-env-4.c: New file. * tests/test-fenv-env-5.sh: New file. * tests/test-fenv-env-5.c: New file. * modules/fenv-environment-tests: New file. --- ChangeLog | 9 ++ modules/fenv-environment-tests | 37 +++++++++ tests/test-fenv-env-1.c | 129 +++++++++++++++++++++++++++++ tests/test-fenv-env-2.c | 141 +++++++++++++++++++++++++++++++ tests/test-fenv-env-3.c | 135 ++++++++++++++++++++++++++++++ tests/test-fenv-env-4.c | 147 +++++++++++++++++++++++++++++++++ tests/test-fenv-env-5.c | 75 +++++++++++++++++ tests/test-fenv-env-5.sh | 18 ++++ 8 files changed, 691 insertions(+) create mode 100644 modules/fenv-environment-tests create mode 100644 tests/test-fenv-env-1.c create mode 100644 tests/test-fenv-env-2.c create mode 100644 tests/test-fenv-env-3.c create mode 100644 tests/test-fenv-env-4.c create mode 100644 tests/test-fenv-env-5.c create mode 100755 tests/test-fenv-env-5.sh diff --git a/ChangeLog b/ChangeLog index 18ee7639c2..0ff384ba0c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2023-11-05 Bruno Haible + fenv-environment: Add tests. + * tests/test-fenv-env-1.c: New file. + * tests/test-fenv-env-2.c: New file. + * tests/test-fenv-env-3.c: New file. + * tests/test-fenv-env-4.c: New file. + * tests/test-fenv-env-5.sh: New file. + * tests/test-fenv-env-5.c: New file. + * modules/fenv-environment-tests: New file. + fenv-environment: New module. * lib/fenv.in.h (fenv_t) [hppa]: Remove the __exception field. (FE_DFL_ENV): Override if exists but HAVE_FE_DFL_ENV is not diff --git a/modules/fenv-environment-tests b/modules/fenv-environment-tests new file mode 100644 index 0000000000..ecb7b327f3 --- /dev/null +++ b/modules/fenv-environment-tests @@ -0,0 +1,37 @@ +Files: +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/macros.h +m4/musl.m4 + +Depends-on: +fenv-rounding +fenv-exceptions-tracking-c99 +fenv-exceptions-trapping +fpe-trapping + +configure.ac: +gl_MUSL_LIBC + +Makefile.am: +TESTS += \ + test-fenv-env-1 \ + test-fenv-env-2 \ + test-fenv-env-3 \ + test-fenv-env-4 \ + test-fenv-env-5.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_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) diff --git a/tests/test-fenv-env-1.c b/tests/test-fenv-env-1.c new file mode 100644 index 0000000000..95c37ad6ac --- /dev/null +++ b/tests/test-fenv-env-1.c @@ -0,0 +1,129 @@ +/* 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 . */ + +/* Written by Bruno Haible , 2023. */ + +#include + +/* Specification. */ +#include + +#include "macros.h" + +/* Test the combination of fegetenv() with fesetenv(). */ + +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); + + /* 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-2.c b/tests/test-fenv-env-2.c new file mode 100644 index 0000000000..fa9dec78af --- /dev/null +++ b/tests/test-fenv-env-2.c @@ -0,0 +1,141 @@ +/* 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 . */ + +/* Written by Bruno Haible , 2023. */ + +#include + +/* Specification. */ +#include + +#include "macros.h" + +/* Test the combination of fegetenv() with feupdateenv(). */ + +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 (feupdateenv (&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 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_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 (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 */ + + /* 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)); + + /* 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 feupdateenv restores the trapping behaviour. */ + + /* Enable trapping on FE_INVALID. */ + feclearexcept (FE_INVALID); + 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-3.c b/tests/test-fenv-env-3.c new file mode 100644 index 0000000000..5cd094a616 --- /dev/null +++ b/tests/test-fenv-env-3.c @@ -0,0 +1,135 @@ +/* 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 . */ + +/* Written by Bruno Haible , 2023. */ + +#include + +/* Specification. */ +#include + +#include "macros.h" + +/* Test the combination of feholdexcept() with fesetenv(). */ + +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 (feholdexcept (&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 (feholdexcept (&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); + + /* 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 feholdexcept, unlike fegetenv, disables trapping. */ + + /* musl libc does not support floating-point exception trapping, even where + the hardware supports it. See + */ +# 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-4.c b/tests/test-fenv-env-4.c new file mode 100644 index 0000000000..9e669f2af5 --- /dev/null +++ b/tests/test-fenv-env-4.c @@ -0,0 +1,147 @@ +/* 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 . */ + +/* Written by Bruno Haible , 2023. */ + +#include + +/* Specification. */ +#include + +#include "macros.h" + +/* Test the combination of feholdexcept() with feupdateenv(). */ + +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 (feholdexcept (&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 (feholdexcept (&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); + + /* Go back to env1. */ + ASSERT (feupdateenv (&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.) */ + 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 */ + + /* 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)); + + /* 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 + */ +# 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.c b/tests/test-fenv-env-5.c new file mode 100644 index 0000000000..b54db76791 --- /dev/null +++ b/tests/test-fenv-env-5.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 . */ + +/* Written by Bruno Haible , 2023. */ + +#include + +/* Specification. */ +#include + +#include "fpe-trapping.h" +#include "macros.h" + +/* musl libc does not support floating-point exception trapping, even where + the hardware supports it. See + */ +#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-5.sh new file mode 100755 index 0000000000..5f81a49ba9 --- /dev/null +++ b/tests/test-fenv-env-5.sh @@ -0,0 +1,18 @@ +#!/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 -- 2.39.5