summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2017-12-13 17:02:14 +0000
committerredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2017-12-13 17:02:14 +0000
commit419381b5d32b5a38c1fe7703dc0400c836106939 (patch)
tree6c85c79c6bd41d1703c081e063e3a6db5195e718
parent7d093718fb5baa4472136086739791194a2f5ec1 (diff)
downloadgcc-419381b5d32b5a38c1fe7703dc0400c836106939.tar.gz
PR libstdc++/59568 fix error handling for std::complex stream extraction
PR libstdc++/59568 * include/std/complex (operator>>): Implement proposed resolution to LWG 2714. Use putback if and only if a character has been successfully extracted but isn't a delimiter. Use ctype::widen and traits::eq when testing if extracted characters match delimiters. * testsuite/26_numerics/complex/dr2714.cc: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@255608 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libstdc++-v3/ChangeLog9
-rw-r--r--libstdc++-v3/include/std/complex59
-rw-r--r--libstdc++-v3/testsuite/26_numerics/complex/dr2714.cc168
3 files changed, 217 insertions, 19 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index c8c93350a60..e4e435dccee 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,12 @@
+2017-12-13 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/59568
+ * include/std/complex (operator>>): Implement proposed resolution to
+ LWG 2714. Use putback if and only if a character has been successfully
+ extracted but isn't a delimiter. Use ctype::widen and traits::eq when
+ testing if extracted characters match delimiters.
+ * testsuite/26_numerics/complex/dr2714.cc: New test.
+
2017-12-12 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/83395
diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex
index 61f8cc1fce3..bfe10347bd3 100644
--- a/libstdc++-v3/include/std/complex
+++ b/libstdc++-v3/include/std/complex
@@ -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;
}
diff --git a/libstdc++-v3/testsuite/26_numerics/complex/dr2714.cc b/libstdc++-v3/testsuite/26_numerics/complex/dr2714.cc
new file mode 100644
index 00000000000..6b35e8adcf9
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/complex/dr2714.cc
@@ -0,0 +1,168 @@
+// Copyright (C) 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
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++98" }
+
+#include <complex>
+#include <sstream>
+#include <complex>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::istringstream in(" 1 (2) ( 2.0 , 0.5 ) ");
+ std::complex<double> c1, c2, c3;
+ in >> c1 >> c2 >> c3;
+ VERIFY( in.good() );
+ VERIFY( c1.real() == 1 && c1.imag() == 0 );
+ VERIFY( c2.real() == 2 && c2.imag() == 0 );
+ VERIFY( c3.real() == 2 && c3.imag() == 0.5 );
+}
+
+void
+test02()
+{
+ std::wistringstream in(L" ( 2.0 , 0.5 ) ");
+ std::complex<double> c;
+ in >> c;
+ VERIFY( in.good() );
+ VERIFY( c.real() == 2.0 && c.imag() == 0.5 );
+}
+
+void
+test03()
+{
+ std::istringstream in;
+ std::complex<double> c(-1, -1);
+ const std::complex<double> c0 = c;
+
+ in.str("a");
+ in >> c;
+ VERIFY( in.fail() );
+ in.clear();
+
+ in.str(" ( ) ");
+ in >> c;
+ VERIFY( in.fail() );
+ in.clear();
+ VERIFY( in.get() == ')' );
+
+ in.str("(,");
+ in >> c;
+ VERIFY( in.fail() );
+ in.clear();
+ VERIFY( in.get() == ',' );
+
+ in.str("(b)");
+ in >> c;
+ VERIFY( in.fail() );
+
+ in.clear();
+ VERIFY( in.get() == 'b' );
+ in.str("( c)");
+
+ in >> c;
+ VERIFY( in.fail() );
+ in.clear();
+ VERIFY( in.get() == 'c' );
+
+ in.str("(99d");
+ in >> c;
+ VERIFY( in.fail() );
+ in.clear();
+ VERIFY( in.get() == 'd' );
+
+ in.str("(99 e");
+ in >> c;
+ VERIFY( in.fail() );
+ in.clear();
+ VERIFY( in.get() == 'e' );
+
+ in.str("(99, f");
+ in >> c;
+ VERIFY( in.fail() );
+ in.clear();
+ VERIFY( in.get() == 'f' );
+
+ in.str("(99, 88g");
+ in >> c;
+ VERIFY( in.fail() );
+ in.clear();
+ VERIFY( in.get() == 'g' );
+
+ in.str("(99, 88 h");
+ in >> c;
+ VERIFY( in.fail() );
+ in.clear();
+ VERIFY( in.get() == 'h' );
+
+ in.str("(99, )");
+ in >> c;
+ VERIFY( in.fail() );
+ in.clear();
+ VERIFY( in.get() == ')' );
+
+ VERIFY( c == c0 );
+}
+
+void
+test04()
+{
+ // PR libstdc++/59568
+ std::istringstream in;
+ std::complex<double> c;
+
+ in.str("");
+ in >> c;
+ VERIFY( in.fail() );
+ VERIFY( in.eof() );
+ in.clear();
+
+ in.str(" ");
+ in >> c;
+ VERIFY( in.fail() );
+ VERIFY( in.eof() );
+ in.clear();
+
+ in.str("(99");
+ in >> c;
+ VERIFY( in.fail() );
+ VERIFY( in.eof() );
+ in.clear();
+
+ in.str("(99,");
+ in >> c;
+ VERIFY( in.fail() );
+ VERIFY( in.eof() );
+ in.clear();
+
+ in.str("(99,99");
+ in >> c;
+ VERIFY( in.fail() );
+ VERIFY( in.eof() );
+ in.clear();
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+}