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