[libcxx-commits] [libcxx] [libc++] Optimize standard streams with sync_with_stdio(false) (PR #209161)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jul 17 00:48:11 PDT 2026


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/209161

>From 059ec6cec9cb06a0be51d521c1945870a3ad2b0d Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 13 Jul 2026 14:28:02 +0200
Subject: [PATCH] [libc++] Optimize standard streams with
 sync_with_stdio(false)

Fixes #21566
---
 libcxx/include/fstream                        |  15 +--
 libcxx/lib/abi/CHANGELOG.TXT                  |  17 +++
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |   5 +-
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |   3 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |   3 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |   5 +-
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |   3 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |   3 +
 ...xxabi.v1.stable.noexceptions.nonew.abilist |   5 +-
 libcxx/src/ios.cpp                            |   7 --
 libcxx/src/iostream.cpp                       | 102 ++++++++++++++----
 .../cin.sync_with_stdio.sh.cpp                |  37 +++++++
 .../clog.sync_with_stdio.sh.cpp               |  29 +++++
 .../cout.sync_with_stdio.sh.cpp               |  27 +++++
 .../wcin.sync_with_stdio.sh.cpp               |  44 ++++++++
 .../wclog.sync_with_stdio.sh.cpp              |  36 +++++++
 .../wcout.sync_with_stdio.sh.cpp              |  34 ++++++
 17 files changed, 340 insertions(+), 35 deletions(-)
 create mode 100644 libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cin.sync_with_stdio.sh.cpp
 create mode 100644 libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/clog.sync_with_stdio.sh.cpp
 create mode 100644 libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cout.sync_with_stdio.sh.cpp
 create mode 100644 libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcin.sync_with_stdio.sh.cpp
 create mode 100644 libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wclog.sync_with_stdio.sh.cpp
 create mode 100644 libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcout.sync_with_stdio.sh.cpp

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 7b84bf6609086..4b276251aa917 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -391,10 +391,10 @@ private:
 
   _LIBCPP_EXPORTED_FROM_ABI friend FILE* __get_ostream_file(ostream&);
 
-  // There are multiple (__)open function, they use different C-API open
-  // function. After that call these functions behave the same. This function
-  // does that part and determines the final return value.
-  _LIBCPP_HIDE_FROM_ABI basic_filebuf* __do_open(FILE* __file, ios_base::openmode __mode) {
+public:
+  // Update the buffer so that __file is considered to be the underlying file and is opened as __mode. This is used in
+  // the open family of functions as well as various iostreams in sync_with_stdio(false) mode.
+  _LIBCPP_HIDE_FROM_ABI basic_filebuf* __adopt_file(FILE* __file, ios_base::openmode __mode) {
     __file_ = __file;
     if (!__file_)
       return nullptr;
@@ -417,6 +417,7 @@ private:
     return this;
   }
 
+private:
   // If the file is already open, switch to unbuffered mode. Otherwise, record
   // the request to use unbuffered mode so that we use that mode when we
   // eventually open the file.
@@ -742,7 +743,7 @@ basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const char*
   if (!__mdstr)
     return nullptr;
 
-  return __do_open(std::fopen(__s, __mdstr), __mode);
+  return __adopt_file(std::fopen(__s, __mdstr), __mode);
 }
 
 template <class _CharT, class _Traits>
@@ -753,7 +754,7 @@ inline basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::__open(in
   if (!__mdstr)
     return nullptr;
 
-  return __do_open(fdopen(__fd, __mdstr), __mode);
+  return __adopt_file(fdopen(__fd, __mdstr), __mode);
 }
 
 #    if _LIBCPP_HAS_OPEN_WITH_WCHAR
@@ -767,7 +768,7 @@ basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const wchar
   if (!__mdstr)
     return nullptr;
 
-  return __do_open(_wfopen(__s, __mdstr), __mode);
+  return __adopt_file(_wfopen(__s, __mdstr), __mode);
 }
 #    endif
 
