PR libstdc++/59568 fix error handling for std::complex stream extraction
[gcc.git] / libstdc++-v3 / include / std / complex
index a682247b2a66a5127d555b8048097337be24adec..bfe10347bd3788b12e701fc68b3a6216a0cc7925 100644 (file)
@@ -1,6 +1,6 @@
 // The template and inlines for the -*- C++ -*- complex number classes.
 
-// Copyright (C) 1997-2016 Free Software Foundation, Inc.
+// Copyright (C) 1997-2017 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -492,31 +492,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     basic_istream<_CharT, _Traits>&
     operator>>(basic_istream<_CharT, _Traits>& __is, complex<_Tp>& __x)
     {
-      _Tp __re_x, __im_x;
+      bool __fail = true;
       _CharT __ch;
-      __is >> __ch;
-      if (__ch == '(')
+      if (__is >> __ch)
        {
-         __is >> __re_x >> __ch;
-         if (__ch == ',')
+         if (_Traits::eq(__ch, __is.widen('(')))
            {
-             __is >> __im_x >> __ch;
-             if (__ch == ')')
-               __x = complex<_Tp>(__re_x, __im_x);
-             else
-               __is.setstate(ios_base::failbit);
+             _Tp __u;
+             if (__is >> __u >> __ch)
+               {
+                 const _CharT __rparen = __is.widen(')');
+                 if (_Traits::eq(__ch, __rparen))
+                   {
+                     __x = __u;
+                     __fail = false;
+                   }
+                 else if (_Traits::eq(__ch, __is.widen(',')))
+                   {
+                     _Tp __v;
+                     if (__is >> __v >> __ch)
+                       {
+                         if (_Traits::eq(__ch, __rparen))
+                           {
+                             __x = complex<_Tp>(__u, __v);
+                             __fail = false;
+                           }
+                         else
+                           __is.putback(__ch);
+                       }
+                   }
+                 else
+                   __is.putback(__ch);
+               }
            }
-         else if (__ch == ')')
-           __x = __re_x;
          else
-           __is.setstate(ios_base::failbit);
-       }
-      else
-       {
-         __is.putback(__ch);
-         __is >> __re_x;
-         __x = __re_x;
+           {
+             __is.putback(__ch);
+             _Tp __u;
+             if (__is >> __u)
+               {
+                 __x = __u;
+                 __fail = false;
+               }
+           }
        }
+      if (__fail)
+       __is.setstate(ios_base::failbit);
       return __is;
     }
 
@@ -1840,7 +1861,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type
+    _GLIBCXX_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type
     imag(_Tp)
     { return _Tp(); }
 
@@ -1853,7 +1874,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type
+    _GLIBCXX_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type
     real(_Tp __x)
     { return __x; }
 
@@ -1921,25 +1942,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { return __complex_proj(__z); }
 #endif
 
-  // DR 1137.
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type
+    inline std::complex<typename __gnu_cxx::__promote<_Tp>::__type>
     proj(_Tp __x)
-    { return __x; }
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return std::proj(std::complex<__type>(__x));
+    }
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type
+    inline std::complex<typename __gnu_cxx::__promote<_Tp>::__type>
     conj(_Tp __x)
-    { return __x; }
-
-_GLIBCXX_END_NAMESPACE_VERSION
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return std::complex<__type>(__x, -__type());
+    }
 
 #if __cplusplus > 201103L
 
 inline namespace literals {
 inline namespace complex_literals {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wliteral-suffix"
 #define __cpp_lib_complex_udls 201309
 
   constexpr std::complex<float>
@@ -1966,12 +1990,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   operator""il(unsigned long long __num)
   { return std::complex<long double>{0.0L, static_cast<long double>(__num)}; }
 
-_GLIBCXX_END_NAMESPACE_VERSION
+#pragma GCC diagnostic pop
 } // inline namespace complex_literals
 } // inline namespace literals
 
 #endif // C++14
 
+_GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
 #endif  // C++11