PR libstdc++/80624 satisfy invariant for char_traits<char16_t>::eof()
authorJonathan Wakely <jwakely@redhat.com>
Fri, 2 Jun 2017 18:35:37 +0000 (19:35 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 2 Jun 2017 18:35:37 +0000 (19:35 +0100)
PR libstdc++/80624
* doc/xml/manual/status_cxx2011.xml: Document to_int_type behaviour.
* include/bits/char_traits.h (char_traits<char16_t>::to_int_type):
Transform eof value to U+FFFD.
* testsuite/21_strings/char_traits/requirements/char16_t/eof.cc: New.
* testsuite/27_io/basic_streambuf/sgetc/char16_t/80624.cc: New.
* testsuite/27_io/basic_streambuf/sputc/char16_t/80624.cc: New.

From-SVN: r248843

libstdc++-v3/ChangeLog
libstdc++-v3/doc/xml/manual/status_cxx2011.xml
libstdc++-v3/include/bits/char_traits.h
libstdc++-v3/testsuite/21_strings/char_traits/requirements/char16_t/eof.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_streambuf/sgetc/char16_t/80624.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_streambuf/sputc/char16_t/80624.cc [new file with mode: 0644]

index 1ad06f1..4d91484 100644 (file)
@@ -1,5 +1,13 @@
 2017-06-02  Jonathan Wakely  <jwakely@redhat.com>
 
+       PR libstdc++/80624
+       * doc/xml/manual/status_cxx2011.xml: Document to_int_type behaviour.
+       * include/bits/char_traits.h (char_traits<char16_t>::to_int_type):
+       Transform eof value to U+FFFD.
+       * testsuite/21_strings/char_traits/requirements/char16_t/eof.cc: New.
+       * testsuite/27_io/basic_streambuf/sgetc/char16_t/80624.cc: New.
+       * testsuite/27_io/basic_streambuf/sputc/char16_t/80624.cc: New.
+
        * libsupc++/Makefile.am: Remove custom targets for files that need to
        be compiled as C++11 or C++14.
        * libsupc++/Makefile.in: Regenerate.
index 705f2ee..0fa4bc0 100644 (file)
@@ -2630,6 +2630,10 @@ particular release.
       <classname>u32streampos</classname> are both synonyms for
       <classname>fpos&lt;mbstate_t&gt;</classname>.
       The function <function>eof</function> returns <code>int_type(-1)</code>.
+      <function>char_traits&lt;char16_t&gt;::to_int_type</function> will
+      transform the "noncharacter" U+FFFF to U+FFFD (REPLACEMENT CHARACTER).
+      This is done to ensure that <function>to_int_type</function> never
+      returns the same value as <function>eof</function>, which is U+FFFF.
    </para>
 
    <para>
index 75db5b8..f19120b 100644 (file)
@@ -507,7 +507,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       static constexpr int_type
       to_int_type(const char_type& __c) noexcept
-      { return int_type(__c); }
+      { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
 
       static constexpr bool
       eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
diff --git a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/char16_t/eof.cc b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/char16_t/eof.cc
new file mode 100644 (file)
index 0000000..05def7f
--- /dev/null
@@ -0,0 +1,31 @@
+// 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-do compile { target c++11 } }
+
+#include <string>
+
+
+constexpr bool not_equal_to_eof(char16_t c)
+{
+  using T = std::char_traits<char16_t>;
+  return T::eq_int_type(T::eof(), T::to_int_type(c)) == false;
+}
+
+// Last two code points of the BMP are noncharacters:
+static_assert(not_equal_to_eof(u'\uFFFE'), "U+FFFE compares unequal to eof");
+static_assert(not_equal_to_eof(u'\uFFFF'), "U+FFFF compares unequal to eof");
diff --git a/libstdc++-v3/testsuite/27_io/basic_streambuf/sgetc/char16_t/80624.cc b/libstdc++-v3/testsuite/27_io/basic_streambuf/sgetc/char16_t/80624.cc
new file mode 100644 (file)
index 0000000..c08c227
--- /dev/null
@@ -0,0 +1,56 @@
+// 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-do run { target c++11 } }
+
+#include <streambuf>
+#include <testsuite_hooks.h>
+
+struct streambuf : std::basic_streambuf<char16_t>
+{
+  basic_streambuf* setbuf(char_type* s, std::streamsize n) override
+  {
+    setp(s, s + n);
+    setg(s, s, s + n);
+    return this;
+  }
+};
+
+void
+test01()
+{
+  using traits = streambuf::traits_type;
+
+  char16_t buf[2] = { streambuf::char_type(-1), streambuf::char_type(-2) };
+  streambuf sb;
+  sb.pubsetbuf(buf, 2);
+
+  streambuf::int_type res;
+
+  res = sb.sbumpc();
+  VERIFY( traits::eq_int_type(res, traits::eof()) == false );
+  res = sb.sbumpc();
+  VERIFY( traits::eq_int_type(res, traits::eof()) == false );
+  res = sb.sbumpc();
+  VERIFY( traits::eq_int_type(res, traits::eof()) == true );
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_streambuf/sputc/char16_t/80624.cc b/libstdc++-v3/testsuite/27_io/basic_streambuf/sputc/char16_t/80624.cc
new file mode 100644 (file)
index 0000000..a2a1917
--- /dev/null
@@ -0,0 +1,59 @@
+// 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-do run { target c++11 } }
+
+#include <streambuf>
+#include <testsuite_hooks.h>
+
+struct streambuf : std::basic_streambuf<char16_t>
+{
+  basic_streambuf* setbuf(char_type* s, std::streamsize n) override
+  {
+    setp(s, s + n);
+    setg(s, s, s + n);
+    return this;
+  }
+};
+
+void
+test01()
+{
+  using traits = streambuf::traits_type;
+
+  char16_t buf[2] = { };
+  streambuf sb;
+  sb.pubsetbuf(buf, 2);
+
+  streambuf::int_type res;
+
+  res = sb.sputc(streambuf::char_type(-1));
+  VERIFY( traits::eq_int_type(res, traits::eof()) == false );
+  res = sb.sputc(streambuf::char_type(-2));
+  VERIFY( traits::eq_int_type(res, traits::eof()) == false );
+  res = sb.sputc(streambuf::char_type(1));
+  VERIFY( traits::eq_int_type(res, traits::eof()) == true );
+
+  VERIFY( buf[0] == streambuf::char_type(-1) );
+  VERIFY( buf[1] == streambuf::char_type(-2) );
+}
+
+int
+main()
+{
+  test01();
+}