Created attachment 34131 [details] The preprocessed source of the test program We use a cross-conpiler configured as follows: /home/niva/src/gcc-4.7.4/configure --target=mips64-none-elf --enable-threads=no --disable-shared --enable-long-long --enable-c99 --enable-languages=c --enable-multilib --enable-symvers=gnu --disable-libmudflap --disable-libssp --disable-libgcc_eh --with-newlib --with-dwarf2 --with-system-zlib --enable-generated-files-in-srcdir --verbose --prefix=/home/niva/local --enable-cpp The following program (the preprocessed source is attached) #include <assert.h> #include <errno.h> #include <math.h> int main () { double res; errno = 0; res = erf (-1.2553634935946022721708238314E-308); assert (errno == ERANGE); return 0; } compiled as mips64-none-elf-gcc -O1 tst_erf.c produces an assertion though we use a POSIX-compliant math library and the erf function sets errno = ERANGE according to erf description in POSIX Programmer's Manual. The test program works correctly (i.e. without the assertion) if we compile it with -fno-builtin-erf. Apparently GCC treats erf as a "clean" or "pure" function (see gcc/builtins.def). IMHO this is not correct. ISO C 99 (see 7.12.8.1) does not state directly whether erf may set errno. But in 7.12.1 (6) it is stated that "If the result underflows, the function returns an implementation-defined value whose magnitude is no greater than the smallest normalized positive number in the specified type; if the integer expression math_errhandling & MATH_ERRNO is nonzero, whether errno acquires the value ERANGE is implementation-defined; if the integer expression math_errhandling & MATH_ERREXCEPT is nonzero, whether the ‘‘underflow’’ floating-point exception is raised is implementation-defined." In many Linux erf man pages we read that "These functions do not set errno". But there is a bug report https://sourceware.org/bugzilla/show_bug.cgi?id=6785 : "When erf() is given a subnormal argument, it raises an underflow exception. However errno is not set. It should be set to ERANGE."
I think the issue is that you don't use the result of erf() and the function is marked as 'const' - thus does not use ATTR_MATHFN_FPROUNDING_ERRNO. If you make 'res' global then it will work.
Please explain why erf is marked as 'const' and does not use ATTR_MATHFN_FPROUNDING_ERRNO? ISO C does not say that erf may not set errno. And POSIX directly requires that erf, erff, erfl set errno=ERANGE in case of underflow. Here is another example: #include <stdio.h> #include <errno.h> #include <math.h> extern double res; int main () { errno = 0; res = erf (-1.2553634935946022721708238314E-308); printf ("errno=%d, res=%g\n", errno, res); return 0; } As a result of mips64-none-elf-gcc -O1 -S tst2_erf.c -o tst2_erf.s the following code is generated: main: ... addiu $sp,$sp,-40 sd $31,32($sp) sw $0,%gp_rel(errno)($28) jal erf ldc1 $f12,%gp_rel($LC0)($28) sdc1 $f0,%gp_rel(res)($28) lui $4,%hi($LC1) # printf arg 0: format line addiu $4,$4,%lo($LC1) dmfc1 $6,$f0 # printf arg 2: res jal printf move $5,$0 #! printf arg 1: zero (must be errno) move $2,$0 ld $31,32($sp) j $31 addiu $sp,$sp,40 Zero ($0) is passed to printf instead of errno. If -fno-builtin-printf is used the compiler generates lw $5,%gp_rel(errno)($28) instead of move $5,$0 in the delay slot after "jal printf". В Птн, 28/11/2014 в 13:24 +0000, rguenth at gcc dot gnu.org пишет: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64101 > > Richard Biener <rguenth at gcc dot gnu.org> changed: > > What |Removed |Added > ---------------------------------------------------------------------------- > Target| |x86_64-*-*, mips64-none-elf > Status|UNCONFIRMED |NEW > Last reconfirmed| |2014-11-28 > Ever confirmed|0 |1 > > --- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> --- > I think the issue is that you don't use the result of erf() and the function > is marked as 'const' - thus does not use ATTR_MATHFN_FPROUNDING_ERRNO. > If you make 'res' global then it will work. >
possibly related to some of the other -fmath-errno bugs that have been under discussion lately?
(In reply to Eric Gallager from comment #3) > possibly related to some of the other -fmath-errno bugs that have been under > discussion lately? i.e., bug 88576 and bug 37073
Recent glibc documents These functions do not set errno. (and in fact they do not). GCC does not elide the erf() call with -O0 which is how you can verify your erf implementation sets or does not set errno, at -O1 GCC elides the erf call as the result is unused. According to Joseph glibcs behavior is correct and so is then GCCs.