Author: ericwf Date: Tue Jul 19 19:14:10 2016 New Revision: 276067 URL: http://llvm.org/viewvc/llvm-project?rev=276067&view=rev Log: 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. Added: libcxx/trunk/test/std/numerics/complex.number/cmplx.over/UDT_is_rejected.fail.cpp Modified: libcxx/trunk/include/complex libcxx/trunk/test/libcxx/test/format.py Modified: libcxx/trunk/include/complex URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/complex?rev=276067&r1=276066&r2=276067&view=diff ============================================================================== --- libcxx/trunk/include/complex (original) +++ libcxx/trunk/include/complex Tue Jul 19 19:14:10 2016 @@ -795,6 +795,27 @@ operator!=(const _Tp& __x, const complex // 26.3.7 values: +template <class _Tp, bool = is_integral<_Tp>::value, + bool = is_floating_point<_Tp>::value + > +struct __libcpp_complex_overload_traits {}; + +// Integral Types +template <class _Tp> +struct __libcpp_complex_overload_traits<_Tp, true, false> +{ + typedef double _ValueType; + typedef complex<double> _ComplexType; +}; + +// Floating point types +template <class _Tp> +struct __libcpp_complex_overload_traits<_Tp, false, true> +{ + typedef _Tp _ValueType; + typedef complex<_Tp> _ComplexType; +}; + // real template<class _Tp> @@ -805,35 +826,10 @@ real(const complex<_Tp>& __c) return __c.real(); } +template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -long double -real(long double __re) -{ - return __re; -} - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -double -real(double __re) -{ - return __re; -} - -template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -typename enable_if -< - is_integral<_Tp>::value, - double ->::type -real(_Tp __re) -{ - return __re; -} - -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 Modified: libcxx/trunk/test/libcxx/test/format.py URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/test/format.py?rev=276067&r1=276066&r2=276067&view=diff ============================================================================== --- libcxx/trunk/test/libcxx/test/format.py (original) +++ libcxx/trunk/test/libcxx/test/format.py Tue Jul 19 19:14:10 2016 @@ -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) Added: libcxx/trunk/test/std/numerics/complex.number/cmplx.over/UDT_is_rejected.fail.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/numerics/complex.number/cmplx.over/UDT_is_rejected.fail.cpp?rev=276067&view=auto ============================================================================== --- libcxx/trunk/test/std/numerics/complex.number/cmplx.over/UDT_is_rejected.fail.cpp (added) +++ libcxx/trunk/test/std/numerics/complex.number/cmplx.over/UDT_is_rejected.fail.cpp Tue Jul 19 19:14:10 2016 @@ -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}} + } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits