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;
 }
 
 

Reply via email to