libstdc++: Add c++2a <syncstream>

Message ID 20201021165344.2412936-1-rodgert@appliantology.com
State Superseded
Headers show
Series
  • libstdc++: Add c++2a <syncstream>
Related show

Commit Message

Thomas Rodgers Oct. 21, 2020, 4:53 p.m.
From: Thomas Rodgers <trodgers@redhat.com>


libstdc++/Changelog:
	libstdc++-v3/doc/doxygen/user.cfg.in (INPUT): Add new header.
	libstdc++-v3/include/Makefile.am (std_headers): Add new header.
	libstdc++-v3/include/Makefile.in: Regenerate.
	libstdc++-v3/include/precompiled/stdc++.h: Include new header.
	libstdc++-v3/include/std/streambuf
        (__detail::__streambuf_core_access): Define.
        (basic_streambuf): Befriend __detail::__streambuf_core_access.
	libstdc++-v3/include/std/syncstream: New header.
	libstdc++-v3/include/std/version: Add __cpp_lib_syncbuf:
	libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc: New test.
	libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc: Likewise.
	libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc:
        Likewise.
	libstdc++-v3/testsuite/27_io/basic_syncbuf/requirements/types.cc:
        Likewise.
	libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc:
        Likewise.
	libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc: Likewise.
	libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc: Likewise.
	libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc:
        Likewise.
	libstdc++-v3/testsuite/27_io/basic_syncstream/requirements/types.cc:
        Likewise.

---
 libstdc++-v3/doc/doxygen/user.cfg.in          |   1 +
 libstdc++-v3/include/Makefile.am              |   1 +
 libstdc++-v3/include/Makefile.in              |   1 +
 libstdc++-v3/include/precompiled/stdc++.h     |   2 +-
 libstdc++-v3/include/std/syncstream           | 279 ++++++++++++++++++
 libstdc++-v3/include/std/version              |   4 +
 .../testsuite/27_io/basic_syncbuf/1.cc        |  28 ++
 .../testsuite/27_io/basic_syncbuf/2.cc        |  27 ++
 .../27_io/basic_syncbuf/basic_ops/1.cc        | 138 +++++++++
 .../27_io/basic_syncbuf/requirements/types.cc |  42 +++
 .../27_io/basic_syncbuf/sync_ops/1.cc         | 130 ++++++++
 .../testsuite/27_io/basic_syncstream/1.cc     |  28 ++
 .../testsuite/27_io/basic_syncstream/2.cc     |  27 ++
 .../27_io/basic_syncstream/basic_ops/1.cc     | 135 +++++++++
 .../basic_syncstream/requirements/types.cc    |  43 +++
 15 files changed, 885 insertions(+), 1 deletion(-)
 create mode 100644 libstdc++-v3/include/std/syncstream
 create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc
 create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc
 create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc
 create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/requirements/types.cc
 create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc
 create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc
 create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc
 create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc
 create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/requirements/types.cc

-- 
2.26.2

Comments

Jeff Law via Gcc-patches Oct. 21, 2020, 5:34 p.m. | #1
On 21/10/20 09:53 -0700, Thomas Rodgers wrote:
>From: Thomas Rodgers <trodgers@redhat.com>

>

>libstdc++/Changelog:

>	libstdc++-v3/doc/doxygen/user.cfg.in (INPUT): Add new header.

>	libstdc++-v3/include/Makefile.am (std_headers): Add new header.

>	libstdc++-v3/include/Makefile.in: Regenerate.

>	libstdc++-v3/include/precompiled/stdc++.h: Include new header.

>	libstdc++-v3/include/std/streambuf

>        (__detail::__streambuf_core_access): Define.

>        (basic_streambuf): Befriend __detail::__streambuf_core_access.


This file is no longer part of the commit, so the server will reject
this changelog. Please ensure the changelog is accurate (the
gcc-verify alias created by contrib/gcc-git-customization.sh can do
that) and push, thanks.
Thomas Rodgers Oct. 21, 2020, 7:39 p.m. | #2
> On Oct 21, 2020, at 10:34 AM, Jonathan Wakely <jwakely@redhat.com> wrote:

> 

> On 21/10/20 09:53 -0700, Thomas Rodgers wrote:

>> From: Thomas Rodgers <trodgers@redhat.com>

>> 

>> libstdc++/Changelog:

>> 	libstdc++-v3/doc/doxygen/user.cfg.in (INPUT): Add new header.

>> 	libstdc++-v3/include/Makefile.am (std_headers): Add new header.

>> 	libstdc++-v3/include/Makefile.in: Regenerate.

