diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | math/Makefile | 2 | ||||
-rw-r--r-- | math/test-fexcept-traps.c | 84 | ||||
-rw-r--r-- | math/test-fexcept.c | 171 | ||||
-rw-r--r-- | sysdeps/generic/math-tests.h | 9 | ||||
-rw-r--r-- | sysdeps/powerpc/math-tests.h | 6 |
6 files changed, 281 insertions, 1 deletions
@@ -1,3 +1,13 @@ +2016-08-10 Joseph Myers <joseph@codesourcery.com> + + * math/test-fexcept-traps.c: New file. + * math/test-fexcept.c: Likewise. + * math/Makefile (tests): Add test-fexcept and test-fexcept-traps. + * sysdeps/generic/math-tests.h (EXCEPTION_SET_FORCES_TRAP): New + macro. + * sysdeps/powerpc/math-tests.h [!__NO_FPRS__] + (EXCEPTION_SET_FORCES_TRAP): Likewise. + 2016-08-09 Torvald Riegel <triegel@redhat.com> * include/atomic.h (atomic_fetch_and_relaxed, diff --git a/math/Makefile b/math/Makefile index 925b8d4525..1da1797198 100644 --- a/math/Makefile +++ b/math/Makefile @@ -146,7 +146,7 @@ tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \ test-nearbyint-except-2 test-signgam-uchar test-signgam-uchar-init \ test-signgam-uint test-signgam-uint-init test-signgam-ullong \ test-signgam-ullong-init test-nan-overflow test-nan-payload \ - $(tests-static) + test-fexcept test-fexcept-traps $(tests-static) tests-static = test-fpucw-static test-fpucw-ieee-static \ test-signgam-uchar-static test-signgam-uchar-init-static \ test-signgam-uint-static test-signgam-uint-init-static \ diff --git a/math/test-fexcept-traps.c b/math/test-fexcept-traps.c new file mode 100644 index 0000000000..428a444ca3 --- /dev/null +++ b/math/test-fexcept-traps.c @@ -0,0 +1,84 @@ +/* Test fegetexceptflag and fesetexceptflag: exception traps enabled. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <stdio.h> +#include <math-tests.h> + +static int +do_test (void) +{ + int result = 0; + + fedisableexcept (FE_ALL_EXCEPT); + int ret = feraiseexcept (FE_ALL_EXCEPT); + if (ret != 0) + { + if (EXCEPTION_TESTS (float)) + { + puts ("feraiseexcept (FE_ALL_EXCEPT) failed"); + result = 1; + return result; + } + else + { + puts ("feraiseexcept (FE_ALL_EXCEPT) unsupported, cannot test"); + return 77; + } + } + fexcept_t saved; + ret = fegetexceptflag (&saved, FE_ALL_EXCEPT); + if (ret != 0) + { + puts ("fegetexceptflag failed"); + result = 1; + return result; + } + feclearexcept (FE_ALL_EXCEPT); + + ret = feenableexcept (FE_ALL_EXCEPT); + if (!EXCEPTION_ENABLE_SUPPORTED (FE_ALL_EXCEPT) && (ret == -1)) + { + puts ("feenableexcept (FE_ALL_EXCEPT) not supported, cannot test"); + return 77; + } + else if (ret != 0) + { + puts ("feenableexcept (FE_ALL_EXCEPT) failed"); + result = 1; + } + + if (EXCEPTION_SET_FORCES_TRAP) + { + puts ("setting exceptions traps, cannot test on this architecture"); + return 77; + } + /* The test is that this does not cause exception traps. */ + ret = fesetexceptflag (&saved, FE_ALL_EXCEPT); + if (ret != 0) + { + puts ("fesetexceptflag failed"); + result = 1; + } + feclearexcept (FE_ALL_EXCEPT); + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/math/test-fexcept.c b/math/test-fexcept.c new file mode 100644 index 0000000000..5e181a1f8c --- /dev/null +++ b/math/test-fexcept.c @@ -0,0 +1,171 @@ +/* Test fegetexceptflag and fesetexceptflag. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <stdio.h> +#include <math-tests.h> + +static int +test_set (int initial, const fexcept_t *saved, int mask, int expected) +{ + int result = 0; + feclearexcept (FE_ALL_EXCEPT); + printf ("Testing set: initial exceptions %x, mask %x, expected %x\n", + (unsigned int) initial, (unsigned int) mask, + (unsigned int) expected); + int ret = feraiseexcept (initial); + if (ret != 0) + { + puts ("feraiseexcept failed"); + result = 1; + return result; + } + ret = fesetexceptflag (saved, mask); + if (ret != 0) + { + puts ("fesetexceptflag failed"); + result = 1; + } + else + puts ("fesetexceptflag succeeded"); + ret = fetestexcept (FE_ALL_EXCEPT); + if (ret != expected) + { + printf ("raised exceptions %x, expected %x\n", + (unsigned int) ret, (unsigned int) expected); + result = 1; + } + return result; +} + +static int +test_except (int exc, const char *exc_name) +{ + int result = 0; + + printf ("Testing %s\n", exc_name); + feclearexcept (FE_ALL_EXCEPT); + + fexcept_t clear_saved_exc, clear_saved_all; + int ret = fegetexceptflag (&clear_saved_exc, exc); + if (ret == 0) + printf ("fegetexceptflag (%s) succeeded\n", exc_name); + else + { + printf ("fegetexceptflag (%s) failed\n", exc_name); + result = 1; + return result; + } + ret = fegetexceptflag (&clear_saved_all, FE_ALL_EXCEPT); + if (ret == 0) + puts ("fegetexceptflag (FE_ALL_EXCEPT) succeeded"); + else + { + puts ("fegetexceptflag (FE_ALL_EXCEPT) failed"); + result = 1; + return result; + } + + ret = feraiseexcept (exc); + if (ret == 0) + printf ("feraiseexcept (%s) succeeded\n", exc_name); + else + { + printf ("feraiseexcept (%s) failed\n", exc_name); + if (exc == 0 || EXCEPTION_TESTS (float)) + { + puts ("failure of feraiseexcept was unexpected"); + result = 1; + } + else + puts ("failure of feraiseexcept OK, skipping further tests"); + return result; + } + + fexcept_t set_saved_exc, set_saved_all; + ret = fegetexceptflag (&set_saved_exc, exc); + if (ret == 0) + printf ("fegetexceptflag (%s) succeeded\n", exc_name); + else + { + printf ("fegetexceptflag (%s) failed\n", exc_name); + result = 1; + return result; + } + ret = fegetexceptflag (&set_saved_all, FE_ALL_EXCEPT); + if (ret == 0) + puts ("fegetexceptflag (FE_ALL_EXCEPT) succeeded"); + else + { + puts ("fegetexceptflag (FE_ALL_EXCEPT) failed"); + result = 1; + return result; + } + + result |= test_set (0, &set_saved_exc, exc, exc); + result |= test_set (0, &set_saved_all, exc, exc); + result |= test_set (0, &set_saved_all, FE_ALL_EXCEPT, exc); + result |= test_set (0, &clear_saved_exc, exc, 0); + result |= test_set (0, &clear_saved_all, exc, 0); + result |= test_set (0, &clear_saved_all, FE_ALL_EXCEPT, 0); + result |= test_set (exc, &set_saved_exc, exc, exc); + result |= test_set (exc, &set_saved_all, exc, exc); + result |= test_set (exc, &set_saved_all, FE_ALL_EXCEPT, exc); + result |= test_set (exc, &clear_saved_exc, exc, 0); + result |= test_set (exc, &clear_saved_all, exc, 0); + result |= test_set (exc, &clear_saved_all, FE_ALL_EXCEPT, 0); + result |= test_set (FE_ALL_EXCEPT, &set_saved_exc, exc, FE_ALL_EXCEPT); + result |= test_set (FE_ALL_EXCEPT, &set_saved_all, exc, FE_ALL_EXCEPT); + result |= test_set (FE_ALL_EXCEPT, &set_saved_all, FE_ALL_EXCEPT, exc); + result |= test_set (FE_ALL_EXCEPT, &clear_saved_exc, exc, + FE_ALL_EXCEPT & ~exc); + result |= test_set (FE_ALL_EXCEPT, &clear_saved_all, exc, + FE_ALL_EXCEPT & ~exc); + result |= test_set (FE_ALL_EXCEPT, &clear_saved_all, FE_ALL_EXCEPT, 0); + + return result; +} + +static int +do_test (void) +{ + int result = 0; + + result |= test_except (0, "0"); + result |= test_except (FE_ALL_EXCEPT, "FE_ALL_EXCEPT"); +#ifdef FE_DIVBYZERO + result |= test_except (FE_DIVBYZERO, "FE_DIVBYZERO"); +#endif +#ifdef FE_INEXACT + result |= test_except (FE_INEXACT, "FE_INEXACT"); +#endif +#ifdef FE_INVALID + result |= test_except (FE_INVALID, "FE_INVALID"); +#endif +#ifdef FE_OVERFLOW + result |= test_except (FE_OVERFLOW, "FE_OVERFLOW"); +#endif +#ifdef FE_UNDERFLOW + result |= test_except (FE_UNDERFLOW, "FE_UNDERFLOW"); +#endif + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/generic/math-tests.h b/sysdeps/generic/math-tests.h index 9393229a36..974dda403a 100644 --- a/sysdeps/generic/math-tests.h +++ b/sysdeps/generic/math-tests.h @@ -87,3 +87,12 @@ # define EXCEPTION_ENABLE_SUPPORTED(EXCEPT) \ (EXCEPTION_TESTS_float || EXCEPTION_TESTS_double) #endif + +/* Indicate whether exception traps, if enabled, occur whenever an + exception flag is set explicitly, so it is not possible to set flag + bits with traps enabled without causing traps to be taken. If + traps cannot be enabled, the value of this macro does not + matter. */ +#ifndef EXCEPTION_SET_FORCES_TRAP +# define EXCEPTION_SET_FORCES_TRAP 0 +#endif diff --git a/sysdeps/powerpc/math-tests.h b/sysdeps/powerpc/math-tests.h index 31042fa5b6..426a02717d 100644 --- a/sysdeps/powerpc/math-tests.h +++ b/sysdeps/powerpc/math-tests.h @@ -24,4 +24,10 @@ <http://gcc.gnu.org/PR56828>. */ #define SNAN_TESTS_TYPE_CAST 0 +#ifndef __NO_FPRS__ +/* Setting exception flags in FPSCR results in enabled traps for those + exceptions being taken. */ +# define EXCEPTION_SET_FORCES_TRAP 1 +#endif + #include_next <math-tests.h> |