[libcxx] r276067 - Add SFINAE on additional overloads of std::complex functions. Fixes PR19921.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 19 17:14:10 PDT 2016


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}}
+    }
+}




More information about the cfe-commits mailing list