https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90638

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|WAITING                     |RESOLVED
         Resolution|---                         |INVALID

--- Comment #9 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #3)
> The change in output occurs with GCC 6 so that might be the version
> this was fixed.

That difference is because GCC 6 uses -std=gnu++14 by default. In C++03 the
only overloads of std::pow for std::complex values are:

template<class T> complex<T> pow(const complex<T>& x, int y);
template<class T>
  complex<T> pow(const complex<T>& x, const complex<T>& y);
template<class T> complex<T> pow (const complex<T>& x, const T& y);
template<class T> complex<T> pow (const T& x, const complex<T>& y);


Calling std::pow(var0, LONG_MAX) or std::pow(var0, LONG_MAX+1UL) will select
the first overload but overflow the int argument. So it's not doing what you
think it's doing.

Your code is undefined in C++03, and you should fix it.

For C++11 that overload was removed by https://wg21.link/lwg844 and so there's
no more overflow. Instead std::pow(var0, LONG_MAX) is equivalent to
std::pow(var0, (double)LONG_MAX) and chooses the third overload.

We don't actually remove the int overload, as explained by this comment in the
source:

  // In C++11 mode we used to implement the resolution of
  // DR 844. complex pow return type is ambiguous.
  // thus the following overload was disabled in that mode.  However, doing
  // that causes all sorts of issues, see, for example:
  //   http://gcc.gnu.org/ml/libstdc++/2013-01/msg00058.html
  // and also PR57974.
  template<typename _Tp>
    inline complex<_Tp>
    pow(const complex<_Tp>& __z, int __n)
    {
      return __n < 0
        ? complex<_Tp>(1) / std::__complex_pow_unsigned(__z, -(unsigned)__n)
        : std::__complex_pow_unsigned(__z, __n);
    }

But we do add additional overloads which get called instead, and then forward
to  the right one.

So this is not a bug, libstdc++ is following the C++03 standard here.

Reply via email to