Possible bug in optimizer

Hello.

I'm new to this list, but I've been using Clang for a while (and C++ for many years).

I've encountered a problem when compiling with -O1 on FreeBSD/amd64 11.1 (with bundled Clang, i.e. 4.0.0, as well as with 5.0.1 and 6.0.0 from ports).
I asked on comp.lang.c++ and the code was also confirmed to misbehave on Linux, so they suggested I post it here.

What follows is the minimal code which should produce the error; notice something more convoluted is needed at -O3 (the original software still crashes, but in this example, probably too much is optimized away).

// ------------ a.cpp ------------------
#include <iostream>
#include <numeric>
#include <limits>
#include <cfenv>

  double f(double A,double B) {
    if (A<B) return std::numeric_limits<double>::max();
    return A-B;
  }

  int main(int , char**) {
    feenableexcept(FE_OVERFLOW); //**** NOTE 1
    double A=f(.0001002773902563,1.);
    std::cout<<A<<std::endl;
    double B;
    if (A==std::numeric_limits<double>::max()) {
// std::cout<<"Good"<<std::endl; //**** NOTE 2
      B=A;
    } else {
// std::cout<<"Bad"<<std::endl; //**** NOTE 2
      B=A*2.;
    }
    std::cout<<B<<std::endl;
  }
// ---------------------------------------

The command:
$ clang++ -O1 a.cpp
$ ./a.out
1.79769e+308
Floating point exception (core dumped)

NOTE 1: enabling overflow exceptions on FP math will render the instruction "B=A*2" illegal.
That instruction shouldn't be executed, if following the proper program flow; probably the compiler still has the CPU compute this value speculatively.
NOTE 2: inserting the commented statement makes the program behave correctly again, evidently avoiding the execution of the second branch.

Please let me know if you think this is a bug in the compiler, if using feenableexcept along with optimizations is considered bad practive or if you need further info.

  bye & Thanks
  av.

Hi Andrea,

   feenableexcept(FE_OVERFLOW); //**** NOTE 1

There are two problems here. One with the code and one with Clang.

First, in order to use these floating-point environment functions, the
C (and C++) language requires you to use "#pragma stdc fenv_access
on". Without that, the compiler is free to assume that exceptions
aren't possible and the default rounding mode prevails regardless of
the calls you make. And Clang does.

Unfortunately, the other half is the Clang bug: it doesn't actually
support that #pragma yet. It'll warn (yay!?) but won't actually make
your code work.

One final silver lining is that there's actually a reasonably active
effort to start supporting the pragma going on now. We've got most of
a plan, bits are implemented, and people are working on it. Now that
you know to search for the keyword "fenv_access" you should be able to
find lots more discussion on these lists. Though probably not a
committed timeline, I'm afraid.

Cheers.

Tim.