5

Consider the following code:

#include <fenv.h>
#include <stdio.h>
int main()
{
    #pragma STDC FENV_ACCESS ON
    1.0/0.0;
    printf("%x\n", fetestexcept(FE_ALL_EXCEPT));
}

I would expect it to print a nonzero value corresponding to FE_DIVBYZERO, but it prints 0. Changing the second line of main to double x = 1.0/0.0; gives the expected behavior. Is this permitted, or is it a bug?

Edit: For what it's worth, at first it may seem that in most real-world code, the operations which might cause fenv exceptions to be raised could not be optimized out, so one could safely perform large computations and check at the end whether any overflow, div-by-zero, etc. happened. However, things get messy and a real issue emerges when you consider inlining and optimization. If such a function got inlined in a situation where it would always end up dividing by zero due to constant arguments, gcc might get really smart and optimize the whole inlined function essentially to return INFINITY; without raising any exceptions.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711

5 Answers5

6

This is expected behaviour. gcc doesn't evaluate the expression, because it would have nothing to do with it afterwards.

If you compile with "-Wall", it warns you that the statement has no effect, and that it ignores the pragma statement.

GCC is not fully C99 compliant. For more information, see: http://gcc.gnu.org/c99status.html

For the issue of implementing this behaviour, see: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20785

dougallj
  • 409
  • 2
  • 4
  • Accepted. BTW the information in `c99status.html` is rather misleading. It calls the absence of floating point environment support a "Library Issue" when the the remaining issues are not at the library level but the compiler level... – R.. GitHub STOP HELPING ICE Jun 13 '11 at 22:18
  • Also, even if GCC supported the C99 floating point semantics entirely I think that you'd have to turn off `FP_CONTRACT`, too. Otherwise "a contracted expression might also omit the raising of floating-point exceptions" (a footnote to 6.5/8). Note that turning off `FP_CONTRACT` didn't seem to help in my quick test. – Michael Burr Jun 14 '11 at 07:45
2

This is something of a gray area. A strict reading of the floating-point environment section of the standard could easily lead one to believe that this is a bug. I suspect that the GCC maintainers will disagree with that reading, however.

For that matter, I'm not sure that GCC even claims to understand the FENV_ACCESS pragma. Certainly earlier versions did not.

Stephen Canon
  • 103,815
  • 19
  • 183
  • 269
  • As far as I can tell, the standard seems to require each floating point operator to be treated as if it were a function call with side effects when `FENV_ACCESS` is in effect... Does this seem accurate? – R.. GitHub STOP HELPING ICE Jun 14 '11 at 04:19
  • 1
    @R..: not *quite*, but nearly. In particular, the "as if" rule is in effect; the compiler is still free to perform any optimizations that do not change the observable behavior at sequence points. It's also worth noting that the standard explicitly requires a compiler that doesn't support FENV_ACCESS to implement the "ON" behavior. This is a bug in GCC. – Stephen Canon Jun 14 '11 at 06:40
  • I couldn't find anything in 7.6 that overrules 6.5.5/5, making division by zero undefined behavior. Annex F seems to apply only when the implementation defines `__STDC_IEC_559__`, and I don't know whether any version of gcc does that. I'm likely missing something, but if I'm not the program exhibits undefined behavior. It would be interesting to try it with a stand-alone expression that causes floating-point behavior that isn't a divide by zero (possibly overflow) so 6.5.5/5 would definitely not apply. – David Thornley Jun 14 '11 at 14:33
2

Compiling with -Wall on gcc 4.6.0 says:

f.c:5:0: warning: ignoring #pragma FENV_ACCESS ON [-Wunknown-pragmas]

According to the GCC info pages:

* `The default state for the `FENV_ACCESS' pragma (C99 7.6.1).'

 This pragma is not implemented, but the default is to "off" unless
 `-frounding-math' is used in which case it is "on".

Unfortuantely, -frounding-math does not seem to have any effect on your program.

Arguably a compiler bug; I would ask on one of the GCC mailing lists.

Nemo
  • 70,042
  • 10
  • 116
  • 153
0

It's possible that your compiler has optimized the original version out. Recognizing that the two constants are not "used" in any non-trivial sense, it may not even exist in the compiled binary.

The second example changes that, by actually assigning the operation to a variable.

dolphy
  • 6,218
  • 4
  • 24
  • 32
  • Due to `#pragma FE_ENV_ACCESS ON`, the statement has side effects and thus cannot be optimized out, unless there's some special exception in the standard that allows it to be. – R.. GitHub STOP HELPING ICE Jun 13 '11 at 21:54
0

I think the expression is getting optimised away in the first case, but not in the second. I can reproduce your results with gcc 4.2 with gcc -O0, but if I go to gcc -O3 then I get 0 in both cases.

Paul R
  • 208,748
  • 37
  • 389
  • 560