When fpu trapping is enabled in libgfortran, the return value of feenableexcept is not checked. Glibc reports there if the operation was unsuccessful which happens if the target has no trapping support.
There seems to be a separate api for checking trapping support: ieee_support_halting, but it only checked if the exception status flags are available, so check trapping support too by enabling and disabling traps. Updated the test that changed trapping to use ieee_support_halting, (I think this is better than XFAILing the test case as it tests for things that work without trapping support just fine.) Tested on aarch64-linux-gnu and x86_64-linux-gnu. gcc/testsuite/ 2016-11-15 Szabolcs Nagy <szabolcs.n...@arm.com> PR libgfortran/78314 * gfortran.dg/ieee/ieee_6.f90: Use ieee_support_halting. libgfortran/ 2016-11-15 Szabolcs Nagy <szabolcs.n...@arm.com> PR libgfortran/78314 * config/fpu-glibc.h (support_fpu_trap): Use feenableexcept.
diff --git a/gcc/testsuite/gfortran.dg/ieee/ieee_6.f90 b/gcc/testsuite/gfortran.dg/ieee/ieee_6.f90 index 8fb4f6f..43aa3bf 100644 --- a/gcc/testsuite/gfortran.dg/ieee/ieee_6.f90 +++ b/gcc/testsuite/gfortran.dg/ieee/ieee_6.f90 @@ -9,7 +9,7 @@ implicit none type(ieee_status_type) :: s1, s2 - logical :: flags(5), halt(5) + logical :: flags(5), halt(5), haltworks type(ieee_round_type) :: mode real :: x @@ -18,6 +18,7 @@ call ieee_set_flag(ieee_all, .false.) call ieee_set_rounding_mode(ieee_down) call ieee_set_halting_mode(ieee_all, .false.) + haltworks = ieee_support_halting(ieee_overflow) call ieee_get_status(s1) call ieee_set_status(s1) @@ -46,7 +47,7 @@ call ieee_get_rounding_mode(mode) if (mode /= ieee_to_zero) call abort call ieee_get_halting_mode(ieee_all, halt) - if ((.not. halt(1)) .or. any(halt(2:))) call abort + if ((haltworks .and. .not. halt(1)) .or. any(halt(2:))) call abort call ieee_set_status(s2) @@ -58,7 +59,7 @@ call ieee_get_rounding_mode(mode) if (mode /= ieee_to_zero) call abort call ieee_get_halting_mode(ieee_all, halt) - if ((.not. halt(1)) .or. any(halt(2:))) call abort + if ((haltworks .and. .not. halt(1)) .or. any(halt(2:))) call abort call ieee_set_status(s1) @@ -79,6 +80,6 @@ call ieee_get_rounding_mode(mode) if (mode /= ieee_to_zero) call abort call ieee_get_halting_mode(ieee_all, halt) - if ((.not. halt(1)) .or. any(halt(2:))) call abort + if ((haltworks .and. .not. halt(1)) .or. any(halt(2:))) call abort end diff --git a/libgfortran/config/fpu-glibc.h b/libgfortran/config/fpu-glibc.h index 6e505da..e254fb1 100644 --- a/libgfortran/config/fpu-glibc.h +++ b/libgfortran/config/fpu-glibc.h @@ -121,7 +121,43 @@ get_fpu_trap_exceptions (void) int support_fpu_trap (int flag) { - return support_fpu_flag (flag); + int exceptions = 0; + int old, ret; + + if (!support_fpu_flag (flag)) + return 0; + +#ifdef FE_INVALID + if (flag & GFC_FPE_INVALID) exceptions |= FE_INVALID; +#endif + +#ifdef FE_DIVBYZERO + if (flag & GFC_FPE_ZERO) exceptions |= FE_DIVBYZERO; +#endif + +#ifdef FE_OVERFLOW + if (flag & GFC_FPE_OVERFLOW) exceptions |= FE_OVERFLOW; +#endif + +#ifdef FE_UNDERFLOW + if (flag & GFC_FPE_UNDERFLOW) exceptions |= FE_UNDERFLOW; +#endif + +#ifdef FE_DENORMAL + if (flag & GFC_FPE_DENORMAL) exceptions |= FE_DENORMAL; +#endif + +#ifdef FE_INEXACT + if (flag & GFC_FPE_INEXACT) exceptions |= FE_INEXACT; +#endif + + old = fedisableexcept (exceptions); + if (old == -1) + return 0; + + ret = feenableexcept (exceptions) != -1; + feenableexcept (old); + return ret; }