>> 	libstdc++-v3/include/precompiled/stdc++.h: Include new header.

>> 	libstdc++-v3/include/std/streambuf

>>       (__detail::__streambuf_core_access): Define.

>>       (basic_streambuf): Befriend __detail::__streambuf_core_access.

> 

> This file is no longer part of the commit, so the server will reject

> this changelog. Please ensure the changelog is accurate (the

> gcc-verify alias created by contrib/gcc-git-customization.sh can do

> that) and push, thanks.

> 


This patch is dependent on the changes to <sstream> so I can’t push until that patch lands.
Jeff Law via Gcc-patches Oct. 29, 2020, 4:18 p.m. | #3
On 21/10/20 09:53 -0700, Thomas Rodgers wrote:
>From: Thomas Rodgers <trodgers@redhat.com>

>

>libstdc++/Changelog:

>	libstdc++-v3/doc/doxygen/user.cfg.in (INPUT): Add new header.

>	libstdc++-v3/include/Makefile.am (std_headers): Add new header.

>	libstdc++-v3/include/Makefile.in: Regenerate.

>	libstdc++-v3/include/precompiled/stdc++.h: Include new header.

>	libstdc++-v3/include/std/streambuf

>        (__detail::__streambuf_core_access): Define.

>        (basic_streambuf): Befriend __detail::__streambuf_core_access.

>	libstdc++-v3/include/std/syncstream: New header.

>	libstdc++-v3/include/std/version: Add __cpp_lib_syncbuf:

>	libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc: New test.

>	libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc: Likewise.

>	libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc:

>        Likewise.

>	libstdc++-v3/testsuite/27_io/basic_syncbuf/requirements/types.cc:

>        Likewise.

>	libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc:

>        Likewise.

>	libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc: Likewise.

>	libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc: Likewise.

>	libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc:

>        Likewise.

>	libstdc++-v3/testsuite/27_io/basic_syncstream/requirements/types.cc:

>        Likewise.

>

>---

> libstdc++-v3/doc/doxygen/user.cfg.in          |   1 +

> libstdc++-v3/include/Makefile.am              |   1 +

> libstdc++-v3/include/Makefile.in              |   1 +

> libstdc++-v3/include/precompiled/stdc++.h     |   2 +-

> libstdc++-v3/include/std/syncstream           | 279 ++++++++++++++++++

> libstdc++-v3/include/std/version              |   4 +

> .../testsuite/27_io/basic_syncbuf/1.cc        |  28 ++

> .../testsuite/27_io/basic_syncbuf/2.cc        |  27 ++

> .../27_io/basic_syncbuf/basic_ops/1.cc        | 138 +++++++++

> .../27_io/basic_syncbuf/requirements/types.cc |  42 +++

> .../27_io/basic_syncbuf/sync_ops/1.cc         | 130 ++++++++

> .../testsuite/27_io/basic_syncstream/1.cc     |  28 ++

> .../testsuite/27_io/basic_syncstream/2.cc     |  27 ++

> .../27_io/basic_syncstream/basic_ops/1.cc     | 135 +++++++++

> .../basic_syncstream/requirements/types.cc    |  43 +++

> 15 files changed, 885 insertions(+), 1 deletion(-)

> create mode 100644 libstdc++-v3/include/std/syncstream

> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc

> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc

> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc

> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/requirements/types.cc

> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc

> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc

> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc

> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc

> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/requirements/types.cc

>

>diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in

>index 9b49a15d31b..320f6dea688 100644

>--- a/libstdc++-v3/doc/doxygen/user.cfg.in

>+++ b/libstdc++-v3/doc/doxygen/user.cfg.in

>@@ -897,6 +897,7 @@ INPUT                  = @srcdir@/doc/doxygen/doxygroups.cc \

>                          include/streambuf \

>                          include/string \

>                          include/string_view \

>+                         include/syncstream \

>                          include/system_error \

>                          include/thread \

>                          include/tuple \

>diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am

>index 28d273924ee..61aaff7a2f4 100644

>--- a/libstdc++-v3/include/Makefile.am

>+++ b/libstdc++-v3/include/Makefile.am

>@@ -73,6 +73,7 @@ std_headers = \

> 	${std_srcdir}/shared_mutex \

> 	${std_srcdir}/span \

> 	${std_srcdir}/sstream \

>+	${std_srcdir}/syncstream \

> 	${std_srcdir}/stack \

> 	${std_srcdir}/stdexcept \

> 	${std_srcdir}/stop_token \

>diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h

