Bug 29887

Summary: wrong-code for errno handling on overflow/underflow
Product: gcc Reporter: Richard Biener <rguenth>
Component: middle-endAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: gcc-bugs, msebor
Priority: P3 Keywords: wrong-code
Version: 4.3.0   
Target Milestone: 6.0   
Host: Target: i?86-*-*
Build: Known to work:
Known to fail: Last reconfirmed: 2017-02-24 00:00:00

Description Richard Biener 2006-11-18 15:08:21 UTC
builtins.c:expand_errno_check() can only handle setting EDOM if the operation
returns NaN on error.  Most overflow/underflow conditions result in -Inf/+Inf
instead and with non-default rounding-mode (-frounding-math) the maximum or
minimum floating-point value will be returned (round to -Inf/+Inf or zero).

One testcase:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
  double y = atof(argv[1]);
  double x = exp (y);
  printf("%.6e %.6e\n", y, x);
  perror("errno");
  return 0;
}

which shall print "errno: Numerical result out of range" if you pass 5000
to the testcase executable but prints "errno: Success" if you build with
-funsafe-math-optimizations on i686 which will do an inline expansion for
exp ().
Comment 1 Manuel López-Ibáñez 2006-11-26 13:38:39 UTC
Hi, Richard. 

I don't understand completely what you mean. Is the problem in the builtin exp() ? Should it check its argument for large numbers? 
Comment 2 Richard Biener 2006-11-26 13:56:31 UTC
The problem is that we believe we can handle all errno checking/setting via
the expand_errno_check() routine which is not true for overflow/underflow but
only for invalid arguments that result in a NaN.
Comment 3 Manuel López-Ibáñez 2006-12-03 21:12:55 UTC
(In reply to comment #2)
> The problem is that we believe we can handle all errno checking/setting via
> the expand_errno_check() routine which is not true for overflow/underflow but
> only for invalid arguments that result in a NaN.
> 

Is there underflow/overflow if the value is so small/big that we end up with zero/infinite? I am really confused about that. See for example bug 23572.

Comment 4 Richard Biener 2006-12-06 08:58:46 UTC
With overflow we end up with Inf or -Inf, with underflow we end up with 0. (or even -0.?) - but underflow doesn't seem to require a diagnostic errno setting.

I don't see how this relates to PR23572 though.
Comment 5 Martin Sebor 2017-02-24 03:55:49 UTC
When compiled with today's GCC 7 the test case prints the expected result.  Is there still a problem here or can the bug be resolved as fixed?

$ (set -x && cat t.c && for m in 32 64; do gcc -O2 -Wall -funsafe-math-optimizations -m$m -lm t.c && ./a.out 5000; done)

+ cat t.c
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
  double y = atof(argv[1]);
  double x = exp (y);
  printf("%.6e %.6e\n", y, x);
  perror("errno");
  return 0;
}
+ for m in 32 64
+ gcc -O2 -Wall -funsafe-math-optimizations -m32 -lm t.c
+ ./a.out 5000
5.000000e+03 inf
errno: Numerical result out of range
+ for m in 32 64
+ gcc -O2 -Wall -funsafe-math-optimizations -m64 -lm t.c
+ ./a.out 5000
5.000000e+03 inf
errno: Numerical result out of range
Comment 6 Richard Biener 2017-02-24 08:16:32 UTC
Note this bug mostly applied to -mfancy-math-387 -m32 [-funsafe-math-optimizations].  It seems the expand_errno_check() optimization
has been removed gradually and finally with

2015-11-17  Richard Sandiford  <richard.sandiford@arm.com>

        * builtins.c (expand_errno_check, expand_builtin_mathfn)
        (expand_builtin_mathfn_2): Delete.
        (expand_builtin): Remove handling of functions with
        internal function equivalents.
...

Thus this is fixed fully since GCC 6.