diff --git a/libcxx/lib/abi/CHANGELOG.TXT b/libcxx/lib/abi/CHANGELOG.TXT
index b09f297eb65ba..567c23717ed60 100644
--- a/libcxx/lib/abi/CHANGELOG.TXT
+++ b/libcxx/lib/abi/CHANGELOG.TXT
@@ -12,6 +12,23 @@ To generate a summary, re-generate the new ABI list using the
 
 New entries should be added directly below the "Version" header.
 
+------------
+Version 24.0
+------------
+
+* [libc++] Optimize standard streams with sync_with_stdio(false)
+
+  This updates the standard streams so that the buffers are replaced with `basic_filebuf`s.
+
+  Fixes #21566
+
+
+  All platforms
+  -------------
+  Symbol added: _ZTINSt3__113basic_filebufIwNS_11char_traitsIwEEEE
+  Symbol added: _ZTSNSt3__113basic_filebufIwNS_11char_traitsIwEEEE
+  Symbol added: _ZTVNSt3__113basic_filebufIwNS_11char_traitsIwEEEE
+
 ------------
 Version 23.0
 ------------
diff --git a/libcxx/lib/abi/i686-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/i686-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
index 414a239757e1c..09999516face2 100644
--- a/libcxx/lib/abi/i686-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/i686-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -10,8 +10,8 @@
 {'is_defined': True, 'name': '_ZNKSt16nested_exception14rethrow_nestedEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt18bad_variant_access4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt19bad_optional_access4whatEv', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNKSt29__bad_variant_access_with_msg4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt20bad_array_new_length4whatEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNKSt29__bad_variant_access_with_msg4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt6__ndk110__time_put8__do_putEPcRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt6__ndk110__time_put8__do_putEPwRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt6__ndk110error_code7messageEv', 'type': 'FUNC'}
@@ -1672,6 +1672,7 @@
 {'is_defined': True, 'name': '_ZTINSt6__ndk112strstreambufE', 'size': 12, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt6__ndk112system_errorE', 'size': 12, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt6__ndk113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 12, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTINSt6__ndk113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 12, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt6__ndk113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt6__ndk113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt6__ndk113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 24, 'type': 'OBJECT'}
@@ -1908,6 +1909,7 @@
 {'is_defined': True, 'name': '_ZTSNSt6__ndk112strstreambufE', 'size': 26, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt6__ndk112system_errorE', 'size': 26, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt6__ndk113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 50, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTSNSt6__ndk113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 50, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt6__ndk113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 50, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt6__ndk113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 50, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt6__ndk113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 50, 'type': 'OBJECT'}
@@ -2143,6 +2145,7 @@
 {'is_defined': True, 'name': '_ZTVNSt6__ndk112strstreambufE', 'size': 64, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt6__ndk112system_errorE', 'size': 20, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt6__ndk113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 64, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTVNSt6__ndk113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 64, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt6__ndk113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt6__ndk113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt6__ndk113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 40, 'type': 'OBJECT'}
diff --git a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index 590c0de8ce20f..d53eeb7532009 100644
--- a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1816,6 +1816,7 @@
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__111__money_putIwEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__112codecvt_baseE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
+{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
@@ -1889,6 +1890,7 @@
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__111__money_putIwEE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__112codecvt_baseE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
+{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
@@ -1963,6 +1965,7 @@
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__110moneypunctIwLb0EEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__110moneypunctIwLb1EEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
+{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
diff --git a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index f4f4ab99ad866..384904f79d20e 100644
--- a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1816,6 +1816,7 @@
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__111__money_putIwEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__112codecvt_baseE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
+{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTINSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
@@ -1889,6 +1890,7 @@
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__111__money_putIwEE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__112codecvt_baseE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
+{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTSNSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
@@ -1963,6 +1965,7 @@
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__110moneypunctIwLb0EEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__110moneypunctIwLb1EEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
+{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZTVNSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
diff --git a/libcxx/lib/abi/x86_64-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
index e1b1e110318fa..8f26fdb0462cb 100644
--- a/libcxx/lib/abi/x86_64-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -10,8 +10,8 @@
 {'is_defined': True, 'name': '_ZNKSt16nested_exception14rethrow_nestedEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt18bad_variant_access4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt19bad_optional_access4whatEv', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNKSt29__bad_variant_access_with_msg4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt20bad_array_new_length4whatEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNKSt29__bad_variant_access_with_msg4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt6__ndk110__time_put8__do_putEPcRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt6__ndk110__time_put8__do_putEPwRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt6__ndk110error_code7messageEv', 'type': 'FUNC'}
@@ -1672,6 +1672,7 @@
 {'is_defined': True, 'name': '_ZTINSt6__ndk112strstreambufE', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt6__ndk112system_errorE', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt6__ndk113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 24, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTINSt6__ndk113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt6__ndk113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt6__ndk113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt6__ndk113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 40, 'type': 'OBJECT'}
@@ -1905,6 +1906,7 @@
 {'is_defined': True, 'name': '_ZTSNSt6__ndk112strstreambufE', 'size': 26, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt6__ndk112system_errorE', 'size': 26, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt6__ndk113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 50, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTSNSt6__ndk113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 50, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt6__ndk113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 50, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt6__ndk113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 50, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt6__ndk113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 50, 'type': 'OBJECT'}
@@ -2137,6 +2139,7 @@
 {'is_defined': True, 'name': '_ZTVNSt6__ndk112strstreambufE', 'size': 128, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt6__ndk112system_errorE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt6__ndk113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 128, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTVNSt6__ndk113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 128, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt6__ndk113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 80, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt6__ndk113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 80, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt6__ndk113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 80, 'type': 'OBJECT'}
diff --git a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
index 11cc8f180e824..0a2858da94a67 100644
--- a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1644,6 +1644,7 @@
 {'is_defined': True, 'name': '_ZTINSt3__112strstreambufE', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt3__112system_errorE', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 24, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTINSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 40, 'type': 'OBJECT'}
@@ -1778,6 +1779,7 @@
 {'is_defined': True, 'name': '_ZTSNSt3__112strstreambufE', 'size': 23, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt3__112system_errorE', 'size': 23, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 47, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTSNSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 47, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 47, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 47, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 47, 'type': 'OBJECT'}
@@ -1916,6 +1918,7 @@
 {'is_defined': True, 'name': '_ZTVNSt3__112strstreambufE', 'size': 128, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__112system_errorE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 128, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTVNSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 128, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 80, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 80, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 80, 'type': 'OBJECT'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
index a28229a9d6e97..903457e983046 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1643,6 +1643,7 @@
 {'is_defined': True, 'name': '_ZTINSt3__112strstreambufE', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt3__112system_errorE', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 24, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTINSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTINSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 40, 'type': 'OBJECT'}
@@ -1777,6 +1778,7 @@
 {'is_defined': True, 'name': '_ZTSNSt3__112strstreambufE', 'size': 23, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt3__112system_errorE', 'size': 23, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 47, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTSNSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 47, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 47, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 47, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 47, 'type': 'OBJECT'}
@@ -1915,6 +1917,7 @@
 {'is_defined': True, 'name': '_ZTVNSt3__112strstreambufE', 'size': 128, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__112system_errorE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 128, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTVNSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 128, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 80, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 80, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 80, 'type': 'OBJECT'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
index 2b69d6dc89138..c24cdf845b489 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
@@ -2002,4 +2002,7 @@
 {'is_defined': True, 'name': '_ZTv0_n24_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZTv0_n24_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZTv0_n24_NSt3__19strstreamD0Ev', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZTv0_n24_NSt3__19strstreamD1Ev', 'type': 'FUNC'}
\ No newline at end of file
+{'is_defined': True, 'name': '_ZTv0_n24_NSt3__19strstreamD1Ev', 'type': 'FUNC'}
+{'name': '_ZTINSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 24, 'type': 'OBJECT', 'is_defined': True}
+{'name': '_ZTSNSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 47, 'type': 'OBJECT', 'is_defined': True}
+{'name': '_ZTVNSt3__113basic_filebufIwNS_11char_traitsIwEEEE', 'size': 128, 'type': 'OBJECT', 'is_defined': True}
\ No newline at end of file
diff --git a/libcxx/src/ios.cpp b/libcxx/src/ios.cpp
index 2e049098740dc..0b728db5b76f9 100644
--- a/libcxx/src/ios.cpp
+++ b/libcxx/src/ios.cpp
@@ -366,13 +366,6 @@ void ios_base::__set_failbit_and_consider_rethrow() {
 #endif // _LIBCPP_HAS_EXCEPTIONS
 }
 
-bool ios_base::sync_with_stdio(bool sync) {
-  static bool previous_state = true;
-  bool r                     = previous_state;
-  previous_state             = sync;
-  return r;
-}
-
 _LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/libcxx/src/iostream.cpp b/libcxx/src/iostream.cpp
index 0393982361456..551eb25f8fe4a 100644
--- a/libcxx/src/iostream.cpp
+++ b/libcxx/src/iostream.cpp
@@ -10,6 +10,7 @@
 
 #include <__memory/construct_at.h>
 #include <__ostream/basic_ostream.h>
+#include <fstream>
 #include <istream>
 
 #define ABI_NAMESPACE_STR _LIBCPP_TOSTRING(_LIBCPP_ABI_NAMESPACE)
@@ -34,21 +35,44 @@ union stream {
   StreamT value;
 };
 
-template <class StreamT, class BufferT>
+template <class StreamT, class SyncBufT, class UnsyncBufT>
 union stream_data {
   constexpr stream_data() {}
   constexpr ~stream_data() {}
   struct {
-    BufferT buffer;
+    union {
+      SyncBufT sync_buffer;
+      UnsyncBufT unsync_buffer;
+    };
     mbstate_t mb;
   };
 };
 
-template <class StreamT, class BufferT>
-void init_stream(FILE* stdstream, stream<StreamT>& stream, stream_data<StreamT, BufferT>& data) {
+template <class StreamT, class SyncBufT, class UnsyncBufT>
+void init_stream(FILE* stdstream, stream<StreamT>& stream, stream_data<StreamT, SyncBufT, UnsyncBufT>& data) {
   data.mb = {};
-  std::construct_at(&data.buffer, stdstream, &data.mb);
-  std::construct_at(&stream.value, &data.buffer);
+  std::construct_at(&data.sync_buffer, stdstream, &data.mb);
+  std::construct_at(&stream.value, &data.sync_buffer);
+}
+
+template <class StreamT, class SyncBufT, class UnsyncBufT>
+void switch_to_sync_stream(FILE* stdstream, stream<StreamT>& stream, stream_data<StreamT, SyncBufT, UnsyncBufT>& data) {
+  data.unsync_buffer.__adopt_file(nullptr, {}); // reset the file, so that basic_filebuf doesn't close standard streams
+  std::destroy_at(&data.unsync_buffer);
+  data.mb = {};
+  std::construct_at(&data.sync_buffer, stdstream, &data.mb);
+  stream.value.rdbuf(&data.sync_buffer);
+}
+
+template <class StreamT, class SyncBufT, class UnsyncBufT>
+void switch_to_unsync_stream(FILE* stdstream,
+                             stream<StreamT>& stream,
+                             stream_data<StreamT, SyncBufT, UnsyncBufT>& data,
+                             ios_base::openmode mode) {
+  std::destroy_at(&data.sync_buffer);
+  std::construct_at(&data.unsync_buffer);
+  data.unsync_buffer.__adopt_file(stdstream, mode);
+  stream.value.rdbuf(&data.unsync_buffer);
 }
 
 #define CHAR_MANGLING_char "D"
@@ -62,29 +86,39 @@ void init_stream(FILE* stdstream, stream<StreamT>& stream, stream_data<StreamT,
 #endif
 
 #ifdef _LIBCPP_ABI_MICROSOFT
-#  define STREAM(StreamT, BufferT, CharT, var)                                                                         \
-    STRING_DATA_CONSTINIT stream_data<StreamT<CharT>, BufferT<CharT>> var##_data;                                      \
+#  define STREAM(StreamT, SyncBufT, UnsyncBufT, CharT, var)                                                            \
+    STRING_DATA_CONSTINIT stream_data<StreamT<CharT>, SyncBufT<CharT>, UnsyncBufT<CharT>> var##_data;                  \
     _LIBCPP_EXPORTED_FROM_ABI STRING_DATA_CONSTINIT stream<StreamT<CharT>> var __asm__(                                \
         "?" #var "@" ABI_NAMESPACE_STR "@std@@3V?$" #StreamT                                                           \
         "@" CHAR_MANGLING(CharT) "U?$char_traits@" CHAR_MANGLING(CharT) "@" ABI_NAMESPACE_STR "@std@@@12 at A")
 #else
-#  define STREAM(StreamT, BufferT, CharT, var)                                                                         \
-    STRING_DATA_CONSTINIT stream_data<StreamT<CharT>, BufferT<CharT>> var##_data;                                      \
+#  define STREAM(StreamT, SyncBufT, UnsyncBufT, CharT, var)                                                            \
+    STRING_DATA_CONSTINIT stream_data<StreamT<CharT>, SyncBufT<CharT>, UnsyncBufT<CharT>> var##_data;                  \
     _LIBCPP_EXPORTED_FROM_ABI STRING_DATA_CONSTINIT stream<StreamT<CharT>> var
 #endif
 
 // These definitions and the declarations in <iostream> technically cause ODR violations, since they have different
 // types (stream_data and {i,o}stream respectively). This means that <iostream> should never be included in this TU.
 
-STREAM(basic_istream, __stdinbuf, char, cin);
-STREAM(basic_ostream, __stdoutbuf, char, cout);
-STREAM(basic_ostream, __stdoutbuf, char, cerr);
-STREAM(basic_ostream, __stdoutbuf, char, clog);
+#if _LIBCPP_HAS_FILESYSTEM
+template <class CharT>
+using unsync_buffer = basic_filebuf<CharT>;
+#else
+// If we don't have access to files we can't treat the standard streams as files either - just save a dummy object in
+// that case.
+template <class>
+using unsync_buffer = char;
+#endif
+
+STREAM(basic_istream, __stdinbuf, unsync_buffer, char, cin);
+STREAM(basic_ostream, __stdoutbuf, unsync_buffer, char, cout);
+STREAM(basic_ostream, __stdoutbuf, unsync_buffer, char, cerr);
+STREAM(basic_ostream, __stdoutbuf, unsync_buffer, char, clog);
 #if _LIBCPP_HAS_WIDE_CHARACTERS
-STREAM(basic_istream, __stdinbuf, wchar_t, wcin);
-STREAM(basic_ostream, __stdoutbuf, wchar_t, wcout);
-STREAM(basic_ostream, __stdoutbuf, wchar_t, wcerr);
-STREAM(basic_ostream, __stdoutbuf, wchar_t, wclog);
+STREAM(basic_istream, __stdinbuf, unsync_buffer, wchar_t, wcin);
+STREAM(basic_ostream, __stdoutbuf, unsync_buffer, wchar_t, wcout);
+STREAM(basic_ostream, __stdoutbuf, unsync_buffer, wchar_t, wcerr);
+STREAM(basic_ostream, __stdoutbuf, unsync_buffer, wchar_t, wclog);
 #endif // _LIBCPP_HAS_WIDE_CHARACTERS
 
 // Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority
@@ -155,5 +189,37 @@ ios_base::Init::Init() {
 
 ios_base::Init::~Init() {}
 
+bool ios_base::sync_with_stdio(bool sync) {
+  static bool previous_state = true;
+  bool r                     = previous_state;
+
+#if _LIBCPP_HAS_FILESYSTEM
+  if (sync != previous_state) {
+    if (sync) {
+      switch_to_sync_stream(stdin, cin, cin_data);
+      switch_to_sync_stream(stdout, cout, cout_data);
+      switch_to_sync_stream(stderr, clog, clog_data);
+#  if _LIBCPP_HAS_WIDE_CHARACTERS
+      switch_to_sync_stream(stdin, wcin, wcin_data);
+      switch_to_sync_stream(stdout, wcout, wcout_data);
+      switch_to_sync_stream(stderr, wclog, wclog_data);
+#  endif
+    } else {
+      switch_to_unsync_stream(stdin, cin, cin_data, ios::in);
+      switch_to_unsync_stream(stdout, cout, cout_data, ios::out);
+      switch_to_unsync_stream(stderr, clog, clog_data, ios::out);
+#  if _LIBCPP_HAS_WIDE_CHARACTERS
+      switch_to_unsync_stream(stdin, wcin, wcin_data, ios::in);
+      switch_to_unsync_stream(stdout, wcout, wcout_data, ios::out);
+      switch_to_unsync_stream(stderr, wclog, wclog_data, ios::out);
+#  endif
+    }
+  }
+#endif // _LIBCPP_HAS_FILESYSTEM
+
+  previous_state = sync;
+  return r;
+}
+
 _LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cin.sync_with_stdio.sh.cpp b/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cin.sync_with_stdio.sh.cpp
new file mode 100644
index 0000000000000..052356449c5ab
--- /dev/null
+++ b/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cin.sync_with_stdio.sh.cpp
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// QEMU does not detect EOF, when reading from stdin
+// "echo -n" suppresses any characters after the output and so the test hangs.
+// https://gitlab.com/qemu-project/qemu/-/issues/1963
+// UNSUPPORTED: LIBCXX-PICOLIBC-FIXME
+
+// This test hangs on Android devices that lack shell_v2, which was added in
+// Android N (API 24).
+// UNSUPPORTED: LIBCXX-ANDROID-FIXME && android-device-api={{2[1-3]}}
+
+// <iostream>
+
+// istream cin;
+
+// RUN: %{build}
+// RUN: echo -n 1234 > %t.input
+// RUN: %{exec} %t.exe < %t.input
+
+#include <cassert>
+#include <iostream>
+
+int main(int, char**) {
+  assert(std::ios::sync_with_stdio(false));
+  assert(!std::ios::sync_with_stdio(true));
+  assert(std::ios::sync_with_stdio(false));
+  int i;
+  std::cin >> i;
+  assert(i == 1234);
+  return 0;
+}
diff --git a/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/clog.sync_with_stdio.sh.cpp b/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/clog.sync_with_stdio.sh.cpp
new file mode 100644
index 0000000000000..ab30dee5f695d
--- /dev/null
+++ b/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/clog.sync_with_stdio.sh.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: LIBCXX-PICOLIBC-FIXME
+
+// <iostream>
+
+// ostream clog;
+
+// RUN: %{build}
+// RUN: %{exec} %t.exe 2> %t.actual
+// RUN: echo -n 1234 > %t.expected
+// RUN: diff %t.expected %t.actual
+
+#include <cassert>
+#include <iostream>
+
+int main(int, char**) {
+  assert(std::ios::sync_with_stdio(false));
+  assert(!std::ios::sync_with_stdio(true));
+  assert(std::ios::sync_with_stdio(false));
+  std::clog << "1234";
+  return 0;
+}
diff --git a/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cout.sync_with_stdio.sh.cpp b/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cout.sync_with_stdio.sh.cpp
new file mode 100644
index 0000000000000..3a94964f09223
--- /dev/null
+++ b/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cout.sync_with_stdio.sh.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <iostream>
+
+// ostream cout;
+
+// RUN: %{build}
+// RUN: %{exec} %t.exe > %t.actual
+// RUN: echo -n 1234 > %t.expected
+// RUN: diff %t.expected %t.actual
+
+#include <cassert>
+#include <iostream>
+
+int main(int, char**) {
+  assert(std::ios::sync_with_stdio(false));
+  assert(!std::ios::sync_with_stdio(true));
+  assert(std::ios::sync_with_stdio(false));
+  std::cout << "1234";
+  return 0;
+}
diff --git a/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcin.sync_with_stdio.sh.cpp b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcin.sync_with_stdio.sh.cpp
new file mode 100644
index 0000000000000..db6c5ba0e8660
--- /dev/null
+++ b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcin.sync_with_stdio.sh.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// QEMU does not detect EOF, when reading from stdin
+// "echo -n" suppresses any characters after the output and so the test hangs.
+// https://gitlab.com/qemu-project/qemu/-/issues/1963
+// UNSUPPORTED: LIBCXX-PICOLIBC-FIXME
+
+// This test hangs on Android devices that lack shell_v2, which was added in
+// Android N (API 24).
+// UNSUPPORTED: LIBCXX-ANDROID-FIXME && android-device-api={{2[1-3]}}
+
+// UNSUPPORTED: no-wide-characters
+
+// <iostream>
+
+// istream wcin;
+
+// Test that we output correctly after setting sync_with_stdio(false).
+// This must be its own test because sync_with_stdio() must be called
+// before any other IO operation for the test to be portable.
+
+// RUN: %{build}
+// RUN: echo -n 1234 > %t.input
+// RUN: %{exec} %t.exe < %t.input
+
+#include <cassert>
+#include <iostream>
+
+int main(int, char**) {
+  // flip-flop the setting to check that construction both ways works as expected
+  assert(std::ios::sync_with_stdio(false));
+  assert(!std::ios::sync_with_stdio(true));
+  assert(std::ios::sync_with_stdio(false));
+  int i;
+  std::wcin >> i;
+  assert(i == 1234);
+  return 0;
+}
diff --git a/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wclog.sync_with_stdio.sh.cpp b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wclog.sync_with_stdio.sh.cpp
new file mode 100644
index 0000000000000..c0a0f299451fb
--- /dev/null
+++ b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wclog.sync_with_stdio.sh.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// XFAIL: LIBCXX-PICOLIBC-FIXME
+
+// UNSUPPORTED: no-wide-characters
+
+// <iostream>
+
+// ostream wclog;
+
+// Test that we output correctly after setting sync_with_stdio(false).
+// This must be its own test because sync_with_stdio() must be called
+// before any other IO operation for the test to be portable.
+
+// RUN: %{build}
+// RUN: %{exec} %t.exe 2> %t.actual
+// RUN: echo -n 1234 > %t.expected
+// RUN: diff %t.expected %t.actual
+
+#include <cassert>
+#include <iostream>
+
+int main(int, char**) {
+  // flip-flop the setting to check that construction both ways works as expected
+  assert(std::ios::sync_with_stdio(false));
+  assert(!std::ios::sync_with_stdio(true));
+  assert(std::ios::sync_with_stdio(false));
+  std::wclog << L"1234";
+  return 0;
+}
diff --git a/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcout.sync_with_stdio.sh.cpp b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcout.sync_with_stdio.sh.cpp
new file mode 100644
index 0000000000000..a2cdc070620b1
--- /dev/null
+++ b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcout.sync_with_stdio.sh.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-wide-characters
+
+// <iostream>
+
+// ostream wcout;
+
+// Test that we output correctly after setting sync_with_stdio(false).
+// This must be its own test because sync_with_stdio() must be called
+// before any other IO operation for the test to be portable.
+
+// RUN: %{build}
+// RUN: %{exec} %t.exe > %t.actual
+// RUN: echo -n 1234 > %t.expected
+// RUN: diff %t.expected %t.actual
+
+#include <cassert>
+#include <iostream>
+
+int main(int, char**) {
+  // flip-flop the setting to check that construction both ways works as expected
+  assert(std::ios::sync_with_stdio(false));
+  assert(!std::ios::sync_with_stdio(true));
+  assert(std::ios::sync_with_stdio(false));
+  std::wcout << L"1234";
+  return 0;
+}



More information about the libcxx-commits mailing list