>index 7518a98c25a..8899c323a28 100644

>--- a/libstdc++-v3/include/precompiled/stdc++.h

>+++ b/libstdc++-v3/include/precompiled/stdc++.h

>@@ -141,6 +141,6 @@

> #include <ranges>

> #include <span>

> #include <stop_token>

>-// #include <syncstream>

>+#include <syncstream>

> #include <version>

> #endif

>diff --git a/libstdc++-v3/include/std/syncstream b/libstdc++-v3/include/std/syncstream

>new file mode 100644

>index 00000000000..3f78cef1d8d

>--- /dev/null

>+++ b/libstdc++-v3/include/std/syncstream

>@@ -0,0 +1,279 @@

>+// <syncstream> -*- C++ -*-

>+

>+// Copyright (C) 2020 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.

>+

>+// Under Section 7 of GPL version 3, you are granted additional

>+// permissions described in the GCC Runtime Library Exception, version

>+// 3.1, as published by the Free Software Foundation.

>+

>+// You should have received a copy of the GNU General Public License and

>+// a copy of the GCC Runtime Library Exception along with this program;

>+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see

>+// <http://www.gnu.org/licenses/>.

>+

>+/** @file include/syncstream

>+ *  This is a Standard C++ Library header.

>+ */

>+

>+ #ifndef _GLIBCXX_SYNCSTREAM

>+ #define _GLIBCXX_SYNCSTREAM 1


These two lines are indented one column, they shouldn't be.

>+

>+#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI


The _GLIBCXX_USE_CXX11_ABI check needs to come after including at
least one libstdc++ header, because otherwise it's not been set yet.
It gets set to a default value in <bits/c++config.h> so if you check
it before that (or any other header that includes it) has been
included, then it won't be defined.

As discussed, either the entire header needs to be guarded with
#ifdef _GLIBCXX_HAS_GTHREADS or the uses of the mutex need to be
guarded by that (making it usable without threads, even though it does
no synchronization).

>diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version

>index d5d42ed0a72..5542d51087e 100644

>--- a/libstdc++-v3/include/std/version

>+++ b/libstdc++-v3/include/std/version

>@@ -226,6 +226,10 @@

> #define __cpp_lib_span 202002L

> #define __cpp_lib_ssize 201902L

> #define __cpp_lib_starts_ends_with 201711L

>+# ifdef _GLIBCXX_USE_CXX11_ABI


This should be #if not #ifdef, otherwise the  condition is true for
_GLIBCXX_USE_CXX11_ABI=0 as wekk as _GLIBCXX_USE_CXX11_ABI=1

>+// Only supported with cx11-abi

>+#  define __cpp_lib_syncbuf 201803L

>+# endif

> #define __cpp_lib_to_address 201711L

> #define __cpp_lib_to_array 201907L

> #endif


Also several of the tests still do:

#elif __cpp_lib_syncbuf!= 201803L

with no space before the operator.

Patch

diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in
index 9b49a15d31b..320f6dea688 100644
--- a/libstdc++-v3/doc/doxygen/user.cfg.in
+++ b/libstdc++-v3/doc/doxygen/user.cfg.in
@@ -897,6 +897,7 @@  INPUT                  = @srcdir@/doc/doxygen/doxygroups.cc \
                          include/streambuf \
                          include/string \
                          include/string_view \
+                         include/syncstream \
                          include/system_error \
                          include/thread \
                          include/tuple \
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 28d273924ee..61aaff7a2f4 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -73,6 +73,7 @@  std_headers = \
 	${std_srcdir}/shared_mutex \
 	${std_srcdir}/span \
 	${std_srcdir}/sstream \
+	${std_srcdir}/syncstream \
 	${std_srcdir}/stack \
 	${std_srcdir}/stdexcept \
 	${std_srcdir}/stop_token \
diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h
index 7518a98c25a..8899c323a28 100644
--- a/libstdc++-v3/include/precompiled/stdc++.h
+++ b/libstdc++-v3/include/precompiled/stdc++.h
@@ -141,6 +141,6 @@ 
 #include <ranges>
 #include <span>
 #include <stop_token>
-// #include <syncstream>
+#include <syncstream>
 #include <version>
 #endif
diff --git a/libstdc++-v3/include/std/syncstream b/libstdc++-v3/include/std/syncstream
new file mode 100644
index 00000000000..3f78cef1d8d
--- /dev/null
+++ b/libstdc++-v3/include/std/syncstream
@@ -0,0 +1,279 @@ 
+// <syncstream> -*- C++ -*-
+
+// Copyright (C) 2020 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/syncstream
+ *  This is a Standard C++ Library header.
+ */
+
+ #ifndef _GLIBCXX_SYNCSTREAM
+ #define _GLIBCXX_SYNCSTREAM 1
+
+#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
+
+#define __cpp_lib_syncbuf 201803L
+
+#pragma GCC system_header
+
+#include <sstream>
+
+#include <bits/alloc_traits.h>
+#include <bits/allocator.h>
+#include <bits/functexcept.h>
+#include <bits/functional_hash.h>
+#include <bits/std_mutex.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  template<typename _CharT, typename _Traits = char_traits<_CharT>,
+	    typename _Alloc = allocator<_CharT>>
+    class basic_syncbuf : public basic_streambuf<_CharT, _Traits>
+    {
+    public:
+      using char_type = _CharT;
+      using int_type = typename _Traits::int_type;
+      using pos_type = typename _Traits::pos_type;
+      using off_type = typename _Traits::off_type;
+      using traits_type = _Traits;
+      using allocator_type = _Alloc;
+      using streambuf_type = basic_streambuf<_CharT, _Traits>;
+
+      basic_syncbuf()
+      : basic_syncbuf(nullptr, allocator_type{})
+      { }
+
+      explicit
+      basic_syncbuf(streambuf_type* __obuf)
+	: basic_syncbuf(__obuf, allocator_type{})
+      { }
+
+      basic_syncbuf(streambuf_type* __obuf, const allocator_type& __alloc)
+	: _M_wrapped(__obuf)
+	, _M_impl(__alloc)
+	, _M_mtx(__obuf ? &_S_get_mutex(__obuf) : nullptr)
+      { }
+
+      basic_syncbuf(basic_syncbuf&& __other)
+	: _M_wrapped(__other._M_wrapped)
+	, _M_impl(std::move(__other._M_impl))
+	, _M_mtx(__other._M_mtx)
+	, _M_emit_on_sync(__other._M_emit_on_sync)
+	, _M_needs_sync(__other._M_needs_sync)
+      {
+	__other._M_wrapped = nullptr;
+      }
+
+      ~basic_syncbuf()
+      {
+	__try
+	  {
+	    emit();
+	  }
+	__catch (...)
+	  { }
+      }
+
+      basic_syncbuf& operator=(basic_syncbuf&& __other)
+      {
+	if (std::__addressof(__other) != this)
+	  {
+	    emit();
+
+	    _M_impl = std::move(__other._M_impl);
+	    _M_wrapped = __other._M_wrapped; __other._M_wrapped = nullptr;
+	    _M_mtx = __other._M_mtx;
+	    _M_emit_on_sync = __other._M_emit_on_sync;
+	    _M_needs_sync = __other._M_needs_sync;
+	  }
+	return *this;
+      }
+
+      void
+      swap(basic_syncbuf& __other)
+      {
+	if (std::__addressof(__other) != this)
+	  {
+	    std::swap(_M_impl, __other._M_impl);
+	    std::swap(_M_wrapped, __other._M_wrapped);
+	    std::swap(_M_mtx, __other._M_mtx);
+	    std::swap(_M_emit_on_sync, __other._M_emit_on_sync);
+	    std::swap(_M_needs_sync, __other._M_needs_sync);
+	  }
+      }
+
+      bool
+      emit()
+      {
+	if (!_M_wrapped)
+	  return false;
+
+	auto __s = _M_impl.view();
+	if (__s.empty())
+	  return true;
+
+	const lock_guard<mutex> __l(*_M_mtx);
+	auto __xsz = _M_wrapped->sputn(__s.data(), __s.size());
+
+	if (__xsz != __s.size())
+	  return false;
+
+	if (_M_needs_sync)
+	  {
+	    _M_needs_sync = false;
+	    if (_M_wrapped->pubsync() != 0)
+	      return false;
+	  }
+	_M_impl.str("");
+	return true;
+      }
+
+      streambuf_type*
+      get_wrapped() const noexcept
+      { return _M_wrapped; }
+
+      allocator_type get_allocator() const noexcept
+      { return _M_impl.get_allocator(); }
+
+      void
+      set_emit_on_sync(bool __b) noexcept
+      { _M_emit_on_sync = __b; }
+
+    protected:
+      int
+      sync() override
+      {
+	auto __res = _M_impl.pubsync();
+	if (__res == 0)
+	  {
+	    _M_needs_sync = true;
+	    if (_M_emit_on_sync)
+	      return emit() ? 0 : -1;
+	  }
+	return __res;
+      }
+
+      streamsize
+      xsputn(const char_type* __s, streamsize __n) override
+      { return _M_impl.sputn(__s, __n); }
+
+    private:
+      streambuf_type* _M_wrapped;
+
+      using __impl_type = basic_stringbuf<char_type, traits_type,
+					  allocator_type>;
+      __impl_type _M_impl;
+      mutex* _M_mtx;
+
+      bool _M_emit_on_sync = false;
+      bool _M_needs_sync = false;
+
+      // FIXME: This should be put in the .so
+      static mutex&
+      _S_get_mutex(void* __t)
+      {
+	const unsigned char __mask = 0xf;
+	static mutex __m[__mask + 1];
+
+	auto __key = _Hash_impl::hash(__t) & __mask;
+	return __m[__key];
+      }
+    };
+
+  template <typename _CharT, typename _Traits = char_traits<_CharT>,
+	    typename _Alloc = allocator<_CharT>>
+    class basic_osyncstream : public basic_ostream<_CharT, _Traits>
+    {
+      using __ostream_type = basic_ostream<_CharT, _Traits>;
+
+    public:
+      // Types:
+      using char_type = _CharT;
+      using traits_type = _Traits;
+      using allocator_type = _Alloc;
+      using int_type = typename traits_type::int_type;
+      using pos_type = typename traits_type::pos_type;
+      using off_type = typename traits_type::off_type;
+      using syncbuf_type = basic_syncbuf<_CharT, _Traits, _Alloc>;
+      using streambuf_type = typename syncbuf_type::streambuf_type;
+
+    private:
+      syncbuf_type _M_syncbuf;
+
+    public:
+      basic_osyncstream(streambuf_type* __buf, const allocator_type& __a)
+	: _M_syncbuf(__buf, __a)
+      { this->init(std::__addressof(_M_syncbuf)); }
+
+      explicit basic_osyncstream(streambuf_type* __buf)
+	: _M_syncbuf(__buf)
+      { this->init(std::__addressof(_M_syncbuf)); }
+
+      basic_osyncstream(basic_ostream<char_type, traits_type>& __os,
+		        const allocator_type& __a)
+	: basic_osyncstream(__os.rdbuf(), __a)
+      { this->init(std::__addressof(_M_syncbuf)); }
+
+      explicit basic_osyncstream(basic_ostream<char_type, traits_type>& __os)
+	: basic_osyncstream(__os.rdbuf())
+      { this->init(std::__addressof(_M_syncbuf)); }
+
+      basic_osyncstream(basic_osyncstream&& __rhs) noexcept
+	: __ostream_type(std::move(__rhs)),
+	_M_syncbuf(std::move(__rhs._M_syncbuf))
+      { __ostream_type::set_rdbuf(std::__addressof(_M_syncbuf)); }
+
+      ~basic_osyncstream() = default;
+
+      basic_osyncstream& operator=(basic_osyncstream&&) noexcept = default;
+
+      syncbuf_type* rdbuf() const noexcept
+      { return const_cast<syncbuf_type*>(&_M_syncbuf); }
+
+      streambuf_type* get_wrapped() const noexcept
+      { return _M_syncbuf.get_wrapped(); }
+
+      void emit()
+      {
+	if (!_M_syncbuf.emit())
+	  this->setstate(ios_base::failbit);
+      }
+    };
+
+  template <class _CharT, class _Traits, class _Allocator>
+    inline void
+    swap(basic_syncbuf<_CharT, _Traits, _Allocator>& __x,
+	 basic_syncbuf<_CharT, _Traits, _Allocator>& __y) noexcept
+    { __x.swap(__y); }
+
+  using syncbuf = basic_syncbuf<char>;
+  using wsyncbuf = basic_syncbuf<wchar_t>;
+
+  using osyncstream = basic_osyncstream<char>;
+  using wosyncstream = basic_osyncstream<wchar_t>;
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++2a
+#endif	/* _GLIBCXX_SYNCSTREAM */
+
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index d5d42ed0a72..5542d51087e 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -226,6 +226,10 @@ 
 #define __cpp_lib_span 202002L
 #define __cpp_lib_ssize 201902L
 #define __cpp_lib_starts_ends_with 201711L
