From 09095af14fcc2d2903a65901e204e40d18ca4fe2 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sat, 28 Oct 2023 18:39:32 +0200 Subject: [PATCH] fenv-exceptions-tracking-c99: Add tests. * tests/test-fenv-except-tracking-1.c: New file. * tests/test-fenv-except-tracking-2.sh: New file. * tests/test-fenv-except-tracking-2.c: New file. * tests/test-fenv-except-tracking-3.sh: New file. * tests/test-fenv-except-tracking-3.c: New file. * modules/fenv-exceptions-tracking-c99-tests: New file. --- ChangeLog | 8 + modules/fenv-exceptions-tracking-c99-tests | 27 +++ tests/test-fenv-except-tracking-1.c | 250 +++++++++++++++++++++ tests/test-fenv-except-tracking-2.c | 101 +++++++++ tests/test-fenv-except-tracking-2.sh | 20 ++ tests/test-fenv-except-tracking-3.c | 64 ++++++ tests/test-fenv-except-tracking-3.sh | 18 ++ 7 files changed, 488 insertions(+) create mode 100644 modules/fenv-exceptions-tracking-c99-tests create mode 100644 tests/test-fenv-except-tracking-1.c create mode 100644 tests/test-fenv-except-tracking-2.c create mode 100755 tests/test-fenv-except-tracking-2.sh create mode 100644 tests/test-fenv-except-tracking-3.c create mode 100755 tests/test-fenv-except-tracking-3.sh diff --git a/ChangeLog b/ChangeLog index b1c73c0f98..3af21529c2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2023-10-28 Bruno Haible + fenv-exceptions-tracking-c99: Add tests. + * tests/test-fenv-except-tracking-1.c: New file. + * tests/test-fenv-except-tracking-2.sh: New file. + * tests/test-fenv-except-tracking-2.c: New file. + * tests/test-fenv-except-tracking-3.sh: New file. + * tests/test-fenv-except-tracking-3.c: New file. + * modules/fenv-exceptions-tracking-c99-tests: New file. + fenv-exceptions-tracking-c99: New module. * lib/fenv.in.h (feclearexcept, feraiseexcept, fetestexcept): New declarations. diff --git a/modules/fenv-exceptions-tracking-c99-tests b/modules/fenv-exceptions-tracking-c99-tests new file mode 100644 index 0000000000..8c1dde15c6 --- /dev/null +++ b/modules/fenv-exceptions-tracking-c99-tests @@ -0,0 +1,27 @@ +Files: +tests/test-fenv-except-tracking-1.c +tests/test-fenv-except-tracking-2.sh +tests/test-fenv-except-tracking-2.c +tests/test-fenv-except-tracking-3.sh +tests/test-fenv-except-tracking-3.c +tests/macros.h +m4/musl.m4 + +Depends-on: +fpe-trapping + +configure.ac: +gl_MUSL_LIBC + +Makefile.am: +TESTS += \ + test-fenv-except-tracking-1 \ + test-fenv-except-tracking-2.sh \ + test-fenv-except-tracking-3.sh +check_PROGRAMS += \ + test-fenv-except-tracking-1 \ + test-fenv-except-tracking-2 \ + test-fenv-except-tracking-3 +test_fenv_except_tracking_1_LDADD = $(LDADD) @FENV_EXCEPTIONS_TRACKING_LIBM@ +test_fenv_except_tracking_2_LDADD = $(LDADD) @FENV_EXCEPTIONS_TRACKING_LIBM@ @FPE_TRAPPING_LIBM@ +test_fenv_except_tracking_3_LDADD = $(LDADD) @FENV_EXCEPTIONS_TRACKING_LIBM@ @FPE_TRAPPING_LIBM@ diff --git a/tests/test-fenv-except-tracking-1.c b/tests/test-fenv-except-tracking-1.c new file mode 100644 index 0000000000..b7f871e12b --- /dev/null +++ b/tests/test-fenv-except-tracking-1.c @@ -0,0 +1,250 @@ +/* Test of tracking of floating-point exceptions. + 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" + +static volatile double a, b, c; + +int +main () +{ + /* Test setting all exception flags. */ + if (feraiseexcept (FE_ALL_EXCEPT) != 0) + { + fputs ("Skipping test: floating-point exceptions are not supported on this machine.\n", stderr); + return 77; + } + ASSERT (/* with the libc's feraiseexcept(): */ + fetestexcept (FE_ALL_EXCEPT) == FE_ALL_EXCEPT + || /* with gnulib's feraiseexcept(): */ + fetestexcept (FE_ALL_EXCEPT) + == (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | 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) == FE_INEXACT); + + /* Test clearing all exception flags. */ + ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0); + ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0); + ASSERT (fetestexcept (FE_INVALID) == 0); + ASSERT (fetestexcept (FE_DIVBYZERO) == 0); + ASSERT (fetestexcept (FE_OVERFLOW) == 0); + ASSERT (fetestexcept (FE_UNDERFLOW) == 0); + ASSERT (fetestexcept (FE_INEXACT) == 0); + + + /* Test setting just one exception flag: FE_INVALID. */ + ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0); + ASSERT (feraiseexcept (FE_INVALID) == 0); + ASSERT (fetestexcept (FE_ALL_EXCEPT) == FE_INVALID); + ASSERT (fetestexcept (FE_INVALID) == FE_INVALID); + ASSERT (fetestexcept (FE_DIVBYZERO) == 0); + ASSERT (fetestexcept (FE_OVERFLOW) == 0); + ASSERT (fetestexcept (FE_UNDERFLOW) == 0); + ASSERT (fetestexcept (FE_INEXACT) == 0); + + /* Test setting just one exception flag: FE_DIVBYZERO. */ + ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0); + ASSERT (feraiseexcept (FE_DIVBYZERO) == 0); + ASSERT (fetestexcept (FE_ALL_EXCEPT) == FE_DIVBYZERO); + ASSERT (fetestexcept (FE_INVALID) == 0); + ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO); + ASSERT (fetestexcept (FE_OVERFLOW) == 0); + ASSERT (fetestexcept (FE_UNDERFLOW) == 0); + ASSERT (fetestexcept (FE_INEXACT) == 0); + + /* Test setting just one exception flag: FE_OVERFLOW. + On many architectures, this has the side-effect of also setting FE_INEXACT: + arm64, arm, alpha, hppa, ia64, loongarch64, s390, sh, sparc. */ + ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0); + ASSERT (feraiseexcept (FE_OVERFLOW) == 0); + ASSERT ((fetestexcept (FE_ALL_EXCEPT) & ~FE_INEXACT) == FE_OVERFLOW); + ASSERT (fetestexcept (FE_INVALID) == 0); + ASSERT (fetestexcept (FE_DIVBYZERO) == 0); + ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW); + ASSERT (fetestexcept (FE_UNDERFLOW) == 0); + + /* Test setting just one exception flag: FE_UNDERFLOW. + On many architectures, this has the side-effect of also setting FE_INEXACT: + arm64, arm, alpha, hppa, ia64, loongarch64, s390, sh, sparc. */ + ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0); + ASSERT (feraiseexcept (FE_UNDERFLOW) == 0); + ASSERT ((fetestexcept (FE_ALL_EXCEPT) & ~FE_INEXACT) == FE_UNDERFLOW); + ASSERT (fetestexcept (FE_INVALID) == 0); + ASSERT (fetestexcept (FE_DIVBYZERO) == 0); + ASSERT (fetestexcept (FE_OVERFLOW) == 0); + ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW); + + /* Test setting just one exception flag: FE_INEXACT. */ + ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0); + ASSERT (feraiseexcept (FE_INEXACT) == 0); + ASSERT (fetestexcept (FE_ALL_EXCEPT) == FE_INEXACT); + ASSERT (fetestexcept (FE_INVALID) == 0); + ASSERT (fetestexcept (FE_DIVBYZERO) == 0); + ASSERT (fetestexcept (FE_OVERFLOW) == 0); + ASSERT (fetestexcept (FE_UNDERFLOW) == 0); + ASSERT (fetestexcept (FE_INEXACT) == FE_INEXACT); + + + /* Test clearing just one exception flag: FE_INVALID. */ + ASSERT (feraiseexcept (FE_ALL_EXCEPT) == 0); + ASSERT (feclearexcept (FE_INVALID) == 0); + ASSERT (/* with the libc's feraiseexcept(): */ + fetestexcept (FE_ALL_EXCEPT) == (FE_ALL_EXCEPT & ~FE_INVALID) + || /* with gnulib's feraiseexcept(): */ + fetestexcept (FE_ALL_EXCEPT) + == (FE_DIVBYZERO | FE_INEXACT | 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) == FE_INEXACT); + + /* Test clearing just one exception flag: FE_DIVBYZERO. */ + ASSERT (feraiseexcept (FE_ALL_EXCEPT) == 0); + ASSERT (feclearexcept (FE_DIVBYZERO) == 0); + ASSERT (/* with the libc's feraiseexcept(): */ + fetestexcept (FE_ALL_EXCEPT) == (FE_ALL_EXCEPT & ~FE_DIVBYZERO) + || /* with gnulib's feraiseexcept(): */ + fetestexcept (FE_ALL_EXCEPT) + == (FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)); + ASSERT (fetestexcept (FE_INVALID) == FE_INVALID); + ASSERT (fetestexcept (FE_DIVBYZERO) == 0); + ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW); + ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW); + ASSERT (fetestexcept (FE_INEXACT) == FE_INEXACT); + + /* Test clearing just one exception flag: FE_OVERFLOW. */ + ASSERT (feraiseexcept (FE_ALL_EXCEPT) == 0); + ASSERT (feclearexcept (FE_OVERFLOW) == 0); + ASSERT (/* with the libc's feraiseexcept(): */ + fetestexcept (FE_ALL_EXCEPT) == (FE_ALL_EXCEPT & ~FE_OVERFLOW) + || /* with gnulib's feraiseexcept(): */ + fetestexcept (FE_ALL_EXCEPT) + == (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | 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) == FE_INEXACT); + + /* Test clearing just one exception flag: FE_UNDERFLOW. */ + ASSERT (feraiseexcept (FE_ALL_EXCEPT) == 0); + ASSERT (feclearexcept (FE_UNDERFLOW) == 0); + ASSERT (/* with the libc's feraiseexcept(): */ + fetestexcept (FE_ALL_EXCEPT) == (FE_ALL_EXCEPT & ~FE_UNDERFLOW) + || /* with gnulib's feraiseexcept(): */ + fetestexcept (FE_ALL_EXCEPT) + == (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW)); + ASSERT (fetestexcept (FE_INVALID) == FE_INVALID); + ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO); + ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW); + ASSERT (fetestexcept (FE_UNDERFLOW) == 0); + ASSERT (fetestexcept (FE_INEXACT) == FE_INEXACT); + + /* Test clearing just one exception flag: FE_INEXACT. */ + ASSERT (feraiseexcept (FE_ALL_EXCEPT) == 0); + ASSERT (feclearexcept (FE_INEXACT) == 0); + ASSERT (/* with the libc's feraiseexcept(): */ + fetestexcept (FE_ALL_EXCEPT) == (FE_ALL_EXCEPT & ~FE_INEXACT) + || /* with gnulib's feraiseexcept(): */ + fetestexcept (FE_ALL_EXCEPT) + == (FE_DIVBYZERO | FE_INVALID | 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); + + +#if !(defined __arm__ && defined __SOFTFP__) + /* Test the effects of an operation that produces FE_INVALID. */ + ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0); + a = 0; b = 0; c = a / b; + ASSERT (fetestexcept (FE_ALL_EXCEPT) == FE_INVALID); + ASSERT (fetestexcept (FE_INVALID) == FE_INVALID); + ASSERT (fetestexcept (FE_DIVBYZERO) == 0); + ASSERT (fetestexcept (FE_OVERFLOW) == 0); + ASSERT (fetestexcept (FE_UNDERFLOW) == 0); + ASSERT (fetestexcept (FE_INEXACT) == 0); + + /* Test the effects of an operation that produces FE_DIVBYZERO. */ + ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0); + a = 3; b = 0; c = a / b; + ASSERT (fetestexcept (FE_ALL_EXCEPT) == FE_DIVBYZERO); + ASSERT (fetestexcept (FE_INVALID) == 0); + ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO); + ASSERT (fetestexcept (FE_OVERFLOW) == 0); + ASSERT (fetestexcept (FE_UNDERFLOW) == 0); + ASSERT (fetestexcept (FE_INEXACT) == 0); + + /* Test the effects of an operation that produces FE_OVERFLOW. */ + ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0); + a = 1; for (int i = 0; i < 800; i++) a = 2.0 * a; + b = 1; for (int i = 0; i < 700; i++) b = 2.0 * b; + c = a * b; + { + int exc = fetestexcept (FE_ALL_EXCEPT); + ASSERT ((FE_OVERFLOW & !exc) == 0); + ASSERT ((exc & ~(FE_OVERFLOW | FE_INEXACT)) == 0); + } + ASSERT (fetestexcept (FE_INVALID) == 0); + ASSERT (fetestexcept (FE_DIVBYZERO) == 0); + ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW); + ASSERT (fetestexcept (FE_UNDERFLOW) == 0); + + /* Test the effects of an operation that produces FE_UNDERFLOW. */ + ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0); + a = 1; for (int i = 0; i < 800; i++) a = 0.5 * a; + b = 1; for (int i = 0; i < 700; i++) b = 0.5 * b; + c = a * b; + { + int exc = fetestexcept (FE_ALL_EXCEPT); + ASSERT ((FE_UNDERFLOW & !exc) == 0); + ASSERT ((exc & ~(FE_UNDERFLOW | FE_INEXACT)) == 0); + } + ASSERT (fetestexcept (FE_INVALID) == 0); + ASSERT (fetestexcept (FE_DIVBYZERO) == 0); + ASSERT (fetestexcept (FE_OVERFLOW) == 0); + ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW); + +/* On alpha, this test works only when compiled with the GCC option + '-mieee-with-inexact'. */ +# if !defined __alpha + /* Test the effects of an operation that produces FE_INEXACT. */ + ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0); + a = 1; b = 3; c = a / b; + ASSERT (fetestexcept (FE_ALL_EXCEPT) == FE_INEXACT); + ASSERT (fetestexcept (FE_INVALID) == 0); + ASSERT (fetestexcept (FE_DIVBYZERO) == 0); + ASSERT (fetestexcept (FE_OVERFLOW) == 0); + ASSERT (fetestexcept (FE_UNDERFLOW) == 0); + ASSERT (fetestexcept (FE_INEXACT) == FE_INEXACT); +# endif +#endif + + + return 0; +} diff --git a/tests/test-fenv-except-tracking-2.c b/tests/test-fenv-except-tracking-2.c new file mode 100644 index 0000000000..e6f9bf1f9d --- /dev/null +++ b/tests/test-fenv-except-tracking-2.c @@ -0,0 +1,101 @@ +/* Test of tracking of floating-point exceptions. + 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 + +#include "fpe-trapping.h" +#include "macros.h" + +#if HAVE_FPE_TRAPPING + +/* Check that triggering a floating-point operation can trigger a trap. */ + +int +main (int argc, char *argv[]) +{ + /* Clear FE_INVALID exceptions from past operations. */ + feclearexcept (FE_INVALID); + + /* 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; + } + + if (argc > 1) + switch (argv[1][0]) + { + case 'f': + { + volatile float a, b; + _GL_UNUSED volatile float c; + a = 0; b = 0; c = a / b; + } + break; + + case 'd': + { + volatile double a, b; + _GL_UNUSED volatile double c; + a = 0; b = 0; c = a / b; + } + break; + + case 'l': + /* This test does not work on Linux/loongarch64 with glibc 2.37. + Likewise on Linux/alpha with glibc 2.7 on Linux 2.6.26. + Likewise on FreeBSD 12.2/sparc. + Cause unknown. */ + #if !((__GLIBC__ >= 2 && defined __loongarch__) \ + || ((__GLIBC__ == 2 && __GLIBC_MINOR__ < 36) && defined __alpha) \ + || (defined __FreeBSD__ && defined __sparc)) + { + volatile long double a, b; + _GL_UNUSED volatile long double c; + a = 0; b = 0; c = a / b; + } + #else + fputs ("Skipping test: known failure on this platform\n", stderr); + return 77; + #endif + break; + + default: + break; + } + + return 0; +} + +#else + +int +main () +{ + fputs ("Skipping test: feenableexcept or fpsetmask or fp_enable not available\n", stderr); + return 77; +} + +#endif diff --git a/tests/test-fenv-except-tracking-2.sh b/tests/test-fenv-except-tracking-2.sh new file mode 100755 index 0000000000..deb3ed6c79 --- /dev/null +++ b/tests/test-fenv-except-tracking-2.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# Test that a floating-point operation can trigger a trap. + +final_rc=0 + +for arg in f d l; do + ${CHECKER} ./test-fenv-except-tracking-2${EXEEXT} $arg + rc=$? + if test $rc = 77; then + final_rc=77 + else + if test $rc = 0; then + echo "Failed: ./test-fenv-except-tracking-2 $arg" 1>&2 + exit 1 + fi + fi +done + +exit $final_rc diff --git a/tests/test-fenv-except-tracking-3.c b/tests/test-fenv-except-tracking-3.c new file mode 100644 index 0000000000..a7ef77a206 --- /dev/null +++ b/tests/test-fenv-except-tracking-3.c @@ -0,0 +1,64 @@ +/* Test of tracking of floating-point exceptions. + 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 + +#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) + +/* Check that feraiseexcept() can trigger a trap. */ + +int +main () +{ + /* Clear FE_INVALID exceptions from past operations. */ + feclearexcept (FE_INVALID); + + /* 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; + } + + feraiseexcept (FE_INVALID); + + return 0; +} + +#else + +int +main () +{ + fputs ("Skipping test: feenableexcept or fpsetmask or fp_enable not available\n", stderr); + return 77; +} + +#endif diff --git a/tests/test-fenv-except-tracking-3.sh b/tests/test-fenv-except-tracking-3.sh new file mode 100755 index 0000000000..f44e43a59b --- /dev/null +++ b/tests/test-fenv-except-tracking-3.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# Test that feraiseexcept() can trigger a trap. + +final_rc=0 + +${CHECKER} ./test-fenv-except-tracking-3${EXEEXT} +rc=$? +if test $rc = 77; then + final_rc=77 +else + if test $rc = 0; then + echo "Failed: ./test-fenv-except-tracking-3" 1>&2 + exit 1 + fi +fi + +exit $final_rc -- 2.39.5