diff options
author | Joseph Myers <joseph@codesourcery.com> | 2013-05-14 19:49:09 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2013-05-14 19:49:09 +0000 |
commit | 2bcb36b265ea2677198c22d005873b9b9600137e (patch) | |
tree | 9c2976bb1bbd8928e2ce60215a000c3215e197f0 /setjmp/tst-setjmp-fp.c | |
parent | acbd839a0745d969f9dcff8c92e16866d922725e (diff) | |
download | glibc-2bcb36b265ea2677198c22d005873b9b9600137e.tar.gz glibc-2bcb36b265ea2677198c22d005873b9b9600137e.tar.xz glibc-2bcb36b265ea2677198c22d005873b9b9600137e.zip |
Add test for setjmp / longjmp and floating-point state.
Diffstat (limited to 'setjmp/tst-setjmp-fp.c')
-rw-r--r-- | setjmp/tst-setjmp-fp.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/setjmp/tst-setjmp-fp.c b/setjmp/tst-setjmp-fp.c new file mode 100644 index 0000000000..dc2b4b0808 --- /dev/null +++ b/setjmp/tst-setjmp-fp.c @@ -0,0 +1,105 @@ +/* Test that setjmp/longjmp do not save and restore floating-point + exceptions and rounding modes. + Copyright (C) 2013 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 <setjmp.h> +#include <stdio.h> +#include <stdlib.h> + +static jmp_buf env; +static int result = 0; + +#if defined FE_TONEAREST && defined FE_TOWARDZERO +static int expected_rounding_mode = FE_TONEAREST; + +static void +change_rounding_mode (void) +{ + if (fesetround (FE_TOWARDZERO) == 0) + expected_rounding_mode = FE_TOWARDZERO; + else + puts ("fesetround (FE_TOWARDZERO) failed, continuing test"); + longjmp (env, 1); +} +#endif + +#ifdef FE_INVALID +static int expected_exceptions = 0; + +static void +raise_exception (void) +{ + if (feraiseexcept (FE_INVALID) == 0) + expected_exceptions = FE_INVALID; + else + puts ("feraiseexcept (FE_INVALID) failed, continuing test"); + longjmp (env, 1); +} +#endif + +static int +do_test (void) +{ +#if defined FE_TONEAREST && defined FE_TOWARDZERO + if (fesetround (FE_TONEAREST) == 0) + { + if (setjmp (env) == 0) + change_rounding_mode (); + else + { + if (fegetround () == expected_rounding_mode) + puts ("PASS: longjmp preserved rounding mode"); + else + { + puts ("FAIL: longjmp changed rounding mode"); + result = 1; + } + } + } + else + puts ("fesetround (FE_TONEAREST) failed, not testing rounding modes"); +#else + puts ("rounding mode test not supported"); +#endif +#ifdef FE_INVALID + if (feclearexcept (FE_ALL_EXCEPT) == 0) + { + if (setjmp (env) == 0) + raise_exception (); + else + { + if (fetestexcept (FE_INVALID) == expected_exceptions) + puts ("PASS: longjmp preserved exceptions"); + else + { + puts ("FAIL: longjmp changed exceptions"); + result = 1; + } + } + } + else + puts ("feclearexcept (FE_ALL_EXCEPT) failed, not testing exceptions"); +#else + puts ("exception test not supported"); +#endif + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |