[Bug libstdc++/90638] Wrong results of pow(complex<T> , T1) function when the T1 type differs from T and from int
redi at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Fri Jun 7 13:45:00 GMT 2019
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.
More information about the Gcc-bugs
mailing list