diff options
author | Eric Fiselier <eric@efcs.ca> | 2016-07-20 00:14:10 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2016-07-20 00:14:10 +0000 |
commit | b11642bf947d917c7ec284247fe58eb2a25ab4bd (patch) | |
tree | bc491358ed6a8c3f98626a50611c269dc36439a9 | |
parent | d2b886e569fb6c8621cc2b58873fa9e046d47d60 (diff) | |
download | bcm5719-llvm-b11642bf947d917c7ec284247fe58eb2a25ab4bd.tar.gz bcm5719-llvm-b11642bf947d917c7ec284247fe58eb2a25ab4bd.zip |
Add SFINAE on additional overloads of std::complex functions. Fixes PR19921.
The functions arg, conj, imag, norm, proj, and real have additional overloads
for arguments of integral or floating point types. However these overloads should
not allow conversions to the integral/floating point types, only exact matches.
This patch constrains these functions so they no longer allow conversions.
llvm-svn: 276067
-rw-r--r-- | libcxx/include/complex | 205 | ||||
-rw-r--r-- | libcxx/test/libcxx/test/format.py | 3 | ||||
-rw-r--r-- | libcxx/test/std/numerics/complex.number/cmplx.over/UDT_is_rejected.fail.cpp | 74 |
3 files changed, 136 insertions, 146 deletions
diff --git a/libcxx/include/complex b/libcxx/include/complex index f56138fa2d1..d20a30c01c2 100644 --- a/libcxx/include/complex +++ b/libcxx/include/complex @@ -795,45 +795,41 @@ operator!=(const _Tp& __x, const complex<_Tp>& __y) // 26.3.7 values: -// real +template <class _Tp, bool = is_integral<_Tp>::value, + bool = is_floating_point<_Tp>::value + > +struct __libcpp_complex_overload_traits {}; -template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -_Tp -real(const complex<_Tp>& __c) +// Integral Types +template <class _Tp> +struct __libcpp_complex_overload_traits<_Tp, true, false> { - return __c.real(); -} + typedef double _ValueType; + typedef complex<double> _ComplexType; +}; -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -long double -real(long double __re) +// Floating point types +template <class _Tp> +struct __libcpp_complex_overload_traits<_Tp, false, true> { - return __re; -} + typedef _Tp _ValueType; + typedef complex<_Tp> _ComplexType; +}; -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -double -real(double __re) -{ - return __re; -} +// real template<class _Tp> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -typename enable_if -< - is_integral<_Tp>::value, - double ->::type -real(_Tp __re) +_Tp +real(const complex<_Tp>& __c) { - return __re; + return __c.real(); } +template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -float -real(float __re) +typename __libcpp_complex_overload_traits<_Tp>::_ValueType +real(_Tp __re) { return __re; } @@ -848,35 +844,10 @@ imag(const complex<_Tp>& __c) return __c.imag(); } +template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -long double -imag(long double __re) -{ - return 0; -} - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -double -imag(double __re) -{ - return 0; -} - -template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -typename enable_if -< - is_integral<_Tp>::value, - double ->::type -imag(_Tp __re) -{ - return 0; -} - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -float -imag(float __re) +typename __libcpp_complex_overload_traits<_Tp>::_ValueType +imag(_Tp __re) { return 0; } @@ -901,25 +872,22 @@ arg(const complex<_Tp>& __c) return atan2(__c.imag(), __c.real()); } +template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY -long double -arg(long double __re) +typename enable_if< + is_same<_Tp, long double>::value, + long double +>::type +arg(_Tp __re) { return atan2l(0.L, __re); } -inline _LIBCPP_INLINE_VISIBILITY -double -arg(double __re) -{ - return atan2(0., __re); -} - template<class _Tp> inline _LIBCPP_INLINE_VISIBILITY typename enable_if < - is_integral<_Tp>::value, + is_integral<_Tp>::value || is_same<_Tp, double>::value, double >::type arg(_Tp __re) @@ -927,9 +895,13 @@ arg(_Tp __re) return atan2(0., __re); } +template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY -float -arg(float __re) +typename enable_if< + is_same<_Tp, float>::value, + float +>::type +arg(_Tp __re) { return atan2f(0.F, __re); } @@ -948,37 +920,13 @@ norm(const complex<_Tp>& __c) return __c.real() * __c.real() + __c.imag() * __c.imag(); } +template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY -long double -norm(long double __re) -{ - return __re * __re; -} - -inline _LIBCPP_INLINE_VISIBILITY -double -norm(double __re) -{ - return __re * __re; -} - -template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value, - double ->::type +typename __libcpp_complex_overload_traits<_Tp>::_ValueType norm(_Tp __re) { - return (double)__re * __re; -} - -inline _LIBCPP_INLINE_VISIBILITY -float -norm(float __re) -{ - return __re * __re; + typedef typename __libcpp_complex_overload_traits<_Tp>::_ValueType _ValueType; + return static_cast<_ValueType>(__re) * __re; } // conj @@ -991,38 +939,16 @@ conj(const complex<_Tp>& __c) return complex<_Tp>(__c.real(), -__c.imag()); } +template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY -complex<long double> -conj(long double __re) -{ - return complex<long double>(__re); -} - -inline _LIBCPP_INLINE_VISIBILITY -complex<double> -conj(double __re) -{ - return complex<double>(__re); -} - -template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value, - complex<double> ->::type +typename __libcpp_complex_overload_traits<_Tp>::_ComplexType conj(_Tp __re) { - return complex<double>(__re); + typedef typename __libcpp_complex_overload_traits<_Tp>::_ComplexType _ComplexType; + return _ComplexType(__re); } -inline _LIBCPP_INLINE_VISIBILITY -complex<float> -conj(float __re) -{ - return complex<float>(__re); -} + // proj @@ -1037,44 +963,33 @@ proj(const complex<_Tp>& __c) return __r; } +template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY -complex<long double> -proj(long double __re) -{ - if (isinf(__re)) - __re = abs(__re); - return complex<long double>(__re); -} - -inline _LIBCPP_INLINE_VISIBILITY -complex<double> -proj(double __re) +typename enable_if +< + is_floating_point<_Tp>::value, + typename __libcpp_complex_overload_traits<_Tp>::_ComplexType +>::type +proj(_Tp __re) { if (isinf(__re)) __re = abs(__re); - return complex<double>(__re); + return complex<_Tp>(__re); } -template<class _Tp> +template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value, - complex<double> + typename __libcpp_complex_overload_traits<_Tp>::_ComplexType >::type proj(_Tp __re) { - return complex<double>(__re); + typedef typename __libcpp_complex_overload_traits<_Tp>::_ComplexType _ComplexType; + return _ComplexType(__re); } -inline _LIBCPP_INLINE_VISIBILITY -complex<float> -proj(float __re) -{ - if (isinf(__re)) - __re = abs(__re); - return complex<float>(__re); -} // polar diff --git a/libcxx/test/libcxx/test/format.py b/libcxx/test/libcxx/test/format.py index b9ec2ba2aa7..66553bd8c1a 100644 --- a/libcxx/test/libcxx/test/format.py +++ b/libcxx/test/libcxx/test/format.py @@ -170,7 +170,8 @@ class LibcxxTestFormat(object): extra_flags += ['-fsyntax-only'] if use_verify: extra_flags += ['-Xclang', '-verify', - '-Xclang', '-verify-ignore-unexpected=note'] + '-Xclang', '-verify-ignore-unexpected=note', + '-ferror-limit=1024'] cmd, out, err, rc = self.cxx.compile(source_path, out=os.devnull, flags=extra_flags, disable_ccache=True) diff --git a/libcxx/test/std/numerics/complex.number/cmplx.over/UDT_is_rejected.fail.cpp b/libcxx/test/std/numerics/complex.number/cmplx.over/UDT_is_rejected.fail.cpp new file mode 100644 index 00000000000..6a3ae48d7bb --- /dev/null +++ b/libcxx/test/std/numerics/complex.number/cmplx.over/UDT_is_rejected.fail.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <complex> + +// Test that UDT's convertible to an integral or floating point type do not +// participate in overload resolution. + +#include <complex> +#include <type_traits> +#include <cassert> + +template <class IntT> +struct UDT { + operator IntT() const { return 1; } +}; + +UDT<float> ft; +UDT<double> dt; +UDT<long double> ldt; +UDT<int> it; +UDT<unsigned long> uit; + +int main() +{ + { + std::real(ft); // expected-error {{no matching function}} + std::real(dt); // expected-error {{no matching function}} + std::real(ldt); // expected-error {{no matching function}} + std::real(it); // expected-error {{no matching function}} + std::real(uit); // expected-error {{no matching function}} + } + { + std::imag(ft); // expected-error {{no matching function}} + std::imag(dt); // expected-error {{no matching function}} + std::imag(ldt); // expected-error {{no matching function}} + std::imag(it); // expected-error {{no matching function}} + std::imag(uit); // expected-error {{no matching function}} + } + { + std::arg(ft); // expected-error {{no matching function}} + std::arg(dt); // expected-error {{no matching function}} + std::arg(ldt); // expected-error {{no matching function}} + std::arg(it); // expected-error {{no matching function}} + std::arg(uit); // expected-error {{no matching function}} + } + { + std::norm(ft); // expected-error {{no matching function}} + std::norm(dt); // expected-error {{no matching function}} + std::norm(ldt); // expected-error {{no matching function}} + std::norm(it); // expected-error {{no matching function}} + std::norm(uit); // expected-error {{no matching function}} + } + { + std::conj(ft); // expected-error {{no matching function}} + std::conj(dt); // expected-error {{no matching function}} + std::conj(ldt); // expected-error {{no matching function}} + std::conj(it); // expected-error {{no matching function}} + std::conj(uit); // expected-error {{no matching function}} + } + { + std::proj(ft); // expected-error {{no matching function}} + std::proj(dt); // expected-error {{no matching function}} + std::proj(ldt); // expected-error {{no matching function}} + std::proj(it); // expected-error {{no matching function}} + std::proj(uit); // expected-error {{no matching function}} + } +} |