]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR libstdc++/59568 don't use putback or update value when extraction fails
authorJonathan Wakely <jwakely@redhat.com>
Thu, 14 Dec 2017 12:01:40 +0000 (12:01 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 14 Dec 2017 12:01:40 +0000 (12:01 +0000)
PR libstdc++/59568
* include/std/complex (operator>>): Only use putback if a character
was successfully extracted and only set the value if a number was
successfully extracted.
* testsuite/26_numerics/complex/inserters_extractors/char/59568.cc:
New test.

From-SVN: r255634

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/complex
libstdc++-v3/testsuite/26_numerics/complex/inserters_extractors/char/59568.cc [new file with mode: 0644]

index cbe0fc5daa89496b1615af699cd9fdcf028c513c..63fcb50596f2786ac1df275e809802ad50a9ad3d 100644 (file)
@@ -1,3 +1,12 @@
+2017-12-14  Jonathan Wakely  <jwakely@redhat.com>
+
+       PR libstdc++/59568
+       * include/std/complex (operator>>): Only use putback if a character
+       was successfully extracted and only set the value if a number was
+       successfully extracted.
+       * testsuite/26_numerics/complex/inserters_extractors/char/59568.cc:
+       New test.
+
 2017-11-11  John David Anglin  <danglin@gcc.gnu.org>
 
        Backport from mainline
index 8f9703a59c817b55e2d06014ce3c6bb67d50a808..1225c6bc44e391d1e4097278ece6cb2a09ccb9a1 100644 (file)
@@ -493,7 +493,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     operator>>(basic_istream<_CharT, _Traits>& __is, complex<_Tp>& __x)
     {
       _Tp __re_x, __im_x;
-      _CharT __ch;
+      _CharT __ch = _CharT();
       __is >> __ch;
       if (__ch == '(') 
        {
@@ -511,11 +511,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          else
            __is.setstate(ios_base::failbit);
        }
-      else 
+      else if (__is)
        {
          __is.putback(__ch);
-         __is >> __re_x;
-         __x = __re_x;
+         if (__is >> __re_x)
+           __x = __re_x;
+         else
+           __is.setstate(ios_base::failbit);
        }
       return __is;
     }
diff --git a/libstdc++-v3/testsuite/26_numerics/complex/inserters_extractors/char/59568.cc b/libstdc++-v3/testsuite/26_numerics/complex/inserters_extractors/char/59568.cc
new file mode 100644 (file)
index 0000000..e292e13
--- /dev/null
@@ -0,0 +1,191 @@
+// 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/>.
+
+#include <complex>
+#include <sstream>
+#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::istringstream in;
+  std::complex<double> c(-1, -1);
+  const std::complex<double> c0 = c;
+
+  in.str("a");
+  in >> c;
+  VERIFY( in.fail() );
+  in.clear();
+  VERIFY( in.get() == 'a' );
+  VERIFY( c == c0 );
+
+  in.str(" ( ) ");
+  in >> c;
+  VERIFY( in.fail() );
+  in.clear();
+  VERIFY( in.get() == ')' );
+  VERIFY( c == c0 );
+
+  in.str("(,");
+  in >> c;
+  VERIFY( in.fail() );
+  in.clear();
+  VERIFY( in.get() == ',' );
+  VERIFY( c == c0 );
+
+  in.str("(b)");
+  in >> c;
+  VERIFY( in.fail() );
+  in.clear();
+  VERIFY( in.get() == 'b' );
+  VERIFY( c == c0 );
+
+  in.str("( c)");
+  in >> c;
+  VERIFY( in.fail() );
+  in.clear();
+  VERIFY( in.get() == 'c' );
+  VERIFY( c == c0 );
+
+  in.str("(99d");
+  in >> c;
+  VERIFY( in.fail() );
+  in.clear();
+  // VERIFY( in.get() == 'd' );
+  VERIFY( c == c0 );
+
+  in.str("(99 e");
+  in >> c;
+  VERIFY( in.fail() );
+  in.clear();
+  // VERIFY( in.get() == 'e' );
+  VERIFY( c == c0 );
+
+  in.str("(99, f");
+  in >> c;
+  VERIFY( in.fail() );
+  in.clear();
+  VERIFY( in.get() == 'f' );
+  VERIFY( c == c0 );
+
+  in.str("(99, 88g");
+  in >> c;
+  VERIFY( in.fail() );
+  in.clear();
+  // VERIFY( in.get() == 'g' );
+  VERIFY( c == c0 );
+
+  in.str("(99, 88 h");
+  in >> c;
+  VERIFY( in.fail() );
+  in.clear();
+  // VERIFY( in.get() == 'h' );
+  VERIFY( c == c0 );
+
+  in.str("(99, )");
+  in >> c;
+  VERIFY( in.fail() );
+  in.clear();
+  VERIFY( in.get() == ')' );
+  VERIFY( c == c0 );
+}
+
+void
+test03()
+{
+  // 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();
+}
+
+void
+test04()
+{
+  // Test noskipws handling
+  std::istringstream in;
+  const char* bad_inputs[] = {
+    " 1", " (2)", "( 2)", "(2 )", "(2 ,3)", "(2,3 )", 0
+  };
+  const std::complex<double> c0(-1, -1);
+  std::complex<double> c;
+  for (int i = 0; bad_inputs[i]; ++i)
+  {
+    c = c0;
+    in.clear();
+    in.str(bad_inputs[i]);
+    in >> std::noskipws >> c;
+    VERIFY( in.fail() );
+    VERIFY( c == c0 );
+
+    in.clear();
+    in.str(bad_inputs[i]);
+    in >> std::skipws >> c;
+    VERIFY( !in.fail() );
+    VERIFY( c != c0 );
+  }
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+}