+# ifdef _GLIBCXX_USE_CXX11_ABI
+// Only supported with cx11-abi
+#  define __cpp_lib_syncbuf 201803L
+# endif
 #define __cpp_lib_to_address 201711L
 #define __cpp_lib_to_array 201907L
 #endif
diff --git a/libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc b/libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc
new file mode 100644
index 00000000000..ebea9becdb3
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc
@@ -0,0 +1,28 @@ 
+// Copyright (C) 2020 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++2a" }
+// { dg-do compile { target c++2a } }
+// { dg-require-effective-target cxx11-abi }
+
+#include <syncstream>
+
+#ifndef __cpp_lib_syncbuf
+# error "Feature-test macro for syncbuf missing in <syncstream>"
+#elif __cpp_lib_syncbuf!= 201803L
+# error "Feature-test macro for syncbuf has wrong value in <syncstream>"
+#endif
diff --git a/libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc b/libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc
new file mode 100644
index 00000000000..43538f89fb8
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc
@@ -0,0 +1,27 @@ 
+// Copyright (C) 2020 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++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <version>
+
+#ifndef __cpp_lib_syncbuf
+# error "Feature-test macro for syncbuf missing in <version>"
+#elif __cpp_lib_syncbuf!= 201803L
+# error "Feature-test macro for syncbuf has wrong value in <version>"
+#endif
diff --git a/libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc b/libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc
new file mode 100644
index 00000000000..98e00dea1f1
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc
@@ -0,0 +1,138 @@ 
+// Copyright (C) 2020 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++2a -pthread" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-effective-target cxx11-abi }
+// { dg-require-gthreads "" }
+
+#include <sstream>
+#include <string_view>
+#include <syncstream>
+
+#include <testsuite_allocator.h>
+#include <testsuite_hooks.h>
+
+void
+test01() // construction
+{
+  {
+    std::syncbuf s1;
+    VERIFY( s1.get_wrapped() == nullptr );
+
+    std::stringbuf b;
+    std::syncbuf s2(&b);
+    VERIFY( s2.get_wrapped() == &b );
+  }
+
+  {
+    using alloc_type = __gnu_test::uneq_allocator<char>;
+    using sbuf_t = std::basic_syncbuf<char, std::char_traits<char>,
+				      alloc_type>;
+
+    sbuf_t b;
+
+    alloc_type aa;
+    sbuf_t s1(&b, aa);
+    VERIFY( aa == s1.get_allocator() );
+
+    alloc_type aaa(42);
+    sbuf_t s2(&b, aaa);
+    VERIFY( aaa == s2.get_allocator() );
+
+    VERIFY( s1.get_allocator() != s2.get_allocator() );
+  }
+}
+
+void
+test02() // moving
+{
+  {
+    std::stringbuf b;
+    std::syncbuf s1(&b);
+
+    std::syncbuf s2(std::move(s1));
+
+    VERIFY( s1.get_wrapped() == nullptr );
+    VERIFY( s2.get_wrapped() == &b );
+  }
+
+  {
+    std::stringbuf b;
+    std::syncbuf s1(&b);
+
+    std::syncbuf s2;
+    s2 = std::move(s1);
+
+    VERIFY( s1.get_wrapped() == nullptr );
+    VERIFY( s2.get_wrapped() == &b );
+  }
+}
+
+void
+test03() // swaping
+{
+  std::stringbuf b;
+  std::syncbuf s1(&b);
+
+  std::syncbuf s2;
+  std::swap(s1, s2);
+
+  VERIFY( s1.get_wrapped() == nullptr );
+  VERIFY( s2.get_wrapped() == &b );
+}
+
+void
+test04() // emitting
+{
+  {
+    std::stringbuf b;
+    std::syncbuf s(&b);
+
+    const std::string_view txt("This is a test");
+    s.sputn(txt.data(), txt.size());
+
+    VERIFY( b.str() != txt );
+    VERIFY( s.pubsync() == 0 );
+    VERIFY( b.str() != txt );
+
+    VERIFY( s.emit() );
+    VERIFY( b.str() == txt );
+  }
+
+  {
+    std::stringbuf b;
+    std::syncbuf s(&b);
+    s.set_emit_on_sync(true);
+
+    const std::string_view txt("This is a test");
+    s.sputn(txt.data(), txt.size());
+
+    VERIFY( s.pubsync() == 0 );
+    VERIFY( b.str() == txt );
+  }
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_syncbuf/requirements/types.cc b/libstdc++-v3/testsuite/27_io/basic_syncbuf/requirements/types.cc
new file mode 100644
index 00000000000..49266b4abf0
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_syncbuf/requirements/types.cc
@@ -0,0 +1,42 @@ 
+// Copyright (C) 2020 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++2a" }
+// { dg-do compile { target c++2a } }
+// { dg-require-effective-target cxx11-abi }
+
+#include <syncstream>
+
+template<typename T>
+  struct type_reqs
+  {
+    using test_type = T;
+    using char_type = test_type::char_type;
+    using int_type = test_type::int_type;
+    using pos_type = test_type::pos_type;
+    using off_Type = test_type::off_type;
+    using traits_type = test_type::traits_type;
+    using allocator_type = test_type::allocator_type;
+    using streambuf_type = test_type::streambuf_type;
+  };
+
+void test01()
+{
+  // Check for required typedefs
+  using test_type = type_reqs<std::osyncstream>;
+  using wtest_type = type_reqs<std::wosyncstream>;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc b/libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc
new file mode 100644
index 00000000000..097da110178
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc
@@ -0,0 +1,130 @@ 
+// Copyright (C) 2020 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++2a -pthread -Wl,--no-demangle" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-effective-target cxx11-abi }
+// { dg-require-gthreads "" }
+
+#include <algorithm>
+#include <atomic>
+#include <chrono>
+#include <sstream>
+#include <string>
+#include <string_view>
+#include <syncstream>
+#include <thread>
+#include <vector>
+#include <unordered_map>
+#include <utility>
+
+#include <testsuite_hooks.h>
+
+int
+main()
+{
+  using namespace std::chrono_literals;
+
+  std::stringbuf b;
+  std::atomic<unsigned> running(0);
+
+  auto const cstr = "This is a test";
+
+  constexpr int ct = 1000;
+  auto const body = [&]{
+    ++running;
+    auto tid = std::this_thread::get_id();
+    std::syncbuf s(&b);
+    for (auto i = 0; i < ct; ++i)
+    {
+      std::stringstream stm;
+      stm << tid << ' ' << cstr << ' ' << i << std::endl;
+      auto sv = stm.view();
+      s.sputn(sv.data(), sv.size());
+      VERIFY( s.emit() );
+    }
+  };
+
+  const auto tct = 8;
+  std::vector<std::thread> ts;
+  ts.reserve(tct);
+
+  for (auto i = 0; i < tct; ++i)
+    ts.emplace_back(std::thread(body));
+
+  do
+  {
+    std::this_thread::sleep_for(100ms);
+  }
+  while (running.load() < tct);
+
+  std::unordered_map<std::string, int> tids;
+  for (auto&& t : ts)
+  {
+    std::stringstream stm;
+    stm << t.get_id();
+    tids.emplace(std::make_pair(stm.str(), 0));
+  };
+
+  for (auto&& t : ts)
+     t.join();
+
+  std::vector<std::string_view> lines;
+  const auto lct = ct * ts.size();
+  lines.reserve(lct);
+
+  std::size_t last = 0;
+  auto sv = b.view();
+  auto p = sv.find('\n');
+  while (p != std::string_view::npos)
+  {
+    lines.emplace_back(sv.substr(last, p - last));
+    last = p+1;
+    p = sv.find('\n', last);
+  }
+  VERIFY( lines.size() == lct );
+
+  auto sep = "";
+  auto i = 0;
+  sv = std::string_view(cstr);
+
+  for (auto&& l : lines)
+  {
+    auto p = l.find(' ');
+    VERIFY( p != std::string_view::npos );
+    std::string tid(l.substr(0, p));
+    ++p;
+
+    VERIFY( l.substr(p, sv.size()) == sv );
+    std::string s(l.substr(++p + sv.size()));
+    std::stringstream stm(s);
+    int n;
+    stm >> n;
+    VERIFY( stm.eof() );
+    VERIFY( n >= 0 && n < ct );
+    auto it = tids.find(tid);
+    VERIFY( it != std::end(tids) );
+    ++(it->second);
+  }
+
+  for (auto const& t : tids)
+  {
+    VERIFY( t.second == ct );
+  }
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc b/libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc
new file mode 100644
index 00000000000..ebea9becdb3
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc
@@ -0,0 +1,28 @@ 
+// Copyright (C) 2020 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++2a" }
+// { dg-do compile { target c++2a } }
+// { dg-require-effective-target cxx11-abi }
+
+#include <syncstream>
+
+#ifndef __cpp_lib_syncbuf
+# error "Feature-test macro for syncbuf missing in <syncstream>"
+#elif __cpp_lib_syncbuf!= 201803L
+# error "Feature-test macro for syncbuf has wrong value in <syncstream>"
+#endif
diff --git a/libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc b/libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc
new file mode 100644
index 00000000000..43538f89fb8
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc
@@ -0,0 +1,27 @@ 
+// Copyright (C) 2020 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++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <version>
+
+#ifndef __cpp_lib_syncbuf
+# error "Feature-test macro for syncbuf missing in <version>"
+#elif __cpp_lib_syncbuf!= 201803L
+# error "Feature-test macro for syncbuf has wrong value in <version>"
+#endif
diff --git a/libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc b/libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc
new file mode 100644
index 00000000000..e2cb6404cbe
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc
@@ -0,0 +1,135 @@ 
+// Copyright (C) 2020 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++2a -pthread" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-effective-target cxx11-abi }
+// { dg-require-gthreads "" }
+
+#include <sstream>
+#include <string_view>
+#include <syncstream>
+#include <testsuite_allocator.h>
+#include <testsuite_hooks.h>
+
+void
+test01() // construction
+{
+  {
+    std::stringbuf b;
+    std::osyncstream s(&b);
+    VERIFY( s.rdbuf() != nullptr );
+    VERIFY( s.get_wrapped() == &b );
+  }
+
+  {
+    std::ostringstream stm;
+    std::osyncstream s(stm);
+    VERIFY( s.get_wrapped() == stm.rdbuf() );
+  }
+
+  {
+    using alloc_type = __gnu_test::uneq_allocator<char>;
+    using sbuf_t = std::basic_syncbuf<char, std::char_traits<char>,
+				      alloc_type>;
+    using stream_t = std::basic_osyncstream<char, std::char_traits<char>,
+					    alloc_type>;
+    using str_t = std::basic_ostringstream<char, std::char_traits<char>,
+                                           alloc_type>;
+    sbuf_t b;
+
+    alloc_type aa;
+    stream_t s1(&b, aa);
+    VERIFY( aa == s1.rdbuf()->get_allocator() );
+
+    alloc_type aaa(42);
+    stream_t s2(&b, aaa);
+    VERIFY( aaa == s2.rdbuf()->get_allocator() );
+
+    VERIFY( s1.rdbuf()->get_allocator() != s2.rdbuf()->get_allocator() );
+
+    str_t stm;
+    stream_t s3(stm, aa);
+    VERIFY( s3.get_wrapped() == stm.rdbuf() );
+    VERIFY( aa == s1.rdbuf()->get_allocator() );
+  }
+}
+
+void
+test02() // moving
+{
+  {
+    std::stringbuf b;
+    std::osyncstream s1(&b);
+
+    std::osyncstream s2(std::move(s1));
+
+    VERIFY( s1.get_wrapped() == nullptr );
+    VERIFY( s2.get_wrapped() == &b );
+  }
+
+  {
+    std::stringbuf b1;
+    std::osyncstream s1(&b1);
+
+    std::stringbuf b2;
+    std::osyncstream s2(&b2);
+    s2 = std::move(s1);
+
+    VERIFY( s1.get_wrapped() == nullptr );
+    VERIFY( s2.get_wrapped() == &b1 );
+  }
+}
+
+void
+test03() // swaping
+{
+  std::stringbuf b1;
+  std::osyncstream s1(&b1);
+  
+  std::stringbuf b2;
+  std::osyncstream s2(&b2);
+
+  std::swap(s1, s2);
+
+  VERIFY( s1.get_wrapped() == &b2 );
+  VERIFY( s2.get_wrapped() == &b1 );
+}
+
+void
+test04() // emitting
+{
+  {
+    std::stringbuf b;
+    std::osyncstream s(&b);
+
+    const std::string_view txt("This is a test");
+    s << txt;
+
+    s.emit();
+    VERIFY( b.str() == txt );
+  }
+}
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_syncstream/requirements/types.cc b/libstdc++-v3/testsuite/27_io/basic_syncstream/requirements/types.cc
new file mode 100644
index 00000000000..dfc0b72efcd
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_syncstream/requirements/types.cc
@@ -0,0 +1,43 @@ 
+// Copyright (C) 2020 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++2a" }
+// { dg-do compile { target c++2a } }
+// { dg-require-effective-target cxx11-abi }
+
+#include <syncstream>
+
+template<typename T>
+  struct type_reqs
+  {
+    using test_type = T;
+    using char_type = test_type::char_type;
+    using int_type = test_type::int_type;
+    using pos_type = test_type::pos_type;
+    using off_Type = test_type::off_type;
+    using traits_type = test_type::traits_type;
+    using allocator_type = test_type::allocator_type;
+    using streambuf_type = test_type::streambuf_type;
+    using syncbuf_type = test_type::syncbuf_type;
+  };
+
+void test01()
+{
+  // Check for required typedefs
+  using test_type = type_reqs<std::osyncstream>;
+  using wtest_type = type_reqs<std::wosyncstream>;
+}