From: Bruno Haible Date: Sun, 29 Oct 2023 21:20:02 +0000 (+0100) Subject: fenv-exceptions-tracking-c23: New module. X-Git-Tag: v1.0~670 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=b21a4c46d03409e91a44b0dad5fc1e868afe4112;p=gnulib.git fenv-exceptions-tracking-c23: New module. * lib/fenv.in.h (fesetexcept): New declaration. * lib/fenv-except-tracking-set.c: New file, based on glibc. * lib/fenv-private.h (_GETMSR, _SETMSR, MSR_FP_EXC_MASK, PR_SET_FPEXC, PR_FP_EXC_DISABLED, PR_FP_EXC_NONRECOV, PR_FP_EXC_ASYNC, PR_FP_EXC_PRECISE, prctl) [NetBSD/powerpc]: New macros. * m4/fenv-exceptions-tracking-c23.m4: New file. * modules/fenv-exceptions-tracking-c23: New file. * doc/posix-functions/fesetexcept.texi: Mention the new module and the glibc bugs. --- diff --git a/ChangeLog b/ChangeLog index 928ddf72b8..36256c30e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2023-10-29 Bruno Haible + + fenv-exceptions-tracking-c23: New module. + * lib/fenv.in.h (fesetexcept): New declaration. + * lib/fenv-except-tracking-set.c: New file, based on glibc. + * lib/fenv-private.h (_GETMSR, _SETMSR, MSR_FP_EXC_MASK, PR_SET_FPEXC, + PR_FP_EXC_DISABLED, PR_FP_EXC_NONRECOV, PR_FP_EXC_ASYNC, + PR_FP_EXC_PRECISE, prctl) [NetBSD/powerpc]: New macros. + * m4/fenv-exceptions-tracking-c23.m4: New file. + * modules/fenv-exceptions-tracking-c23: New file. + * doc/posix-functions/fesetexcept.texi: Mention the new module and the + glibc bugs. + 2023-10-28 Bruno Haible fenv-exceptions-tracking-c99: Fix feraiseexcept (FE_OVERFLOW) on MSVC. diff --git a/doc/posix-functions/fesetexcept.texi b/doc/posix-functions/fesetexcept.texi index e1535f31a5..23c3ea0868 100644 --- a/doc/posix-functions/fesetexcept.texi +++ b/doc/posix-functions/fesetexcept.texi @@ -10,15 +10,21 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/Status-bit-operations.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: fenv-exceptions-tracking-c23 Portability problems fixed by Gnulib: @itemize +@item +This function is missing on all non-glibc platforms: +glibc 2.24, macOS 11.1, FreeBSD 13.0, NetBSD 9.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.4, Cygwin 2.9, mingw, MSVC 14, Android 9.0. +@item +This function triggers floating-point exception traps although it shouldn't, on +@c https://sourceware.org/bugzilla/show_bug.cgi?id=30989 +glibc 2.37/i386, +@c https://sourceware.org/bugzilla/show_bug.cgi?id=30988 +glibc 2.37/powerpc. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on all non-glibc platforms: -glibc 2.24, macOS 11.1, FreeBSD 13.0, NetBSD 9.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.4, Cygwin 2.9, mingw, MSVC 14, Android 9.0. @end itemize diff --git a/lib/fenv-except-tracking-set.c b/lib/fenv-except-tracking-set.c new file mode 100644 index 0000000000..73b566cb01 --- /dev/null +++ b/lib/fenv-except-tracking-set.c @@ -0,0 +1,500 @@ +/* Functions for tracking which floating-point exceptions have occurred. + Copyright (C) 1997-2023 Free Software Foundation, Inc. + + This file 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. + + This file 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 this program. If not, see . */ + +/* Based on glibc/sysdeps//fesetexcept.c + together with glibc/sysdeps//{fpu_control.h,fenv_private.h,fenv_libc.h}. */ + +#include + +/* Specification. */ +#include + +#include "fenv-private.h" + +#if defined __GNUC__ || defined __clang__ || defined _MSC_VER + +# if (defined __x86_64__ || defined _M_X64) || (defined __i386 || defined _M_IX86) + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + +# if defined _MSC_VER + exceptions = exceptions_to_x86hardware (exceptions); + + /* Set the flags in the SSE unit. */ + unsigned int mxcsr, orig_mxcsr; + _FPU_GETSSECW (orig_mxcsr); + mxcsr = orig_mxcsr | exceptions; + if (mxcsr != orig_mxcsr) + _FPU_SETSSECW (mxcsr); + +# else + + /* We can set the flags in the 387 unit or in the SSE unit. + Either works, due to the way fetestexcept() is implemented. + Choose the simplest approach. */ +# if defined __x86_64__ || defined _M_X64 + /* Set the flags in the SSE unit. */ + unsigned int mxcsr, orig_mxcsr; + _FPU_GETSSECW (orig_mxcsr); + mxcsr = orig_mxcsr | exceptions; + if (mxcsr != orig_mxcsr) + _FPU_SETSSECW (mxcsr); +# else + if (CPU_HAS_SSE ()) + { + /* Set the flags in the SSE unit. */ + unsigned int mxcsr, orig_mxcsr; + _FPU_GETSSECW (orig_mxcsr); + mxcsr = orig_mxcsr | exceptions; + if (mxcsr != orig_mxcsr) + _FPU_SETSSECW (mxcsr); + } + else + { + /* Set the flags in the 387 unit. */ + x86_387_fenv_t env; + unsigned short orig_status_word; + __asm__ __volatile__ ("fnstenv %0" : "=m" (*&env)); + orig_status_word = env.__status_word; + env.__status_word |= exceptions; + if (env.__status_word != orig_status_word) + { + if ((~env.__control_word) & exceptions) + { + /* Setting the exception flags may trigger a trap (at the next + floating-point instruction, but that does not matter). + ISO C 23 § 7.6.4.4 does not allow it. */ + return -1; + } + __asm__ __volatile__ ("fldenv %0" : : "m" (*&env)); + } + } +# endif +# endif + + return 0; +} + +# elif defined __aarch64__ /* arm64 */ + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + + unsigned long fpsr, orig_fpsr; + _FPU_GETFPSR (orig_fpsr); + fpsr = orig_fpsr | exceptions; + if (fpsr != orig_fpsr) + _FPU_SETFPSR (fpsr); + + return 0; +} + +# elif defined __arm__ + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + +# ifdef __SOFTFP__ + if (exceptions != 0) + return -1; +# else + unsigned int fpscr, orig_fpscr; + _FPU_GETCW (orig_fpscr); + fpscr = orig_fpscr | exceptions; + if (fpscr != orig_fpscr) + _FPU_SETCW (fpscr); +# endif + return 0; +} + +# elif defined __alpha + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + + unsigned long swcr, orig_swcr; + orig_swcr = __ieee_get_fp_control (); + swcr = orig_swcr | exceptions; + if (swcr != orig_swcr) + __ieee_set_fp_control (swcr); + + return 0; +} + +# elif defined __hppa + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + + union { unsigned long long fpreg; unsigned int halfreg[2]; } s; + /* Get the current status word. */ + __asm__ __volatile__ ("fstd %%fr0,0(%1)" : "=m" (s.fpreg) : "r" (&s.fpreg) : "%r0"); + unsigned int old_halfreg0 = s.halfreg[0]; + /* Clear all the relevant bits. */ + s.halfreg[0] |= ((unsigned int) exceptions << 27); + if (s.halfreg[0] != old_halfreg0) + { + /* Store the new status word. */ + __asm__ __volatile__ ("fldd 0(%0),%%fr0" : : "r" (&s.fpreg), "m" (s.fpreg) : "%r0"); + } + + return 0; +} + +# elif defined __ia64__ + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + + unsigned long fpsr, orig_fpsr; + _FPU_GETCW (orig_fpsr); + fpsr = orig_fpsr | (unsigned long) (exceptions << 13); + if (fpsr != orig_fpsr) + _FPU_SETCW (fpsr); + + return 0; +} + +# elif defined __m68k__ + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + + unsigned int fpsr, orig_fpsr; + _FPU_GETFPSR (orig_fpsr); + fpsr = orig_fpsr | exceptions; + if (fpsr != orig_fpsr) + _FPU_SETFPSR (fpsr); + + return 0; +} + +# elif defined __mips__ + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + + unsigned int fcsr, orig_fcsr; + _FPU_GETCW (orig_fcsr); + fcsr = orig_fcsr | exceptions; + if (fcsr != orig_fcsr) + _FPU_SETCW (fcsr); + + return 0; +} + +# elif defined __loongarch__ + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + + unsigned int fcsr, orig_fcsr; + _FPU_GETCW (orig_fcsr); + fcsr = orig_fcsr | exceptions; + if (fcsr != orig_fcsr) + _FPU_SETCW (fcsr); + + return 0; +} + +# elif defined __powerpc__ + +int +fesetexcept (int exceptions) +{ + /* The hardware does not support setting an exception flag without triggering + a trap, except through the "Ignore Exceptions Mode", bits FE0 and FE1 of + the MSR register set to zero, that can be obtained through a system call: + - On Linux and NetBSD: prctl (PR_SET_FPEXC, PR_FP_EXC_DISABLED); + - On AIX: fp_trap (FP_TRAP_OFF); + But that is not what we need here, as it would have a persistent effect on + the thread. */ + exceptions &= FE_ALL_EXCEPT; + + union { unsigned long long u; double f; } memenv, orig_memenv; + _FPU_GETCW_AS_DOUBLE (memenv.f); + orig_memenv = memenv; + + /* Instead of setting FE_INVALID (= bit 29), we need to set one of the + individual bits: bit 10 or, if that does not work, bit 24. */ + memenv.u |= (exceptions & FE_INVALID + ? (exceptions & ~FE_INVALID) | (1U << 10) + : exceptions); + + if (!(memenv.u == orig_memenv.u)) + { + if (memenv.u & (exceptions >> 22)) + { + /* Setting the exception flags may trigger a trap. + ISO C 23 § 7.6.4.4 does not allow it. */ + return -1; + } + _FPU_SETCW_AS_DOUBLE (memenv.f); + if (exceptions & FE_INVALID) + { + /* Did it work? */ + _FPU_GETCW_AS_DOUBLE (memenv.f); + if ((memenv.u & FE_INVALID) == 0) + { + memenv.u |= (1U << 24); + _FPU_SETCW_AS_DOUBLE (memenv.f); + } + } + } + + return 0; +} + +# elif defined __riscv + +int +fesetexcept (int exceptions) +{ + /* This is identical to feraiseexcept(), because the hardware does not + support trapping on floating-point exceptions. */ + exceptions &= FE_ALL_EXCEPT; + __asm__ __volatile__ ("csrs fflags, %0" : : "r" (exceptions)); + return 0; +} + +# elif defined __s390__ || defined __s390x__ + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + + unsigned int fpc, orig_fpc; + _FPU_GETCW (orig_fpc); +# if FE_INEXACT == 8 /* glibc compatible FE_* values */ + fpc = orig_fpc | (exceptions << 16); +# else /* musl libc compatible FE_* values */ + fpc = orig_fpc | exceptions; +# endif + if (fpc != orig_fpc) + _FPU_SETCW (fpc); + + return 0; +} + +# elif defined __sh__ + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + + unsigned int fpscr, orig_fpscr; + _FPU_GETCW (orig_fpscr); + fpscr = orig_fpscr | exceptions; + if (fpscr != orig_fpscr) + _FPU_SETCW (fpscr); + + return 0; +} + +# elif defined __sparc + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + + unsigned long fsr, orig_fsr; + _FPU_GETCW (orig_fsr); +# if FE_INEXACT == 32 /* glibc compatible FE_* values */ + fsr = orig_fsr | exceptions; +# else /* Solaris compatible FE_* values */ + fsr = orig_fsr | (exceptions << 5); +# endif + if (fsr != orig_fsr) + _FPU_SETCW (fsr); + + return 0; +} + +# else + +# if defined __GNUC__ || defined __clang__ +# warning "Unknown CPU / architecture. Please report your platform and compiler to ." +# endif +# define NEED_FALLBACK 1 + +# endif + +#else + +/* The compiler does not support __asm__ statements or equivalent + intrinsics. */ + +# if defined __sun && ((defined __x86_64__ || defined _M_X64) || (defined __i386 || defined _M_IX86)) && defined __SUNPRO_C +/* Solaris/i386, Solaris/x86_64. */ + +/* On these platforms, fpsetsticky cannot be used here, because it may generate + traps (since fpsetsticky calls _putsw, which modifies the control word of the + 387 unit). Instead, we need to modify only the flags in the SSE unit. */ + +/* Accessors for the mxcsr register. Fortunately, the Solaris cc supports a + poor form of 'asm'. */ + +static void +getssecw (unsigned int *mxcsr_p) +{ +# if defined __x86_64__ || defined _M_X64 + asm ("stmxcsr (%rdi)"); +# else + /* The compiler generates a stack frame. Therefore the first argument is in + 8(%ebp), not in 4(%esp). */ + asm ("movl 8(%ebp),%eax"); + asm ("stmxcsr (%eax)"); +# endif +} + +static void +setssecw (unsigned int const *mxcsr_p) +{ +# if defined __x86_64__ || defined _M_X64 + asm ("ldmxcsr (%rdi)"); +# else + /* The compiler generates a stack frame. Therefore the first argument is in + 8(%ebp), not in 4(%esp). */ + asm ("movl 8(%ebp),%eax"); + asm ("ldmxcsr (%eax)"); +# endif +} + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + + /* Set the flags in the SSE unit. */ + unsigned int mxcsr, orig_mxcsr; + getssecw (&orig_mxcsr); + mxcsr = orig_mxcsr | exceptions; + if (mxcsr != orig_mxcsr) + setssecw (&mxcsr); + + return 0; +} + +# elif HAVE_FPSETSTICKY +/* FreeBSD ≥ 3.1, NetBSD ≥ 1.1, OpenBSD, IRIX, Solaris, Minix ≥ 3.2. */ + +/* Get fpgetsticky, fpsetsticky. */ +# include +/* The type is called 'fp_except_t' on FreeBSD, but 'fp_except' on + all other systems. */ +# if !defined __FreeBSD__ +# define fp_except_t fp_except +# endif + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + + fp_except_t flags, orig_flags; + orig_flags = fpgetsticky (); + flags = orig_flags | exceptions; + if (flags != orig_flags) + fpsetsticky (flags); + + return 0; +} + +# elif defined _AIX && defined __powerpc__ /* AIX */ + +# include +# include + +# include + +/* Documentation: + */ + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + + /* Instead of setting FE_INVALID (= bit 29), we need to set one of the + individual bits: bit 10 or, if that does not work, bit 24. */ + fpflag_t f_to_set = + (exceptions & FE_INVALID + ? exceptions_to_fpflag (exceptions & ~FE_INVALID) | (1U << 10) + : exceptions_to_fpflag (exceptions)); + if (f_to_set != 0) + { + if ((fegetexcept_impl () & exceptions) != 0) + { + /* Setting the exception flags may trigger a trap. + ISO C 23 § 7.6.4.4 does not allow it. */ + return -1; + } + fp_set_flag (f_to_set); + if (exceptions & FE_INVALID) + { + /* Did it work? */ + if ((fp_read_flag () & FP_INVALID) == 0) + fp_set_flag (1U << 24); + } + } + + return 0; +} + +# else + +# define NEED_FALLBACK 1 + +# endif + +#endif + +#if NEED_FALLBACK + +/* A dummy fallback. */ + +int +fesetexcept (int exceptions) +{ + exceptions &= FE_ALL_EXCEPT; + if (exceptions != 0) + return -1; + return 0; +} + +#endif diff --git a/lib/fenv-private.h b/lib/fenv-private.h index 286768cf10..b5e542b65d 100644 --- a/lib/fenv-private.h +++ b/lib/fenv-private.h @@ -287,6 +287,33 @@ extern void __ieee_set_fp_control (unsigned long); # define _FPU_SETCW_AS_DOUBLE(cw) \ __asm__ __volatile__ ("mtfsf 0xff,%0" : : "f" (cw)) +# if defined __NetBSD__ +/* Modifying the FE0 and FE1 bits of the machine state register (MSR) is + only possible from the kernel. NetBSD allows it to be done from user + space, by emulating the mfmsr and mtmsr instructions when they trap. + In other words, these instructions are actually system calls in NetBSD. */ +# define _GETMSR(msr) __asm__ __volatile__ ("mfmsr %0" : "=r" (msr)) +# define _SETMSR(msr) __asm__ __volatile__ ("mtmsr %0" : : "r" (msr)) +# define MSR_FP_EXC_MASK 0x00000900 +/* This allows us to simulate the Linux prctl() through a macro. */ +# define PR_SET_FPEXC 1 +# define PR_FP_EXC_DISABLED 0x00000000 /* FP exceptions disabled */ +# define PR_FP_EXC_NONRECOV 0x00000100 /* async non-recoverable exc. mode */ +# define PR_FP_EXC_ASYNC 0x00000800 /* async recoverable exception mode */ +# define PR_FP_EXC_PRECISE 0x00000900 /* precise exception mode */ +# define prctl(operation,arg) \ + do { \ + if ((operation) == PR_SET_FPEXC) \ + { \ + unsigned int local_msr; \ + _GETMSR (local_msr); \ + local_msr &= ~MSR_FP_EXC_MASK; \ + local_msr |= (arg) & MSR_FP_EXC_MASK; \ + _SETMSR (local_msr); \ + } \ + } while (0) +# endif + #elif defined __riscv /* fcsr bits 4..0 indicate which floating-point exceptions have occurred diff --git a/lib/fenv.in.h b/lib/fenv.in.h index 9662558805..0c119c5936 100644 --- a/lib/fenv.in.h +++ b/lib/fenv.in.h @@ -514,6 +514,33 @@ _GL_CXXALIAS_SYS (fetestexcept, int, (int exceptions)); _GL_CXXALIASWARN (fetestexcept); #endif +/* Added in ISO C 23 § 7.6.4 Floating-point exceptions. */ + +#if @GNULIB_FESETEXCEPT@ +/* Sets the specified exception flags, without triggering handlers or traps, + and returns 0. Upon failure, it returns non-zero. */ +# if @REPLACE_FESETEXCEPT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fesetexcept +# define fesetexcept rpl_fesetexcept +# endif +_GL_FUNCDECL_RPL (fesetexcept, int, (int exceptions)); +_GL_CXXALIAS_RPL (fesetexcept, int, (int exceptions)); +# else +# if !@HAVE_FESETEXCEPT@ +_GL_FUNCDECL_SYS (fesetexcept, int, (int exceptions)); +# endif +_GL_CXXALIAS_SYS (fesetexcept, int, (int exceptions)); +# endif +_GL_CXXALIASWARN (fesetexcept); +#elif defined GNULIB_POSIXCHECK +# undef fesetexcept +# if HAVE_RAW_DECL_FESETEXCEPT +_GL_WARN_ON_USE (fesetexcept, "fesetexcept is unportable - " + "use gnulib module fenv-exceptions-tracking-c23 for portability"); +# endif +#endif + /* ISO C 99 § 7.6.2 Floating-point exceptions ISO C 23 § 7.6.4 Floating-point exceptions diff --git a/m4/fenv-exceptions-tracking-c23.m4 b/m4/fenv-exceptions-tracking-c23.m4 new file mode 100644 index 0000000000..61c3363d33 --- /dev/null +++ b/m4/fenv-exceptions-tracking-c23.m4 @@ -0,0 +1,86 @@ +# fenv-exceptions-tracking-c23.m4 serial 1 +dnl Copyright (C) 2023 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FENV_EXCEPTIONS_TRACKING_C23], +[ + AC_REQUIRE([gl_FENV_H_DEFAULTS]) + AC_REQUIRE([AC_CANONICAL_HOST]) + + gl_MATHFUNC([fesetexcept], [int], [(int)], [#include ]) + if test $gl_cv_func_fesetexcept_no_libm != yes \ + && test $gl_cv_func_fesetexcept_in_libm != yes; then + HAVE_FESETEXCEPT=0 + else + dnl Persuade glibc to declare feenableexcept(). + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + gl_MATHFUNC([feenableexcept], [int], [(int)], [#include ]) + dnl On glibc 2.37 for PowerPC and i386, fesetexcept may raise traps. + AC_CACHE_CHECK([whether fesetexcept is guaranteed non-trapping], + [gl_cv_func_fesetexcept_works], + [if test $gl_cv_func_feenableexcept_no_libm = yes \ + || test $gl_cv_func_feenableexcept_in_libm = yes; then + dnl A platform that has feenableexcept. + save_LIBS="$LIBS" + if test $gl_cv_func_feenableexcept_no_libm != yes; then + LIBS="$LIBS -lm" + fi + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ + #include + static volatile double a, b; + static volatile long double al, bl; + ]], + [[if (feclearexcept (FE_INVALID) == 0 + && feenableexcept (FE_INVALID) == 0 + && fesetexcept (FE_INVALID) == 0) + { + a = 1.0; b = a + a; + al = 1.0L; bl = al + al; + } + return 0; + ]]) + ], + [gl_cv_func_fesetexcept_works=yes], + [gl_cv_func_fesetexcept_works=no], + [case "$host_os" in + # Guess yes or no on glibc systems, depending on CPU. + *-gnu*) + case "$host_cpu" in +changequote(,)dnl + powerpc* | i[34567]86 | x86_64) +changequote([,])dnl + gl_cv_func_fesetexcept_works="guessing no" ;; + *) + gl_cv_func_fesetexcept_works="guessing yes" ;; + esac + ;; + # If we don't know, obey --enable-cross-guesses. + *) gl_cv_func_fesetexcept_works="$gl_cross_guess_normal" ;; + esac + ]) + LIBS="$save_LIBS" + else + gl_cv_func_fesetexcept_works="guessing yes" + fi + ]) + case "$gl_cv_func_fesetexcept_works" in + *yes) ;; + *) REPLACE_FESETEXCEPT=1 ;; + esac + fi + + dnl Modify FENV_EXCEPTIONS_TRACKING_LIBM, set by gl_FENV_EXCEPTIONS_TRACKING. + AC_REQUIRE([gl_FENV_EXCEPTIONS_TRACKING]) + if test $HAVE_FESETEXCEPT = 0 || test $REPLACE_FESETEXCEPT = 1; then + gl_PREREQ_FENV_EXCEPTIONS + dnl Possibly need -lm for fpgetsticky(), fpsetsticky(). + if test $gl_cv_func_fpsetsticky_no_libm = no \ + && test $gl_cv_func_fpsetsticky_in_libm = yes \ + && test -z "$FENV_EXCEPTIONS_TRACKING_LIBM"; then + FENV_EXCEPTIONS_TRACKING_LIBM=-lm + fi + fi +]) diff --git a/modules/fenv-exceptions-tracking-c23 b/modules/fenv-exceptions-tracking-c23 new file mode 100644 index 0000000000..a10145a24e --- /dev/null +++ b/modules/fenv-exceptions-tracking-c23 @@ -0,0 +1,36 @@ +Description: +Functions for tracking which floating-point exceptions have occurred: +feclearexcept, fesetexcept, feraiseexcept, fetestexcept. + +Files: +lib/fenv-except-tracking-set.c +lib/fenv-private.h +m4/fenv-exceptions-tracking-c23.m4 +m4/mathfunc.m4 + +Depends-on: +fenv +fenv-exceptions-tracking-c99 + +configure.ac: +gl_FENV_EXCEPTIONS_TRACKING_C23 +gl_CONDITIONAL([GL_COND_OBJ_FENV_EXCEPTIONS_TRACKING_C23], + [test $HAVE_FESETEXCEPT = 0 || test $REPLACE_FESETEXCEPT = 1]) +gl_FENV_MODULE_INDICATOR([fesetexcept]) + +Makefile.am: +if GL_COND_OBJ_FENV_EXCEPTIONS_TRACKING_C23 +lib_SOURCES += fenv-except-tracking-set.c +endif + +Include: +#include + +Link: +$(FENV_EXCEPTIONS_TRACKING_LIBM) + +License: +LGPLv2+ + +Maintainer: +all