[libcxx-commits] [libcxx] [libc++] Implements LWG3130. (PR #101889)

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Sun Aug 4 06:32:30 PDT 2024


https://github.com/mordante created https://github.com/llvm/llvm-project/pull/101889

This adds addressof at the required places in [input.output]. Some of the new tests failed since string used operator& internally. These have been fixed too.

Note the new fstream tests stream to a basic_string instead of a double. Using a double requires num_get specialization

  num_get<CharT, istreambuf_iterator<CharT, char_traits_operator_hijacker<CharT>>

This facet is not present in the locale database so the conversion would fail due to a missing locale facet. Using basic_string avoids using the locale.

As a drive-by fixes several bugs in the ofstream.cons tests. These tested ifstream instead of ofstream with an open mode.

Implements:
- LWG3130 [input.output] needs many addressof

>From 2d3e10abfbe04f632749897699f670ba13f5d6cb Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Sat, 27 Jul 2024 18:11:24 +0200
Subject: [PATCH] [libc++] Implements LWG3130.

This adds addressof at the required places in [input.output]. Some of the
new tests failed since string used operator& internally. These have been
fixed too.

Note the new fstream tests stream to a basic_string instead of a double.
Using a double requires num_get specialization

  num_get<CharT, istreambuf_iterator<CharT, char_traits_operator_hijacker<CharT>>

This facet is not present in the locale database so the conversion would fail
due to a missing locale facet. Using basic_string avoids using the locale.

As a drive-by fixes several bugs in the ofstream.cons tests. These tested
ifstream instead of ofstream with an open mode.

Implements:
- LWG3130 [input.output] needs many addressof
---
 libcxx/docs/Status/Cxx20Issues.csv            |  2 +-
 libcxx/include/fstream                        | 43 +++++-----
 libcxx/include/ios                            | 11 +--
 libcxx/include/sstream                        | 32 ++++----
 libcxx/include/string                         | 10 +--
 .../fstreams/fstream.cons/default.pass.cpp    |  8 +-
 .../fstreams/fstream.cons/move.pass.cpp       | 26 ++++++
 .../fstreams/fstream.cons/path.pass.cpp       | 24 ++++++
 .../fstreams/fstream.cons/pointer.pass.cpp    | 24 ++++++
 .../fstreams/fstream.cons/string.pass.cpp     | 24 ++++++
 .../fstreams/ifstream.cons/default.pass.cpp   |  8 +-
 .../fstreams/ifstream.cons/move.pass.cpp      | 16 ++++
 .../fstreams/ifstream.cons/path.pass.cpp      | 13 +++
 .../fstreams/ifstream.cons/pointer.pass.cpp   | 13 +++
 .../fstreams/ifstream.cons/string.pass.cpp    | 13 +++
 .../fstreams/ofstream.cons/default.pass.cpp   |  8 +-
 .../fstreams/ofstream.cons/move.pass.cpp      | 28 +++++++
 .../fstreams/ofstream.cons/path.pass.cpp      | 69 +++++++++++++++-
 .../fstreams/ofstream.cons/pointer.pass.cpp   | 80 +++++++++++++++++--
 .../fstreams/ofstream.cons/string.pass.cpp    | 79 ++++++++++++++++--
 .../ios/basic.ios.members/copyfmt.pass.cpp    |  9 +++
 .../istringstream.cons/default.pass.cpp       | 34 +++++++-
 .../istringstream.cons/mode.alloc.pass.cpp    | 15 ++--
 .../istringstream.cons/move.pass.cpp          | 27 +++++++
 .../string-alloc.mode.pass.cpp                | 13 +--
 .../istringstream.cons/string.alloc.pass.cpp  | 14 ++--
 .../string.mode.alloc.pass.cpp                | 14 ++--
 .../string.move.mode.pass.cpp                 | 14 ++++
 .../istringstream.cons/string.pass.cpp        | 56 ++++++++++++-
 .../ostringstream.cons/default.pass.cpp       | 34 +++++++-
 .../ostringstream.cons/mode.alloc.pass.cpp    | 15 ++--
 .../ostringstream.cons/move.pass.cpp          | 27 ++++++-
 .../string-alloc.mode.pass.cpp                | 13 +--
 .../ostringstream.cons/string.alloc.pass.cpp  | 14 ++--
 .../string.mode.alloc.pass.cpp                | 16 ++--
 .../string.move.mode.pass.cpp                 | 25 +++---
 .../ostringstream.cons/string.pass.cpp        | 48 ++++++++++-
 .../stringstream.cons/default.pass.cpp        | 21 ++++-
 .../stringstream.cons/mode.alloc.pass.cpp     | 16 ++--
 .../stringstream.cons/move.pass.cpp           | 35 +++++++-
 .../string-alloc.mode.pass.cpp                | 13 +--
 .../stringstream.cons/string.alloc.pass.cpp   | 14 ++--
 .../string.mode.alloc.pass.cpp                | 15 ++--
 .../string.move.mode.pass.cpp                 | 17 +++-
 .../stringstream.cons/string.pass.cpp         | 32 +++++++-
 .../string.cons/move_alloc.pass.cpp           | 13 +++
 .../string.cons/substr_rvalue.pass.cpp        |  3 +
 .../string_swap/swap.pass.cpp                 |  2 +
 libcxx/test/support/operator_hijacker.h       | 18 ++++-
 libcxx/test/support/test_macros.h             |  6 ++
 50 files changed, 947 insertions(+), 177 deletions(-)

diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv
index d6eb8bc9cf027..84e201276f4ae 100644
--- a/libcxx/docs/Status/Cxx20Issues.csv
+++ b/libcxx/docs/Status/Cxx20Issues.csv
@@ -117,7 +117,7 @@
 "`LWG3127 <https://wg21.link/LWG3127>`__","``basic_osyncstream::rdbuf``\  needs a ``const_cast``\ ","San Diego","|Complete|","18.0",""
 "`LWG3128 <https://wg21.link/LWG3128>`__","``strstream::rdbuf``\  needs a ``const_cast``\ ","San Diego","|Nothing To Do|","",""
 "`LWG3129 <https://wg21.link/LWG3129>`__","``regex_token_iterator``\  constructor uses wrong pointer arithmetic","San Diego","","",""
-"`LWG3130 <https://wg21.link/LWG3130>`__","|sect|\ [input.output] needs many ``addressof``\ ","San Diego","","",""
+"`LWG3130 <https://wg21.link/LWG3130>`__","|sect|\ [input.output] needs many ``addressof``\ ","San Diego","|Complete|","20.0",""
 "`LWG3131 <https://wg21.link/LWG3131>`__","``addressof``\  all the things","San Diego","","",""
 "`LWG3132 <https://wg21.link/LWG3132>`__","Library needs to ban macros named ``expects``\  or ``ensures``\ ","San Diego","|Nothing To Do|","",""
 "`LWG3134 <https://wg21.link/LWG3134>`__","[fund.ts.v3] LFTSv3 contains extraneous [meta] variable templates that should have been deleted by P09961","San Diego","Resolved by `P1210R0 <https://wg21.link/P1210R0>`__","",""
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index ab5ebf8e2c3d3..a77b7ce06f2aa 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -191,6 +191,7 @@ typedef basic_fstream<wchar_t> wfstream;
 #include <__config>
 #include <__fwd/fstream.h>
 #include <__locale>
+#include <__memory/addressof.h>
 #include <__type_traits/enable_if.h>
 #include <__type_traits/is_same.h>
 #include <__utility/move.h>
@@ -1136,11 +1137,12 @@ private:
 };
 
 template <class _CharT, class _Traits>
-inline basic_ifstream<_CharT, _Traits>::basic_ifstream() : basic_istream<char_type, traits_type>(&__sb_) {}
+inline basic_ifstream<_CharT, _Traits>::basic_ifstream()
+    : basic_istream<char_type, traits_type>(std::addressof(__sb_)) {}
 
 template <class _CharT, class _Traits>
 inline basic_ifstream<_CharT, _Traits>::basic_ifstream(const char* __s, ios_base::openmode __mode)
-    : basic_istream<char_type, traits_type>(&__sb_) {
+    : basic_istream<char_type, traits_type>(std::addressof(__sb_)) {
   if (__sb_.open(__s, __mode | ios_base::in) == nullptr)
     this->setstate(ios_base::failbit);
 }
@@ -1148,15 +1150,16 @@ inline basic_ifstream<_CharT, _Traits>::basic_ifstream(const char* __s, ios_base
 #  ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR
 template <class _CharT, class _Traits>
 inline basic_ifstream<_CharT, _Traits>::basic_ifstream(const wchar_t* __s, ios_base::openmode __mode)
-    : basic_istream<char_type, traits_type>(&__sb_) {
+    : basic_istream<char_type, traits_type>(std::addressof(__sb_)) {
   if (__sb_.open(__s, __mode | ios_base::in) == nullptr)
     this->setstate(ios_base::failbit);
 }
 #  endif
 
+// extension
 template <class _CharT, class _Traits>
 inline basic_ifstream<_CharT, _Traits>::basic_ifstream(const string& __s, ios_base::openmode __mode)
-    : basic_istream<char_type, traits_type>(&__sb_) {
+    : basic_istream<char_type, traits_type>(std::addressof(__sb_)) {
   if (__sb_.open(__s, __mode | ios_base::in) == nullptr)
     this->setstate(ios_base::failbit);
 }
@@ -1164,7 +1167,7 @@ inline basic_ifstream<_CharT, _Traits>::basic_ifstream(const string& __s, ios_ba
 template <class _CharT, class _Traits>
 inline basic_ifstream<_CharT, _Traits>::basic_ifstream(basic_ifstream&& __rhs)
     : basic_istream<char_type, traits_type>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
-  this->set_rdbuf(&__sb_);
+  this->set_rdbuf(std::addressof(__sb_));
 }
 
 template <class _CharT, class _Traits>
@@ -1187,7 +1190,7 @@ inline _LIBCPP_HIDE_FROM_ABI void swap(basic_ifstream<_CharT, _Traits>& __x, bas
 
 template <class _CharT, class _Traits>
 inline basic_filebuf<_CharT, _Traits>* basic_ifstream<_CharT, _Traits>::rdbuf() const {
-  return const_cast<basic_filebuf<char_type, traits_type>*>(&__sb_);
+  return const_cast<basic_filebuf<char_type, traits_type>*>(std::addressof(__sb_));
 }
 
 template <class _CharT, class _Traits>
@@ -1293,11 +1296,12 @@ private:
 };
 
 template <class _CharT, class _Traits>
-inline basic_ofstream<_CharT, _Traits>::basic_ofstream() : basic_ostream<char_type, traits_type>(&__sb_) {}
+inline basic_ofstream<_CharT, _Traits>::basic_ofstream()
+    : basic_ostream<char_type, traits_type>(std::addressof(__sb_)) {}
 
 template <class _CharT, class _Traits>
 inline basic_ofstream<_CharT, _Traits>::basic_ofstream(const char* __s, ios_base::openmode __mode)
-    : basic_ostream<char_type, traits_type>(&__sb_) {
+    : basic_ostream<char_type, traits_type>(std::addressof(__sb_)) {
   if (__sb_.open(__s, __mode | ios_base::out) == nullptr)
     this->setstate(ios_base::failbit);
 }
@@ -1305,15 +1309,16 @@ inline basic_ofstream<_CharT, _Traits>::basic_ofstream(const char* __s, ios_base
 #  ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR
 template <class _CharT, class _Traits>
 inline basic_ofstream<_CharT, _Traits>::basic_ofstream(const wchar_t* __s, ios_base::openmode __mode)
-    : basic_ostream<char_type, traits_type>(&__sb_) {
+    : basic_ostream<char_type, traits_type>(std::addressof(__sb_)) {
   if (__sb_.open(__s, __mode | ios_base::out) == nullptr)
     this->setstate(ios_base::failbit);
 }
 #  endif
 
+// extension
 template <class _CharT, class _Traits>
 inline basic_ofstream<_CharT, _Traits>::basic_ofstream(const string& __s, ios_base::openmode __mode)
-    : basic_ostream<char_type, traits_type>(&__sb_) {
+    : basic_ostream<char_type, traits_type>(std::addressof(__sb_)) {
   if (__sb_.open(__s, __mode | ios_base::out) == nullptr)
     this->setstate(ios_base::failbit);
 }
@@ -1321,7 +1326,7 @@ inline basic_ofstream<_CharT, _Traits>::basic_ofstream(const string& __s, ios_ba
 template <class _CharT, class _Traits>
 inline basic_ofstream<_CharT, _Traits>::basic_ofstream(basic_ofstream&& __rhs)
     : basic_ostream<char_type, traits_type>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
-  this->set_rdbuf(&__sb_);
+  this->set_rdbuf(std::addressof(__sb_));
 }
 
 template <class _CharT, class _Traits>
@@ -1344,7 +1349,7 @@ inline _LIBCPP_HIDE_FROM_ABI void swap(basic_ofstream<_CharT, _Traits>& __x, bas
 
 template <class _CharT, class _Traits>
 inline basic_filebuf<_CharT, _Traits>* basic_ofstream<_CharT, _Traits>::rdbuf() const {
-  return const_cast<basic_filebuf<char_type, traits_type>*>(&__sb_);
+  return const_cast<basic_filebuf<char_type, traits_type>*>(std::addressof(__sb_));
 }
 
 template <class _CharT, class _Traits>
@@ -1454,11 +1459,12 @@ private:
 };
 
 template <class _CharT, class _Traits>
-inline basic_fstream<_CharT, _Traits>::basic_fstream() : basic_iostream<char_type, traits_type>(&__sb_) {}
+inline basic_fstream<_CharT, _Traits>::basic_fstream()
+    : basic_iostream<char_type, traits_type>(std::addressof(__sb_)) {}
 
 template <class _CharT, class _Traits>
 inline basic_fstream<_CharT, _Traits>::basic_fstream(const char* __s, ios_base::openmode __mode)
-    : basic_iostream<char_type, traits_type>(&__sb_) {
+    : basic_iostream<char_type, traits_type>(std::addressof(__sb_)) {
   if (__sb_.open(__s, __mode) == nullptr)
     this->setstate(ios_base::failbit);
 }
@@ -1466,7 +1472,7 @@ inline basic_fstream<_CharT, _Traits>::basic_fstream(const char* __s, ios_base::
 #  ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR
 template <class _CharT, class _Traits>
 inline basic_fstream<_CharT, _Traits>::basic_fstream(const wchar_t* __s, ios_base::openmode __mode)
-    : basic_iostream<char_type, traits_type>(&__sb_) {
+    : basic_iostream<char_type, traits_type>(std::addressof(__sb_)) {
   if (__sb_.open(__s, __mode) == nullptr)
     this->setstate(ios_base::failbit);
 }
@@ -1474,15 +1480,16 @@ inline basic_fstream<_CharT, _Traits>::basic_fstream(const wchar_t* __s, ios_bas
 
 template <class _CharT, class _Traits>
 inline basic_fstream<_CharT, _Traits>::basic_fstream(const string& __s, ios_base::openmode __mode)
-    : basic_iostream<char_type, traits_type>(&__sb_) {
+    : basic_iostream<char_type, traits_type>(std::addressof(__sb_)) {
   if (__sb_.open(__s, __mode) == nullptr)
     this->setstate(ios_base::failbit);
 }
 
+// extension
 template <class _CharT, class _Traits>
 inline basic_fstream<_CharT, _Traits>::basic_fstream(basic_fstream&& __rhs)
     : basic_iostream<char_type, traits_type>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
-  this->set_rdbuf(&__sb_);
+  this->set_rdbuf(std::addressof(__sb_));
 }
 
 template <class _CharT, class _Traits>
@@ -1505,7 +1512,7 @@ inline _LIBCPP_HIDE_FROM_ABI void swap(basic_fstream<_CharT, _Traits>& __x, basi
 
 template <class _CharT, class _Traits>
 inline basic_filebuf<_CharT, _Traits>* basic_fstream<_CharT, _Traits>::rdbuf() const {
-  return const_cast<basic_filebuf<char_type, traits_type>*>(&__sb_);
+  return const_cast<basic_filebuf<char_type, traits_type>*>(std::addressof(__sb_));
 }
 
 template <class _CharT, class _Traits>
diff --git a/libcxx/include/ios b/libcxx/include/ios
index d8a3643c7ad50..426838b91e5dc 100644
--- a/libcxx/include/ios
+++ b/libcxx/include/ios
@@ -218,6 +218,7 @@ storage-class-specifier const error_category& iostream_category() noexcept;
 #  include <__fwd/ios.h>
 #  include <__ios/fpos.h>
 #  include <__locale>
+#  include <__memory/addressof.h>
 #  include <__system_error/error_category.h>
 #  include <__system_error/error_code.h>
 #  include <__system_error/error_condition.h>
@@ -621,11 +622,11 @@ protected:
 private:
   basic_ostream<char_type, traits_type>* __tie_;
 
-#if defined(_LIBCPP_ABI_IOS_ALLOW_ARBITRARY_FILL_VALUE)
+#  if defined(_LIBCPP_ABI_IOS_ALLOW_ARBITRARY_FILL_VALUE)
   using _FillType = _FillHelper<traits_type>;
-#else
+#  else
   using _FillType = _SentinelValueFill<traits_type>;
-#endif
+#  endif
   mutable _FillType __fill_;
 };
 
@@ -640,7 +641,7 @@ basic_ios<_CharT, _Traits>::~basic_ios() {}
 template <class _CharT, class _Traits>
 inline _LIBCPP_HIDE_FROM_ABI void basic_ios<_CharT, _Traits>::init(basic_streambuf<char_type, traits_type>* __sb) {
   ios_base::init(__sb);
-  __tie_  = nullptr;
+  __tie_ = nullptr;
   __fill_.__init();
 }
 
@@ -707,7 +708,7 @@ inline _LIBCPP_HIDE_FROM_ABI _CharT basic_ios<_CharT, _Traits>::fill(char_type _
 
 template <class _CharT, class _Traits>
 basic_ios<_CharT, _Traits>& basic_ios<_CharT, _Traits>::copyfmt(const basic_ios& __rhs) {
-  if (this != &__rhs) {
+  if (this != std::addressof(__rhs)) {
     __call_callbacks(erase_event);
     ios_base::copyfmt(__rhs);
     __tie_  = __rhs.__tie_;
diff --git a/libcxx/include/sstream b/libcxx/include/sstream
index 272d8861d59c1..78a7f2d5901d2 100644
--- a/libcxx/include/sstream
+++ b/libcxx/include/sstream
@@ -872,13 +872,14 @@ private:
 
 public:
   // [istringstream.cons] Constructors:
-  _LIBCPP_HIDE_FROM_ABI basic_istringstream() : basic_istream<_CharT, _Traits>(&__sb_), __sb_(ios_base::in) {}
+  _LIBCPP_HIDE_FROM_ABI basic_istringstream()
+      : basic_istream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(ios_base::in) {}
 
   _LIBCPP_HIDE_FROM_ABI explicit basic_istringstream(ios_base::openmode __wch)
-      : basic_istream<_CharT, _Traits>(&__sb_), __sb_(__wch | ios_base::in) {}
+      : basic_istream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__wch | ios_base::in) {}
 
   _LIBCPP_HIDE_FROM_ABI explicit basic_istringstream(const string_type& __s, ios_base::openmode __wch = ios_base::in)
-      : basic_istream<_CharT, _Traits>(&__sb_), __sb_(__s, __wch | ios_base::in) {}
+      : basic_istream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch | ios_base::in) {}
 
 #if _LIBCPP_STD_VER >= 20
   _LIBCPP_HIDE_FROM_ABI basic_istringstream(ios_base::openmode __wch, const _Allocator& __a)
@@ -924,7 +925,7 @@ public:
   basic_istringstream(const basic_istringstream&) = delete;
   _LIBCPP_HIDE_FROM_ABI basic_istringstream(basic_istringstream&& __rhs)
       : basic_istream<_CharT, _Traits>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
-    basic_istream<_CharT, _Traits>::set_rdbuf(&__sb_);
+    basic_istream<_CharT, _Traits>::set_rdbuf(std::addressof(__sb_));
   }
 
   // [istringstream.assign] Assign and swap:
@@ -941,7 +942,7 @@ public:
 
   // [istringstream.members] Member functions:
   _LIBCPP_HIDE_FROM_ABI basic_stringbuf<char_type, traits_type, allocator_type>* rdbuf() const {
-    return const_cast<basic_stringbuf<char_type, traits_type, allocator_type>*>(&__sb_);
+    return const_cast<basic_stringbuf<char_type, traits_type, allocator_type>*>(std::addressof(__sb_));
   }
 
 #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_BUILDING_LIBRARY)
@@ -1007,13 +1008,14 @@ private:
 
 public:
   // [ostringstream.cons] Constructors:
-  _LIBCPP_HIDE_FROM_ABI basic_ostringstream() : basic_ostream<_CharT, _Traits>(&__sb_), __sb_(ios_base::out) {}
+  _LIBCPP_HIDE_FROM_ABI basic_ostringstream()
+      : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(ios_base::out) {}
 
   _LIBCPP_HIDE_FROM_ABI explicit basic_ostringstream(ios_base::openmode __wch)
-      : basic_ostream<_CharT, _Traits>(&__sb_), __sb_(__wch | ios_base::out) {}
+      : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__wch | ios_base::out) {}
 
   _LIBCPP_HIDE_FROM_ABI explicit basic_ostringstream(const string_type& __s, ios_base::openmode __wch = ios_base::out)
-      : basic_ostream<_CharT, _Traits>(&__sb_), __sb_(__s, __wch | ios_base::out) {}
+      : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch | ios_base::out) {}
 
 #if _LIBCPP_STD_VER >= 20
   _LIBCPP_HIDE_FROM_ABI basic_ostringstream(ios_base::openmode __wch, const _Allocator& __a)
@@ -1060,7 +1062,7 @@ public:
   basic_ostringstream(const basic_ostringstream&) = delete;
   _LIBCPP_HIDE_FROM_ABI basic_ostringstream(basic_ostringstream&& __rhs)
       : basic_ostream<_CharT, _Traits>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
-    basic_ostream<_CharT, _Traits>::set_rdbuf(&__sb_);
+    basic_ostream<_CharT, _Traits>::set_rdbuf(std::addressof(__sb_));
   }
 
   // [ostringstream.assign] Assign and swap:
@@ -1078,7 +1080,7 @@ public:
 
   // [ostringstream.members] Member functions:
   _LIBCPP_HIDE_FROM_ABI basic_stringbuf<char_type, traits_type, allocator_type>* rdbuf() const {
-    return const_cast<basic_stringbuf<char_type, traits_type, allocator_type>*>(&__sb_);
+    return const_cast<basic_stringbuf<char_type, traits_type, allocator_type>*>(std::addressof(__sb_));
   }
 
 #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_BUILDING_LIBRARY)
@@ -1145,14 +1147,14 @@ private:
 public:
   // [stringstream.cons] constructors
   _LIBCPP_HIDE_FROM_ABI basic_stringstream()
-      : basic_iostream<_CharT, _Traits>(&__sb_), __sb_(ios_base::in | ios_base::out) {}
+      : basic_iostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(ios_base::in | ios_base::out) {}
 
   _LIBCPP_HIDE_FROM_ABI explicit basic_stringstream(ios_base::openmode __wch)
-      : basic_iostream<_CharT, _Traits>(&__sb_), __sb_(__wch) {}
+      : basic_iostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__wch) {}
 
   _LIBCPP_HIDE_FROM_ABI explicit basic_stringstream(const string_type& __s,
                                                     ios_base::openmode __wch = ios_base::in | ios_base::out)
-      : basic_iostream<_CharT, _Traits>(&__sb_), __sb_(__s, __wch) {}
+      : basic_iostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch) {}
 
 #if _LIBCPP_STD_VER >= 20
   _LIBCPP_HIDE_FROM_ABI basic_stringstream(ios_base::openmode __wch, const _Allocator& __a)
@@ -1201,7 +1203,7 @@ public:
   basic_stringstream(const basic_stringstream&) = delete;
   _LIBCPP_HIDE_FROM_ABI basic_stringstream(basic_stringstream&& __rhs)
       : basic_iostream<_CharT, _Traits>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
-    basic_istream<_CharT, _Traits>::set_rdbuf(&__sb_);
+    basic_istream<_CharT, _Traits>::set_rdbuf(std::addressof(__sb_));
   }
 
   // [stringstream.assign] Assign and swap:
@@ -1218,7 +1220,7 @@ public:
 
   // [stringstream.members] Member functions:
   _LIBCPP_HIDE_FROM_ABI basic_stringbuf<char_type, traits_type, allocator_type>* rdbuf() const {
-    return const_cast<basic_stringbuf<char_type, traits_type, allocator_type>*>(&__sb_);
+    return const_cast<basic_stringbuf<char_type, traits_type, allocator_type>*>(std::addressof(__sb_));
   }
 
 #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_BUILDING_LIBRARY)
diff --git a/libcxx/include/string b/libcxx/include/string
index 7b0cd828704ba..6e93a6230cc2c 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1048,7 +1048,7 @@ public:
       __r_.first()       = __str.__r_.first();
       __str.__r_.first() = __rep();
       __str.__annotate_new(0);
-      if (!__is_long() && this != &__str)
+      if (!__is_long() && this != std::addressof(__str))
         __annotate_new(size());
     }
   }
@@ -2711,7 +2711,7 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr
   __str.__set_short_size(0);
   traits_type::assign(__str.__get_short_pointer()[0], value_type());
 
-  if (__str_was_short && this != &__str)
+  if (__str_was_short && this != std::addressof(__str))
     __str.__annotate_shrink(__str_old_size);
   else
     // ASan annotations: was long, so object memory is unpoisoned as new.
@@ -2725,7 +2725,7 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr
   // invariants hold (so functions without preconditions, such as the assignment operator,
   // can be safely used on the object after it was moved from):"
   // Quote: "v = std::move(v); // the value of v is unspecified"
-  if (!__is_long() && &__str != this)
+  if (!__is_long() && std::addressof(__str) != this)
     // If it is long string, delete was never called on original __str's buffer.
     __annotate_new(__get_short_size());
 }
@@ -3450,13 +3450,13 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
       "swapping non-equal allocators");
   if (!__is_long())
     __annotate_delete();
-  if (this != &__str && !__str.__is_long())
+  if (this != std::addressof(__str) && !__str.__is_long())
     __str.__annotate_delete();
   std::swap(__r_.first(), __str.__r_.first());
   std::__swap_allocator(__alloc(), __str.__alloc());
   if (!__is_long())
     __annotate_new(__get_short_size());
-  if (this != &__str && !__str.__is_long())
+  if (this != std::addressof(__str) && !__str.__is_long())
     __str.__annotate_new(__str.__get_short_size());
 }
 
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/default.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/default.pass.cpp
index 5749de2d1e6a4..d15276b440157 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/default.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/default.pass.cpp
@@ -14,19 +14,25 @@
 // basic_fstream();
 
 #include <fstream>
-#include <type_traits>
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
     {
         std::fstream fs;
     }
+    {
+      std::basic_fstream<char, operator_hijacker_char_traits<char> > fs;
+    }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wfstream fs;
     }
+    {
+      std::basic_fstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs;
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/move.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/move.pass.cpp
index b282e7fc5f6ec..95a04bdfccdbc 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/move.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/move.pass.cpp
@@ -15,8 +15,10 @@
 
 #include <fstream>
 #include <cassert>
+
 #include "test_macros.h"
 #include "platform_support.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
@@ -33,6 +35,18 @@ int main(int, char**)
     }
     std::remove(temp.c_str());
 
+    {
+      std::basic_fstream<char, operator_hijacker_char_traits<char> > fso(
+          temp, std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
+      std::basic_fstream<char, operator_hijacker_char_traits<char> > fs = std::move(fso);
+      std::basic_string<char, operator_hijacker_char_traits<char> > x;
+      fs << "3.25";
+      fs.seekg(0);
+      fs >> x;
+      assert(x == "3.25");
+    }
+    std::remove(temp.c_str());
+
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wfstream fso(temp, std::ios_base::in | std::ios_base::out
@@ -45,6 +59,18 @@ int main(int, char**)
         assert(x == 3.25);
     }
     std::remove(temp.c_str());
+
+    {
+      std::basic_fstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fso(
+          temp, std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
+      std::basic_fstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs = std::move(fso);
+      std::basic_string<wchar_t, operator_hijacker_char_traits<wchar_t> > x;
+      fs << L"3.25";
+      fs.seekg(0);
+      fs >> x;
+      assert(x == L"3.25");
+    }
+    std::remove(temp.c_str());
 #endif
 
   return 0;
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/path.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/path.pass.cpp
index d6bb56d9b78b7..d5a2a8f599721 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/path.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/path.pass.cpp
@@ -27,6 +27,7 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "platform_support.h"
+#include "operator_hijacker.h"
 
 namespace fs = std::filesystem;
 
@@ -72,6 +73,17 @@ int main(int, char**) {
   }
   std::remove(p.string().c_str());
 
+  {
+    std::basic_fstream<char, operator_hijacker_char_traits<char> > fs(
+        p, std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
+    std::basic_string<char, operator_hijacker_char_traits<char> > x;
+    fs << "3.25";
+    fs.seekg(0);
+    fs >> x;
+    assert(x == "3.25");
+  }
+  std::remove(p.string().c_str());
+
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
   {
     std::wfstream fs(p, std::ios_base::in | std::ios_base::out |
@@ -83,6 +95,18 @@ int main(int, char**) {
     assert(x == 3.25);
   }
   std::remove(p.string().c_str());
+
+  {
+    std::basic_fstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs(
+        p, std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
+    std::basic_string<wchar_t, operator_hijacker_char_traits<wchar_t> > x;
+    fs << L"3.25";
+    fs.seekg(0);
+    fs >> x;
+    assert(x == L"3.25");
+  }
+  std::remove(p.string().c_str());
+
 #endif
 
   return 0;
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/pointer.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/pointer.pass.cpp
index 18b22d6b214d9..df7d3b948e327 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/pointer.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/pointer.pass.cpp
@@ -17,8 +17,10 @@
 
 #include <fstream>
 #include <cassert>
+
 #include "test_macros.h"
 #include "platform_support.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
@@ -34,6 +36,17 @@ int main(int, char**)
     }
     std::remove(temp.c_str());
 
+    {
+      std::basic_fstream<char, operator_hijacker_char_traits<char> > fs(
+          temp.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
+      std::basic_string<char, operator_hijacker_char_traits<char> > x;
+      fs << "3.25";
+      fs.seekg(0);
+      fs >> x;
+      assert(x == "3.25");
+    }
+    std::remove(temp.c_str());
+
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wfstream fs(temp.c_str(), std::ios_base::in | std::ios_base::out
@@ -45,6 +58,17 @@ int main(int, char**)
         assert(x == 3.25);
     }
     std::remove(temp.c_str());
+
+    {
+      std::basic_fstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs(
+          temp.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
+      std::basic_string<wchar_t, operator_hijacker_char_traits<wchar_t> > x;
+      fs << L"3.25";
+      fs.seekg(0);
+      fs >> x;
+      assert(x == L"3.25");
+    }
+    std::remove(temp.c_str());
 #endif
 
 #if TEST_STD_VER >= 23
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/string.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/string.pass.cpp
index 80b3fe4f464e9..ca0921a00b9b6 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/string.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/string.pass.cpp
@@ -15,8 +15,10 @@
 
 #include <fstream>
 #include <cassert>
+
 #include "test_macros.h"
 #include "platform_support.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
@@ -33,6 +35,17 @@ int main(int, char**)
     }
     std::remove(temp.c_str());
 
+    {
+      std::basic_fstream<char, operator_hijacker_char_traits<char> > fs(
+          temp, std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
+      std::basic_string<char, operator_hijacker_char_traits<char> > x;
+      fs << "3.25";
+      fs.seekg(0);
+      fs >> x;
+      assert(x == "3.25");
+    }
+    std::remove(temp.c_str());
+
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wfstream fs(temp,
@@ -45,6 +58,17 @@ int main(int, char**)
         assert(x == 3.25);
     }
     std::remove(temp.c_str());
+
+    {
+      std::basic_fstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs(
+          temp, std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
+      std::basic_string<wchar_t, operator_hijacker_char_traits<wchar_t> > x;
+      fs << L"3.25";
+      fs.seekg(0);
+      fs >> x;
+      assert(x == L"3.25");
+    }
+    std::remove(temp.c_str());
 #endif
 
   return 0;
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/default.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/default.pass.cpp
index 043db1581d8ee..70d1efca20c65 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/default.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/default.pass.cpp
@@ -14,19 +14,25 @@
 // basic_ifstream();
 
 #include <fstream>
-#include <type_traits>
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
     {
         std::ifstream fs;
     }
+    {
+      std::basic_ifstream<char, operator_hijacker_char_traits<char> > fs;
+    }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wifstream fs;
     }
+    {
+      std::basic_ifstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs;
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/move.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/move.pass.cpp
index f21943a56a0dd..81ec800954cc2 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/move.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/move.pass.cpp
@@ -17,8 +17,10 @@
 
 #include <fstream>
 #include <cassert>
+#include <ios>
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
@@ -29,6 +31,13 @@ int main(int, char**)
         fs >> x;
         assert(x == 3.25);
     }
+    {
+      std::basic_ifstream<char, operator_hijacker_char_traits<char> > fso("test.dat");
+      std::basic_ifstream<char, operator_hijacker_char_traits<char> > fs = std::move(fso);
+      std::basic_string<char, operator_hijacker_char_traits<char> > x;
+      fs >> x;
+      assert(x == "3.25");
+    }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wifstream fso("test.dat");
@@ -37,6 +46,13 @@ int main(int, char**)
         fs >> x;
         assert(x == 3.25);
     }
+    {
+      std::basic_ifstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fso("test.dat");
+      std::basic_ifstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs = std::move(fso);
+      std::basic_string<wchar_t, operator_hijacker_char_traits<wchar_t> > x;
+      fs >> x;
+      assert(x == L"3.25");
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/path.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/path.pass.cpp
index 792b65615679a..630aac10eb384 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/path.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/path.pass.cpp
@@ -28,6 +28,7 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "operator_hijacker.h"
 
 namespace fs = std::filesystem;
 
@@ -75,6 +76,12 @@ int main(int, char**) {
     fs >> x;
     assert(x == 3.25);
   }
+  {
+    std::basic_ifstream<char, operator_hijacker_char_traits<char>> fs(fs::path("test.dat"));
+    std::basic_string<char, operator_hijacker_char_traits<char> > x;
+    fs >> x;
+    assert(x == "3.25");
+  }
   // std::ifstream(const fs::path&, std::ios_base::openmode) is tested in
   // test/std/input.output/file.streams/fstreams/ofstream.cons/string.pass.cpp
   // which creates writable files.
@@ -86,6 +93,12 @@ int main(int, char**) {
     fs >> x;
     assert(x == 3.25);
   }
+  {
+    std::basic_ifstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs(fs::path("test.dat"));
+    std::basic_string<wchar_t, operator_hijacker_char_traits<wchar_t> > x;
+    fs >> x;
+    assert(x == L"3.25");
+  }
   // std::wifstream(const fs::path&, std::ios_base::openmode) is tested in
   // test/std/input.output/file.streams/fstreams/ofstream.cons/string.pass.cpp
   // which creates writable files.
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/pointer.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/pointer.pass.cpp
index bd0880477ff80..6bbe6f1ff7754 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/pointer.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/pointer.pass.cpp
@@ -19,6 +19,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
@@ -28,6 +29,12 @@ int main(int, char**)
         fs >> x;
         assert(x == 3.25);
     }
+    {
+      std::basic_ifstream<char, operator_hijacker_char_traits<char> > fs("test.dat");
+      std::basic_string<char, operator_hijacker_char_traits<char> > x;
+      fs >> x;
+      assert(x == "3.25");
+    }
     // std::ifstream(const char*, std::ios_base::openmode) is tested in
     // test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp
     // which creates writable files.
@@ -39,6 +46,12 @@ int main(int, char**)
         fs >> x;
         assert(x == 3.25);
     }
+    {
+      std::basic_ifstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs("test.dat");
+      std::basic_string<wchar_t, operator_hijacker_char_traits<wchar_t> > x;
+      fs >> x;
+      assert(x == L"3.25");
+    }
     // std::wifstream(const char*, std::ios_base::openmode) is tested in
     // test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp
     // which creates writable files.
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/string.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/string.pass.cpp
index ae7976b1a0581..e1a9b53da1348 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/string.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/string.pass.cpp
@@ -19,6 +19,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
@@ -28,6 +29,12 @@ int main(int, char**)
         fs >> x;
         assert(x == 3.25);
     }
+    {
+      std::basic_ifstream<char, operator_hijacker_char_traits<char> > fs(std::string("test.dat"));
+      std::basic_string<char, operator_hijacker_char_traits<char> > x;
+      fs >> x;
+      assert(x == "3.25");
+    }
     // std::ifstream(const std::string&, std::ios_base::openmode) is tested in
     // test/std/input.output/file.streams/fstreams/ofstream.cons/string.pass.cpp
     // which creates writable files.
@@ -39,6 +46,12 @@ int main(int, char**)
         fs >> x;
         assert(x == 3.25);
     }
+    {
+      std::basic_ifstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs(std::string("test.dat"));
+      std::basic_string<wchar_t, operator_hijacker_char_traits<wchar_t> > x;
+      fs >> x;
+      assert(x == L"3.25");
+    }
     // std::wifstream(const std::string&, std::ios_base::openmode) is tested in
     // test/std/input.output/file.streams/fstreams/ofstream.cons/string.pass.cpp
     // which creates writable files.
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/default.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/default.pass.cpp
index 347013312a343..a7b0918f79365 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/default.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/default.pass.cpp
@@ -14,19 +14,25 @@
 // basic_ofstream();
 
 #include <fstream>
-#include <type_traits>
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
     {
         std::ofstream fs;
     }
+    {
+      std::basic_ofstream<char, operator_hijacker_char_traits<char> > fs;
+    }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wofstream fs;
     }
+    {
+      std::basic_fstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs;
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/move.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/move.pass.cpp
index a06ad43de87f6..ec02fa2621c19 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/move.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/move.pass.cpp
@@ -15,8 +15,10 @@
 
 #include <fstream>
 #include <cassert>
+
 #include "test_macros.h"
 #include "platform_support.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
@@ -34,6 +36,19 @@ int main(int, char**)
     }
     std::remove(temp.c_str());
 
+    {
+      std::basic_ofstream<char, operator_hijacker_char_traits<char> > fso(temp.c_str());
+      std::basic_ofstream<char, operator_hijacker_char_traits<char> > fs = std::move(fso);
+      fs << "3.25";
+    }
+    {
+      std::ifstream fs(temp.c_str());
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
+    }
+    std::remove(temp.c_str());
+
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wofstream fso(temp.c_str());
@@ -47,6 +62,19 @@ int main(int, char**)
         assert(x == 3.25);
     }
     std::remove(temp.c_str());
+
+    {
+      std::basic_ofstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fso(temp.c_str());
+      std::basic_ofstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs = std::move(fso);
+      fs << L"3.25";
+    }
+    {
+      std::wifstream fs(temp.c_str());
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
+    }
+    std::remove(temp.c_str());
 #endif
 
   return 0;
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/path.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/path.pass.cpp
index 602bdadd85813..c62c13d318f13 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/path.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/path.pass.cpp
@@ -16,7 +16,7 @@
 // class basic_ofstream
 
 // template<class T>
-// explicit basic_ifstream(const T& s, ios_base::openmode mode = ios_base::in); // Since C++17
+// explicit basic_ofstream(const T& s, ios_base::openmode mode = ios_base::out); // Since C++17
 // Constraints: is_same_v<T, filesystem::path> is true
 
 #include <cassert>
@@ -25,6 +25,7 @@
 #include <type_traits>
 
 #include "platform_support.h"
+#include "operator_hijacker.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 
@@ -60,7 +61,6 @@ static_assert(test_non_convert_to_path<char16_t>());
 static_assert(test_non_convert_to_path<char32_t>());
 
 int main(int, char**) {
-  fs::path p = get_temp_file_name();
   {
     static_assert(!std::is_convertible<fs::path, std::ofstream>::value,
                   "ctor should be explicit");
@@ -68,6 +68,7 @@ int main(int, char**) {
                                         std::ios_base::openmode>::value,
                   "");
   }
+  fs::path p = get_temp_file_name();
   {
     std::ofstream stream(p);
     stream << 3.25;
@@ -78,8 +79,38 @@ int main(int, char**) {
     stream >> x;
     assert(x == 3.25);
   }
+  std::remove(p.string().c_str());
+
+  {
+    std::basic_ofstream<char, operator_hijacker_char_traits<char> > stream(p);
+    stream << "3.25";
+  }
+  {
+    std::ifstream stream(p);
+    double x = 0;
+    stream >> x;
+    assert(x == 3.25);
+  }
+  std::remove(p.string().c_str());
+
+  {
+    std::ofstream stream(p, std::ios_base::out);
+    stream << 3.25;
+  }
+  {
+    std::ifstream stream(p);
+    double x = 0;
+    stream >> x;
+    assert(x == 3.25);
+  }
+  std::remove(p.string().c_str());
+
+  {
+    std::basic_ofstream<char, operator_hijacker_char_traits<char> > stream(p, std::ios_base::out);
+    stream << "3.25";
+  }
   {
-    std::ifstream stream(p, std::ios_base::out);
+    std::ifstream stream(p);
     double x = 0;
     stream >> x;
     assert(x == 3.25);
@@ -97,8 +128,38 @@ int main(int, char**) {
     stream >> x;
     assert(x == 3.25);
   }
+  std::remove(p.string().c_str());
+
+  {
+    std::basic_ofstream<wchar_t, operator_hijacker_char_traits<wchar_t> > stream(p);
+    stream << L"3.25";
+  }
+  {
+    std::wifstream stream(p);
+    double x = 0;
+    stream >> x;
+    assert(x == 3.25);
+  }
+  std::remove(p.string().c_str());
+
   {
-    std::wifstream stream(p, std::ios_base::out);
+    std::wofstream stream(p, std::ios_base::out);
+    stream << 3.25;
+  }
+  {
+    std::wifstream stream(p);
+    double x = 0;
+    stream >> x;
+    assert(x == 3.25);
+  }
+  std::remove(p.string().c_str());
+
+  {
+    std::basic_ofstream<wchar_t, operator_hijacker_char_traits<wchar_t> > stream(p, std::ios_base::out);
+    stream << L"3.25";
+  }
+  {
+    std::wifstream stream(p);
     double x = 0;
     stream >> x;
     assert(x == 3.25);
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp
index 23bd07a6560e8..af43ffdbf8006 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp
@@ -17,12 +17,16 @@
 
 #include <fstream>
 #include <cassert>
+#include <ios>
+
 #include "test_macros.h"
+#include "operator_hijacker.h"
 #include "platform_support.h"
 
 int main(int, char**)
 {
     std::string temp = get_temp_file_name();
+
     {
         std::ofstream fs(temp.c_str());
         fs << 3.25;
@@ -33,14 +37,43 @@ int main(int, char**)
         fs >> x;
         assert(x == 3.25);
     }
+    std::remove(temp.c_str());
+
     {
-        std::ifstream fs(temp.c_str(), std::ios_base::out);
-        double x = 0;
-        fs >> x;
-        assert(x == 3.25);
+      std::basic_ofstream<char, operator_hijacker_char_traits<char> > fs(temp.c_str());
+      fs << "3.25";
+    }
+    {
+      std::ifstream fs(temp.c_str());
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
+    }
+    std::remove(temp.c_str());
+
+    {
+      std::ofstream fs(temp.c_str(), std::ios_base::out);
+      fs << 3.25;
+    }
+    {
+      std::ifstream fs(temp.c_str());
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
     }
     std::remove(temp.c_str());
 
+    {
+      std::basic_ofstream<char, operator_hijacker_char_traits<char> > fs(temp.c_str(), std::ios_base::out);
+      fs << "3.25";
+    }
+    {
+      std::ifstream fs(temp.c_str());
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
+    }
+    std::remove(temp.c_str());
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wofstream fs(temp.c_str());
@@ -52,13 +85,44 @@ int main(int, char**)
         fs >> x;
         assert(x == 3.25);
     }
+    std::remove(temp.c_str());
+
     {
-        std::wifstream fs(temp.c_str(), std::ios_base::out);
-        double x = 0;
-        fs >> x;
-        assert(x == 3.25);
+      std::basic_ofstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs(temp.c_str());
+      fs << L"3.25";
+    }
+    {
+      std::ifstream fs(temp.c_str());
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
+    }
+    std::remove(temp.c_str());
+
+    {
+      std::wofstream fs(temp.c_str(), std::ios_base::out);
+      fs << 3.25;
+    }
+    {
+      std::wifstream fs(temp.c_str());
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
+    }
+    std::remove(temp.c_str());
+
+    {
+      std::basic_ofstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs(temp.c_str(), std::ios_base::out);
+      fs << L"3.25";
+    }
+    {
+      std::ifstream fs(temp.c_str());
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
     }
     std::remove(temp.c_str());
+
 #endif
 
 #if TEST_STD_VER >= 23
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/string.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/string.pass.cpp
index 4c0823e2574aa..33a7e9b2b6f50 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/string.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/string.pass.cpp
@@ -15,12 +15,16 @@
 
 #include <fstream>
 #include <cassert>
+#include <ios>
+
 #include "test_macros.h"
+#include "operator_hijacker.h"
 #include "platform_support.h"
 
 int main(int, char**)
 {
     std::string temp = get_temp_file_name();
+
     {
         std::ofstream fs(temp);
         fs << 3.25;
@@ -31,14 +35,43 @@ int main(int, char**)
         fs >> x;
         assert(x == 3.25);
     }
+    std::remove(temp.c_str());
+
     {
-        std::ifstream fs(temp, std::ios_base::out);
-        double x = 0;
-        fs >> x;
-        assert(x == 3.25);
+      std::basic_ofstream<char, operator_hijacker_char_traits<char> > fs(temp);
+      fs << "3.25";
+    }
+    {
+      std::ifstream fs(temp);
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
+    }
+    std::remove(temp.c_str());
+
+    {
+      std::ofstream fs(temp, std::ios_base::out);
+      fs << 3.25;
+    }
+    {
+      std::ifstream fs(temp);
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
     }
     std::remove(temp.c_str());
 
+    {
+      std::basic_ofstream<char, operator_hijacker_char_traits<char> > fs(temp, std::ios_base::out);
+      fs << "3.25";
+    }
+    {
+      std::ifstream fs(temp);
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
+    }
+    std::remove(temp.c_str());
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wofstream fs(temp);
@@ -50,11 +83,41 @@ int main(int, char**)
         fs >> x;
         assert(x == 3.25);
     }
+    std::remove(temp.c_str());
+
     {
-        std::wifstream fs(temp, std::ios_base::out);
-        double x = 0;
-        fs >> x;
-        assert(x == 3.25);
+      std::basic_ofstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs(temp);
+      fs << L"3.25";
+    }
+    {
+      std::wifstream fs(temp);
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
+    }
+    std::remove(temp.c_str());
+
+    {
+      std::wofstream fs(temp, std::ios_base::out);
+      fs << 3.25;
+    }
+    {
+      std::wifstream fs(temp);
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
+    }
+    std::remove(temp.c_str());
+
+    {
+      std::basic_ofstream<wchar_t, operator_hijacker_char_traits<wchar_t> > fs(temp, std::ios_base::out);
+      fs << L"3.25";
+    }
+    {
+      std::wifstream fs(temp);
+      double x = 0;
+      fs >> x;
+      assert(x == 3.25);
     }
     std::remove(temp.c_str());
 #endif
diff --git a/libcxx/test/std/input.output/iostreams.base/ios/basic.ios.members/copyfmt.pass.cpp b/libcxx/test/std/input.output/iostreams.base/ios/basic.ios.members/copyfmt.pass.cpp
index 949c87e0b832c..d78f7df8f6b5e 100644
--- a/libcxx/test/std/input.output/iostreams.base/ios/basic.ios.members/copyfmt.pass.cpp
+++ b/libcxx/test/std/input.output/iostreams.base/ios/basic.ios.members/copyfmt.pass.cpp
@@ -16,12 +16,15 @@
 // basic_ios& copyfmt(const basic_ios& rhs);
 
 #include <ios>
+#include <memory>
 #include <streambuf>
+#include <sstream>
 #include <cassert>
 
 #include "platform_support.h" // locale name macros
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 struct testbuf
     : public std::streambuf
@@ -191,5 +194,11 @@ int main(int, char**)
     assert(ios1.fill() == '2');
 #endif
 
+    {
+      std::basic_stringbuf<char, operator_hijacker_char_traits<char> > sb;
+      std::basic_ios<char, operator_hijacker_char_traits<char> > ios(std::addressof(sb));
+      ios.copyfmt(ios);
+    }
+
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/default.pass.cpp b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/default.pass.cpp
index 2a90d5d284f75..8c73df42ae4be 100644
--- a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/default.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/default.pass.cpp
@@ -19,6 +19,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 #if TEST_STD_VER >= 11
 #include "test_convertible.h"
 
@@ -33,29 +34,54 @@ int main(int, char**)
 {
     {
         std::istringstream ss;
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == "");
     }
+    {
+      std::basic_istringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss;
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == "");
+    }
     {
         std::istringstream ss(std::ios_base::in);
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == "");
     }
+    {
+      std::basic_istringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss(std::ios_base::in);
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == "");
+    }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wistringstream ss;
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == L"");
     }
     {
         std::wistringstream ss(std::ios_base::in);
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == L"");
     }
+    {
+      std::basic_istringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss;
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == L"");
+    }
+    {
+      std::basic_istringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss(
+          std::ios_base::in);
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == L"");
+    }
 #endif
 
 #if TEST_STD_VER >= 11
diff --git a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/mode.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/mode.alloc.pass.cpp
index 26dfc4b855413..e2bbd923d8ad0 100644
--- a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/mode.alloc.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/mode.alloc.pass.cpp
@@ -20,19 +20,22 @@
 
 #include "test_allocator.h"
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
-template <class CharT>
-static void test() {
-  const test_allocator<CharT> a(2);
-  const std::basic_istringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(std::ios_base::binary, a);
+template <class CharT, class Allocator>
+static void test(const Allocator& a) {
+  const std::basic_istringstream<CharT, std::char_traits<CharT>, Allocator> ss(std::ios_base::binary, a);
   assert(ss.rdbuf()->get_allocator() == a);
   assert(ss.view().empty());
 }
 
 int main(int, char**) {
-  test<char>();
+  test<char>(test_allocator<char>(2));
+  test<char>(operator_hijacker_allocator<char>());
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
+  test<wchar_t>(test_allocator<wchar_t>(2));
+  test<wchar_t>(operator_hijacker_allocator<wchar_t>());
 #endif
+
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/move.pass.cpp b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/move.pass.cpp
index 45ad2d2f76146..00ac7cc6414e9 100644
--- a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/move.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/move.pass.cpp
@@ -17,6 +17,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
@@ -32,6 +33,18 @@ int main(int, char**)
         ss >> i;
         assert(i == 456);
     }
+    {
+      std::basic_istringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss0(" 123 456");
+      std::basic_istringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss(std::move(ss0));
+      assert(ss.rdbuf() != 0);
+      assert(ss.good());
+      assert(ss.str() == " 123 456");
+      int i = 0;
+      ss >> i;
+      assert(i == 123);
+      ss >> i;
+      assert(i == 456);
+    }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wistringstream ss0(L" 123 456");
@@ -45,6 +58,20 @@ int main(int, char**)
         ss >> i;
         assert(i == 456);
     }
+    {
+      std::basic_istringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss0(
+          L" 123 456");
+      std::basic_istringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss(
+          std::move(ss0));
+      assert(ss.rdbuf() != 0);
+      assert(ss.good());
+      assert(ss.str() == L" 123 456");
+      int i = 0;
+      ss >> i;
+      assert(i == 123);
+      ss >> i;
+      assert(i == 456);
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string-alloc.mode.pass.cpp b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string-alloc.mode.pass.cpp
index 4fc3bfb520196..7e784667a6ccd 100644
--- a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string-alloc.mode.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string-alloc.mode.pass.cpp
@@ -22,28 +22,31 @@
 #include "make_string.h"
 #include "test_allocator.h"
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
 #define SV(S) MAKE_STRING_VIEW(CharT, S)
 
-template <class CharT>
+template <class CharT, class Allocator>
 static void test() {
   {
     const std::basic_string<CharT> s(STR("testing"));
-    const std::basic_istringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(s);
+    const std::basic_istringstream<CharT, std::char_traits<CharT>, Allocator> ss(s);
     assert(ss.view() == SV("testing"));
   }
   {
     const std::basic_string<CharT> s(STR("testing"));
-    const std::basic_istringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(s, std::ios_base::binary);
+    const std::basic_istringstream<CharT, std::char_traits<CharT>, Allocator> ss(s, std::ios_base::binary);
     assert(ss.view() == SV("testing"));
   }
 }
 
 int main(int, char**) {
-  test<char>();
+  test<char, test_allocator<char>>();
+  test<char, operator_hijacker_allocator<char>>();
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
+  test<wchar_t, test_allocator<wchar_t>>();
+  test<wchar_t, operator_hijacker_allocator<wchar_t>>();
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.alloc.pass.cpp
index ca9a6d1989aa0..4e4ac35a60dcd 100644
--- a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.alloc.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.alloc.pass.cpp
@@ -23,23 +23,25 @@
 #include "make_string.h"
 #include "test_allocator.h"
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
 #define SV(S) MAKE_STRING_VIEW(CharT, S)
 
-template <class CharT>
-static void test() {
+template <class CharT, class Allocator>
+static void test(const Allocator& a) {
   const std::basic_string<CharT> s(STR("testing"));
-  const test_allocator<CharT> a(2);
-  const std::basic_istringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(s, a);
+  const std::basic_istringstream<CharT, std::char_traits<CharT>, Allocator> ss(s, a);
   assert(ss.rdbuf()->get_allocator() == a);
   assert(ss.view() == SV("testing"));
 }
 
 int main(int, char**) {
-  test<char>();
+  test<char>(test_allocator<char>(2));
+  test<char>(operator_hijacker_allocator<char>());
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
+  test<wchar_t>(test_allocator<wchar_t>(2));
+  test<wchar_t>(operator_hijacker_allocator<wchar_t>());
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.mode.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.mode.alloc.pass.cpp
index 109d037ddec99..5a88b8f91f836 100644
--- a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.mode.alloc.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.mode.alloc.pass.cpp
@@ -22,23 +22,25 @@
 #include "make_string.h"
 #include "test_allocator.h"
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
 #define SV(S) MAKE_STRING_VIEW(CharT, S)
 
-template <class CharT>
-static void test() {
+template <class CharT, class Allocator>
+static void test(const Allocator& a) {
   const std::basic_string<CharT> s(STR("testing"));
-  const test_allocator<CharT> a(2);
-  const std::basic_istringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(s, std::ios_base::binary, a);
+  const std::basic_istringstream<CharT, std::char_traits<CharT>, Allocator> ss(s, std::ios_base::binary, a);
   assert(ss.rdbuf()->get_allocator() == a);
   assert(ss.view() == SV("testing"));
 }
 
 int main(int, char**) {
-  test<char>();
+  test<char>(test_allocator<char>(2));
+  test<char>(operator_hijacker_allocator<char>());
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
+  test<wchar_t>(test_allocator<wchar_t>(2));
+  test<wchar_t>(operator_hijacker_allocator<wchar_t>());
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.move.mode.pass.cpp b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.move.mode.pass.cpp
index 57208a411fcc0..c7f7cac4f27f0 100644
--- a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.move.mode.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.move.mode.pass.cpp
@@ -20,6 +20,7 @@
 
 #include "make_string.h"
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
 
@@ -30,11 +31,24 @@ static void test() {
     const std::basic_istringstream<CharT> ss(std::move(s));
     assert(ss.str() == STR("testing"));
   }
+  {
+    std::basic_string<CharT, std::char_traits<CharT>, operator_hijacker_allocator<CharT>> s(STR("testing"));
+    const std::basic_istringstream<CharT, std::char_traits<CharT>, operator_hijacker_allocator<CharT>> ss(std::move(s));
+    assert((ss.str() ==
+            std::basic_string<CharT, std::char_traits<CharT>, operator_hijacker_allocator<CharT>>(STR("testing"))));
+  }
   {
     std::basic_string<CharT> s(STR("testing"));
     const std::basic_istringstream<CharT> ss(std::move(s), std::ios_base::binary);
     assert(ss.str() == STR("testing"));
   }
+  {
+    std::basic_string<CharT, std::char_traits<CharT>, operator_hijacker_allocator<CharT>> s(STR("testing"));
+    const std::basic_istringstream<CharT, std::char_traits<CharT>, operator_hijacker_allocator<CharT>> ss(
+        std::move(s), std::ios_base::binary);
+    assert((ss.str() ==
+            std::basic_string<CharT, std::char_traits<CharT>, operator_hijacker_allocator<CharT>>(STR("testing"))));
+  }
 }
 
 int main(int, char**) {
diff --git a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.pass.cpp b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.pass.cpp
index 9b0593f275357..4a5965e7e96e9 100644
--- a/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.pass.cpp
@@ -18,12 +18,13 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
     {
         std::istringstream ss(" 123 456");
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == " 123 456");
         int i = 0;
@@ -32,9 +33,20 @@ int main(int, char**)
         ss >> i;
         assert(i == 456);
     }
+    {
+      std::basic_istringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss(" 123 456");
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == " 123 456");
+      int i = 0;
+      ss >> i;
+      assert(i == 123);
+      ss >> i;
+      assert(i == 456);
+    }
     {
         std::istringstream ss(" 123 456", std::ios_base::out);
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == " 123 456");
         int i = 0;
@@ -43,10 +55,22 @@ int main(int, char**)
         ss >> i;
         assert(i == 456);
     }
+    {
+      std::basic_istringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss(
+          " 123 456", std::ios_base::out);
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == " 123 456");
+      int i = 0;
+      ss >> i;
+      assert(i == 123);
+      ss >> i;
+      assert(i == 456);
+    }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wistringstream ss(L" 123 456");
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == L" 123 456");
         int i = 0;
@@ -55,9 +79,21 @@ int main(int, char**)
         ss >> i;
         assert(i == 456);
     }
+    {
+      std::basic_istringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss(
+          L" 123 456");
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == L" 123 456");
+      int i = 0;
+      ss >> i;
+      assert(i == 123);
+      ss >> i;
+      assert(i == 456);
+    }
     {
         std::wistringstream ss(L" 123 456", std::ios_base::out);
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == L" 123 456");
         int i = 0;
@@ -66,6 +102,18 @@ int main(int, char**)
         ss >> i;
         assert(i == 456);
     }
+    {
+      std::basic_istringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss(
+          L" 123 456", std::ios_base::out);
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == L" 123 456");
+      int i = 0;
+      ss >> i;
+      assert(i == 123);
+      ss >> i;
+      assert(i == 456);
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/default.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/default.pass.cpp
index 92796bb69c78d..a6b98a4e36293 100644
--- a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/default.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/default.pass.cpp
@@ -18,6 +18,7 @@
 #include <sstream>
 #include <cassert>
 
+#include "operator_hijacker.h"
 #include "test_macros.h"
 #if TEST_STD_VER >= 11
 #include "test_convertible.h"
@@ -33,29 +34,54 @@ int main(int, char**)
 {
     {
         std::ostringstream ss;
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == "");
     }
+    {
+      std::basic_ostringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss;
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == "");
+    }
     {
         std::ostringstream ss(std::ios_base::out);
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == "");
     }
+    {
+      std::basic_ostringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss(std::ios_base::out);
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == "");
+    }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wostringstream ss;
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == L"");
     }
+    {
+      std::basic_ostringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss;
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == L"");
+    }
     {
         std::wostringstream ss(std::ios_base::out);
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == L"");
     }
+    {
+      std::basic_ostringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss(
+          std::ios_base::out);
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == L"");
+    }
 #endif // TEST_HAS_NO_WIDE_CHARACTERS
 
 #if TEST_STD_VER >= 11
diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/mode.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/mode.alloc.pass.cpp
index 6b6dc8f2606ae..9e89f66481875 100644
--- a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/mode.alloc.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/mode.alloc.pass.cpp
@@ -20,19 +20,22 @@
 
 #include "test_allocator.h"
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
-template <class CharT>
-static void test() {
-  const test_allocator<CharT> a(2);
-  const std::basic_ostringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(std::ios_base::binary, a);
+template <class CharT, class Allocator>
+static void test(const Allocator& a) {
+  const std::basic_ostringstream<CharT, std::char_traits<CharT>, Allocator> ss(std::ios_base::binary, a);
   assert(ss.rdbuf()->get_allocator() == a);
   assert(ss.view().empty());
 }
 
 int main(int, char**) {
-  test<char>();
+  test<char>(test_allocator<char>(2));
+  test<char>(operator_hijacker_allocator<char>());
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
+  test<wchar_t>(test_allocator<wchar_t>(2));
+  test<wchar_t>(operator_hijacker_allocator<wchar_t>());
 #endif
+
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/move.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/move.pass.cpp
index 6a63cd61d55ed..596a3e7d53584 100644
--- a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/move.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/move.pass.cpp
@@ -16,6 +16,7 @@
 #include <sstream>
 #include <cassert>
 
+#include "operator_hijacker.h"
 #include "test_macros.h"
 
 int main(int, char**)
@@ -23,24 +24,46 @@ int main(int, char**)
     {
         std::ostringstream ss0(" 123 456");
         std::ostringstream ss(std::move(ss0));
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == " 123 456");
         int i = 234;
         ss << i << ' ' << 567;
         assert(ss.str() == "234 5676");
     }
+    {
+      std::basic_ostringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss0(" 123 456");
+      std::basic_ostringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss(std::move(ss0));
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == " 123 456");
+      int i = 234;
+      ss << i << ' ' << 567;
+      assert(ss.str() == "234 5676");
+    }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wostringstream ss0(L" 123 456");
         std::wostringstream ss(std::move(ss0));
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == L" 123 456");
         int i = 234;
         ss << i << ' ' << 567;
         assert(ss.str() == L"234 5676");
     }
+    {
+      std::basic_ostringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss0(
+          L" 123 456");
+      std::basic_ostringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss(
+          std::move(ss0));
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == L" 123 456");
+      int i = 234;
+      ss << i << ' ' << 567;
+      assert(ss.str() == L"234 5676");
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string-alloc.mode.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string-alloc.mode.pass.cpp
index 36b615fc8e020..ca24c40267583 100644
--- a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string-alloc.mode.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string-alloc.mode.pass.cpp
@@ -22,28 +22,31 @@
 #include "make_string.h"
 #include "test_allocator.h"
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
 #define SV(S) MAKE_STRING_VIEW(CharT, S)
 
-template <class CharT>
+template <class CharT, class Allocator>
 static void test() {
   {
     const std::basic_string<CharT> s(STR("testing"));
-    const std::basic_ostringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(s);
+    const std::basic_ostringstream<CharT, std::char_traits<CharT>, Allocator> ss(s);
     assert(ss.view() == SV("testing"));
   }
   {
     const std::basic_string<CharT> s(STR("testing"));
-    const std::basic_ostringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(s, std::ios_base::binary);
+    const std::basic_ostringstream<CharT, std::char_traits<CharT>, Allocator> ss(s, std::ios_base::binary);
     assert(ss.view() == SV("testing"));
   }
 }
 
 int main(int, char**) {
-  test<char>();
+  test<char, test_allocator<char>>();
+  test<char, operator_hijacker_allocator<char>>();
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
+  test<wchar_t, test_allocator<wchar_t>>();
+  test<wchar_t, operator_hijacker_allocator<wchar_t>>();
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.alloc.pass.cpp
index 1425988b40090..2a0e9d771d04c 100644
--- a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.alloc.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.alloc.pass.cpp
@@ -23,23 +23,25 @@
 #include "make_string.h"
 #include "test_allocator.h"
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
 #define SV(S) MAKE_STRING_VIEW(CharT, S)
 
-template <class CharT>
-static void test() {
+template <class CharT, class Allocator>
+static void test(const Allocator& a) {
   const std::basic_string<CharT> s(STR("testing"));
-  const test_allocator<CharT> a(2);
-  const std::basic_ostringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(s, a);
+  const std::basic_ostringstream<CharT, std::char_traits<CharT>, Allocator> ss(s, a);
   assert(ss.rdbuf()->get_allocator() == a);
   assert(ss.view() == SV("testing"));
 }
 
 int main(int, char**) {
-  test<char>();
+  test<char>(test_allocator<char>(2));
+  test<char>(operator_hijacker_allocator<char>());
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
+  test<wchar_t>(test_allocator<wchar_t>(2));
+  test<wchar_t>(operator_hijacker_allocator<wchar_t>());
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.mode.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.mode.alloc.pass.cpp
index 18365e6bc2e60..83b3709376e84 100644
--- a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.mode.alloc.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.mode.alloc.pass.cpp
@@ -22,23 +22,25 @@
 #include "make_string.h"
 #include "test_allocator.h"
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
 #define SV(S) MAKE_STRING_VIEW(CharT, S)
 
-template <class CharT>
-static void test() {
-  const std::basic_string<CharT> s(STR("testing"));
-  const test_allocator<CharT> a(2);
-  const std::basic_ostringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(s, std::ios_base::binary, a);
+template <class CharT, class Allocator>
+static void test(const Allocator& a) {
+  const std::basic_string<CharT, std::char_traits<CharT>, Allocator> s(STR("testing"));
+  const std::basic_ostringstream<CharT, std::char_traits<CharT>, Allocator> ss(s, std::ios_base::binary, a);
   assert(ss.rdbuf()->get_allocator() == a);
   assert(ss.view() == SV("testing"));
 }
 
 int main(int, char**) {
-  test<char>();
+  test<char>(test_allocator<char>(2));
+  test<char>(operator_hijacker_allocator<char>());
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
+  test<wchar_t>(test_allocator<wchar_t>(2));
+  test<wchar_t>(operator_hijacker_allocator<wchar_t>());
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.move.mode.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.move.mode.pass.cpp
index e24ac5cc6849e..3466429645fb5 100644
--- a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.move.mode.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.move.mode.pass.cpp
@@ -19,28 +19,35 @@
 #include <cassert>
 
 #include "make_string.h"
+#include "test_allocator.h"
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
+#define SV(S) MAKE_STRING_VIEW(CharT, S)
 
-template <class CharT>
+template <class CharT, class Allocator>
 static void test() {
   {
-    std::basic_string<CharT> s(STR("testing"));
-    const std::basic_ostringstream<CharT> ss(std::move(s));
-    assert(ss.str() == STR("testing"));
+    std::basic_string<CharT, std::char_traits<CharT>, Allocator> s(STR("testing"));
+    const std::basic_ostringstream<CharT, std::char_traits<CharT>, Allocator> ss(std::move(s));
+    assert(ss.str() == SV("testing"));
   }
   {
-    std::basic_string<CharT> s(STR("testing"));
-    const std::basic_ostringstream<CharT> ss(std::move(s), std::ios_base::binary);
-    assert(ss.str() == STR("testing"));
+    std::basic_string<CharT, std::char_traits<CharT>, Allocator> s(STR("testing"));
+    const std::basic_ostringstream<CharT, std::char_traits<CharT>, Allocator> ss(std::move(s), std::ios_base::binary);
+    assert(ss.str() == SV("testing"));
   }
 }
 
 int main(int, char**) {
-  test<char>();
+  test<char, std::allocator<char>>();
+  test<char, test_allocator<char>>();
+  test<char, operator_hijacker_allocator<char>>();
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
+  test<wchar_t, std::allocator<wchar_t>>();
+  test<wchar_t, test_allocator<wchar_t>>();
+  test<wchar_t, operator_hijacker_allocator<wchar_t>>();
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.pass.cpp
index af3c320ddf5f4..9e9405ad49217 100644
--- a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.pass.cpp
@@ -18,46 +18,86 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
     {
         std::ostringstream ss(" 123 456");
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == " 123 456");
         int i = 234;
         ss << i << ' ' << 567;
         assert(ss.str() == "234 5676");
     }
+    {
+      std::basic_ostringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss(" 123 456");
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == " 123 456");
+      int i = 234;
+      ss << i << ' ' << 567;
+      assert(ss.str() == "234 5676");
+    }
     {
         std::ostringstream ss(" 123 456", std::ios_base::in);
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == " 123 456");
         int i = 234;
         ss << i << ' ' << 567;
         assert(ss.str() == "234 5676");
     }
+    {
+      std::basic_ostringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss(
+          " 123 456", std::ios_base::in);
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == " 123 456");
+      int i = 234;
+      ss << i << ' ' << 567;
+      assert(ss.str() == "234 5676");
+    }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wostringstream ss(L" 123 456");
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == L" 123 456");
         int i = 234;
         ss << i << ' ' << 567;
         assert(ss.str() == L"234 5676");
     }
+    {
+      std::basic_ostringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss(
+          L" 123 456");
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == L" 123 456");
+      int i = 234;
+      ss << i << ' ' << 567;
+      assert(ss.str() == L"234 5676");
+    }
     {
         std::wostringstream ss(L" 123 456", std::ios_base::in);
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == L" 123 456");
         int i = 234;
         ss << i << ' ' << 567;
         assert(ss.str() == L"234 5676");
     }
+    {
+      std::basic_ostringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss(
+          L" 123 456", std::ios_base::in);
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == L" 123 456");
+      int i = 234;
+      ss << i << ' ' << 567;
+      assert(ss.str() == L"234 5676");
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/default.pass.cpp b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/default.pass.cpp
index 5ce17f5c539fe..4f9e7e026c50f 100644
--- a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/default.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/default.pass.cpp
@@ -19,6 +19,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 #if TEST_STD_VER >= 11
 #include "test_convertible.h"
 
@@ -33,26 +34,38 @@ int main(int, char**)
 {
     {
         std::stringstream ss;
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == "");
     }
+    {
+      std::basic_stringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss;
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == "");
+    }
     {
         std::stringstream ss(std::ios_base::in);
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == "");
     }
+    {
+      std::basic_stringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss(std::ios_base::in);
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == "");
+    }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wstringstream ss;
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == L"");
     }
     {
         std::wstringstream ss(std::ios_base::in);
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == L"");
     }
diff --git a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/mode.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/mode.alloc.pass.cpp
index 72e5a7f41287f..ed4c36e56695b 100644
--- a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/mode.alloc.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/mode.alloc.pass.cpp
@@ -15,24 +15,26 @@
 
 // basic_stringstream(ios_base::openmode which, const Allocator& a);
 
-#include <sstream>
 #include <cassert>
+#include <sstream>
 
 #include "test_allocator.h"
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
-template <class CharT>
-static void test() {
-  const test_allocator<CharT> a(2);
-  const std::basic_stringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(std::ios_base::in, a);
+template <class CharT, class Allocator>
+static void test(const Allocator& a) {
+  const std::basic_stringstream<CharT, std::char_traits<CharT>, Allocator> ss(std::ios_base::in, a);
   assert(ss.rdbuf()->get_allocator() == a);
   assert(ss.view().empty());
 }
 
 int main(int, char**) {
-  test<char>();
+  test<char>(test_allocator<char>(2));
+  test<char>(operator_hijacker_allocator<char>());
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
+  test<wchar_t>(test_allocator<wchar_t>(2));
+  test<wchar_t>(operator_hijacker_allocator<wchar_t>());
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/move.pass.cpp b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/move.pass.cpp
index ec19c6736112d..0702d9a278d3c 100644
--- a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/move.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/move.pass.cpp
@@ -17,13 +17,14 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 int main(int, char**)
 {
     {
         std::stringstream ss0(" 123 456 ");
         std::stringstream ss(std::move(ss0));
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == " 123 456 ");
         int i = 0;
@@ -34,11 +35,25 @@ int main(int, char**)
         ss << i << ' ' << 123;
         assert(ss.str() == "456 1236 ");
     }
+    {
+      std::basic_stringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss0(" 123 456 ");
+      std::basic_stringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss(std::move(ss0));
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == " 123 456 ");
+      int i = 0;
+      ss >> i;
+      assert(i == 123);
+      ss >> i;
+      assert(i == 456);
+      ss << i << ' ' << 123;
+      assert(ss.str() == "456 1236 ");
+    }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wstringstream ss0(L" 123 456 ");
         std::wstringstream ss(std::move(ss0));
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == L" 123 456 ");
         int i = 0;
@@ -49,6 +64,22 @@ int main(int, char**)
         ss << i << ' ' << 123;
         assert(ss.str() == L"456 1236 ");
     }
+    {
+      std::basic_stringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss0(
+          L" 123 456 ");
+      std::basic_stringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss(
+          std::move(ss0));
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == L" 123 456 ");
+      int i = 0;
+      ss >> i;
+      assert(i == 123);
+      ss >> i;
+      assert(i == 456);
+      ss << i << ' ' << 123;
+      assert(ss.str() == L"456 1236 ");
+    }
 #endif
 
   return 0;
diff --git a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string-alloc.mode.pass.cpp b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string-alloc.mode.pass.cpp
index 19fb32fe6e86c..f65d7b9449a10 100644
--- a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string-alloc.mode.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string-alloc.mode.pass.cpp
@@ -21,29 +21,32 @@
 
 #include "make_string.h"
 #include "test_allocator.h"
+#include "operator_hijacker.h"
 #include "test_macros.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
 #define SV(S) MAKE_STRING_VIEW(CharT, S)
 
-template <class CharT>
+template <class CharT, class Allocator>
 static void test() {
   {
     const std::basic_string<CharT> s(STR("testing"));
-    const std::basic_stringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(s);
+    const std::basic_stringstream<CharT, std::char_traits<CharT>, Allocator> ss(s);
     assert(ss.view() == SV("testing"));
   }
   {
     const std::basic_string<CharT> s(STR("testing"));
-    const std::basic_stringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(s, std::ios_base::in);
+    const std::basic_stringstream<CharT, std::char_traits<CharT>, Allocator> ss(s, std::ios_base::in);
     assert(ss.view() == SV("testing"));
   }
 }
 
 int main(int, char**) {
-  test<char>();
+  test<char, test_allocator<char>>();
+  test<char, operator_hijacker_allocator<char>>();
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
+  test<wchar_t, test_allocator<wchar_t>>();
+  test<wchar_t, operator_hijacker_allocator<wchar_t>>();
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.alloc.pass.cpp
index 91f34a8c1e533..9d3024d7f83c7 100644
--- a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.alloc.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.alloc.pass.cpp
@@ -22,24 +22,26 @@
 
 #include "make_string.h"
 #include "test_allocator.h"
+#include "operator_hijacker.h"
 #include "test_macros.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
 #define SV(S) MAKE_STRING_VIEW(CharT, S)
 
-template <class CharT>
-static void test() {
+template <class CharT, class Allocator>
+static void test(const Allocator& a) {
   const std::basic_string<CharT> s(STR("testing"));
-  const test_allocator<CharT> a(2);
-  const std::basic_stringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(s, a);
+  const std::basic_stringstream<CharT, std::char_traits<CharT>, Allocator> ss(s, a);
   assert(ss.rdbuf()->get_allocator() == a);
   assert(ss.view() == SV("testing"));
 }
 
 int main(int, char**) {
-  test<char>();
+  test<char>(test_allocator<char>(2));
+  test<char>(operator_hijacker_allocator<char>());
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
+  test<wchar_t>(test_allocator<wchar_t>(2));
+  test<wchar_t>(operator_hijacker_allocator<wchar_t>());
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.mode.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.mode.alloc.pass.cpp
index c1bcccdd2df80..362677cb4e6f5 100644
--- a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.mode.alloc.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.mode.alloc.pass.cpp
@@ -22,23 +22,26 @@
 #include "make_string.h"
 #include "test_allocator.h"
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
 #define SV(S) MAKE_STRING_VIEW(CharT, S)
 
-template <class CharT>
-static void test() {
+template <class CharT, class Allocator>
+static void test(const Allocator& a) {
   const std::basic_string<CharT> s(STR("testing"));
-  const test_allocator<CharT> a(2);
-  const std::basic_stringstream<CharT, std::char_traits<CharT>, test_allocator<CharT>> ss(s, std::ios_base::out, a);
+  const std::basic_stringstream<CharT, std::char_traits<CharT>, Allocator> ss(s, std::ios_base::out, a);
   assert(ss.rdbuf()->get_allocator() == a);
   assert(ss.view() == SV("testing"));
 }
 
 int main(int, char**) {
-  test<char>();
+  test<char>(test_allocator<char>(2));
+  test<char>(operator_hijacker_allocator<char>());
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
+  test<wchar_t>(test_allocator<wchar_t>(2));
+  test<wchar_t>(operator_hijacker_allocator<wchar_t>());
 #endif
+
   return 0;
 }
diff --git a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.move.mode.pass.cpp b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.move.mode.pass.cpp
index d0146f0ccc271..40528f186f898 100644
--- a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.move.mode.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.move.mode.pass.cpp
@@ -20,20 +20,33 @@
 
 #include "make_string.h"
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
+#define SV(S) MAKE_STRING_VIEW(CharT, S)
 
 template <class CharT>
 static void test() {
   {
     std::basic_string<CharT> s(STR("testing"));
     const std::basic_stringstream<CharT> ss(std::move(s));
-    assert(ss.str() == STR("testing"));
+    assert(ss.str() == SV("testing"));
+  }
+  {
+    std::basic_string<CharT, std::char_traits<CharT>, operator_hijacker_allocator<CharT>> s(STR("testing"));
+    const std::basic_stringstream<CharT, std::char_traits<CharT>, operator_hijacker_allocator<CharT>> ss(std::move(s));
+    assert(ss.str() == SV("testing"));
   }
   {
     std::basic_string<CharT> s(STR("testing"));
     const std::basic_stringstream<CharT> ss(std::move(s), std::ios_base::out);
-    assert(ss.str() == STR("testing"));
+    assert(ss.str() == SV("testing"));
+  }
+  {
+    std::basic_string<CharT, std::char_traits<CharT>, operator_hijacker_allocator<CharT>> s(STR("testing"));
+    const std::basic_stringstream<CharT, std::char_traits<CharT>, operator_hijacker_allocator<CharT>> ss(
+        std::move(s), std::ios_base::out);
+    assert(ss.str() == SV("testing"));
   }
 }
 
diff --git a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.pass.cpp b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.pass.cpp
index 0fb8a0288578e..08880878361da 100644
--- a/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.pass.cpp
@@ -18,6 +18,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "operator_hijacker.h"
 
 template<typename T>
 struct NoDefaultAllocator : std::allocator<T>
@@ -33,7 +34,7 @@ int main(int, char**)
 {
     {
         std::stringstream ss(" 123 456 ");
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == " 123 456 ");
         int i = 0;
@@ -44,10 +45,23 @@ int main(int, char**)
         ss << i << ' ' << 123;
         assert(ss.str() == "456 1236 ");
     }
+    {
+      std::basic_stringstream<char, std::char_traits<char>, operator_hijacker_allocator<char> > ss(" 123 456 ");
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == " 123 456 ");
+      int i = 0;
+      ss >> i;
+      assert(i == 123);
+      ss >> i;
+      assert(i == 456);
+      ss << i << ' ' << 123;
+      assert(ss.str() == "456 1236 ");
+    }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     {
         std::wstringstream ss(L" 123 456 ");
-        assert(ss.rdbuf() != 0);
+        assert(ss.rdbuf() != nullptr);
         assert(ss.good());
         assert(ss.str() == L" 123 456 ");
         int i = 0;
@@ -58,6 +72,20 @@ int main(int, char**)
         ss << i << ' ' << 123;
         assert(ss.str() == L"456 1236 ");
     }
+    {
+      std::basic_stringstream<wchar_t, std::char_traits<wchar_t>, operator_hijacker_allocator<wchar_t> > ss(
+          L" 123 456 ");
+      assert(ss.rdbuf() != nullptr);
+      assert(ss.good());
+      assert(ss.str() == L" 123 456 ");
+      int i = 0;
+      ss >> i;
+      assert(i == 123);
+      ss >> i;
+      assert(i == 456);
+      ss << i << ' ' << 123;
+      assert(ss.str() == L"456 1236 ");
+    }
 #endif
     { // This is https://llvm.org/PR33727
         typedef std::basic_string   <char, std::char_traits<char>, NoDefaultAllocator<char> > S;
diff --git a/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp
index 7210d67b5cb22..93a8e59349634 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp
@@ -19,6 +19,7 @@
 #include "test_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "operator_hijacker.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s0, const typename S::allocator_type& a) {
@@ -74,6 +75,18 @@ TEST_CONSTEXPR_CXX20 bool test() {
     test(S("1"), A());
     test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A());
   }
+  {
+    typedef operator_hijacker_allocator<char> A;
+    typedef std::basic_string<char, std::char_traits<char>, A> S;
+#if TEST_STD_VER > 14
+    static_assert((noexcept(S{})), "");
+#elif TEST_STD_VER >= 11
+    static_assert((noexcept(S()) == std::is_nothrow_move_constructible<A>::value), "");
+#endif
+    test(S(), A());
+    test(S("1"), A());
+    test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A());
+  }
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.cons/substr_rvalue.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/substr_rvalue.pass.cpp
index a9b07a6eb1aa4..9c7c341302df9 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/substr_rvalue.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/substr_rvalue.pass.cpp
@@ -24,6 +24,7 @@
 #include "test_allocator.h"
 #include "test_macros.h"
 #include "asan_testing.h"
+#include "operator_hijacker.h"
 
 #define STR(string) MAKE_CSTRING(typename S::value_type, string)
 
@@ -212,6 +213,8 @@ constexpr void test_allocators() {
   test_string<std::basic_string<CharT, CharTraits, std::allocator<CharT>>>(std::allocator<CharT>{});
   test_string<std::basic_string<CharT, CharTraits, min_allocator<CharT>>>(min_allocator<CharT>{});
   test_string<std::basic_string<CharT, CharTraits, test_allocator<CharT>>>(test_allocator<CharT>{42});
+  test_string<std::basic_string<CharT, CharTraits, operator_hijacker_allocator<CharT>>>(
+      operator_hijacker_allocator<CharT>{});
 }
 
 template <class CharT>
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp
index 16bdac1c4dcc6..9af110a8920d6 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "operator_hijacker.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s1, S s2) {
@@ -62,6 +63,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, operator_hijacker_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/support/operator_hijacker.h b/libcxx/test/support/operator_hijacker.h
index a2569da0310ff..15add460d3768 100644
--- a/libcxx/test/support/operator_hijacker.h
+++ b/libcxx/test/support/operator_hijacker.h
@@ -10,7 +10,9 @@
 #define SUPPORT_OPERATOR_HIJACKER_H
 
 #include <cstddef>
+#include <memory>
 #include <functional>
+#include <string>
 
 #include "test_macros.h"
 
@@ -18,8 +20,8 @@
 ///
 /// The class has some additional operations to be usable in all containers.
 struct operator_hijacker {
-  bool operator<(const operator_hijacker&) const { return true; }
-  bool operator==(const operator_hijacker&) const { return true; }
+  TEST_CONSTEXPR bool operator<(const operator_hijacker&) const { return true; }
+  TEST_CONSTEXPR bool operator==(const operator_hijacker&) const { return true; }
 
   template <typename T>
   friend void operator&(T&&) = delete;
@@ -43,4 +45,16 @@ struct std::hash<operator_hijacker> {
   std::size_t operator()(const operator_hijacker&) const { return 0; }
 };
 
+template <class T>
+struct operator_hijacker_allocator : std::allocator<T>, operator_hijacker {
+#if TEST_STD_VER <= 17
+  struct rebind {
+    typedef operator_hijacker_allocator<T> other;
+  };
+#endif
+};
+
+template <class CharT>
+struct operator_hijacker_char_traits : std::char_traits<CharT>, operator_hijacker {};
+
 #endif // SUPPORT_OPERATOR_HIJACKER_H
diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h
index 15fc5b69b5207..9dab5750a5f91 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -7,6 +7,12 @@
 //
 //===----------------------------------------------------------------------===//
 
+// This header contains several configuration defines.
+// Removing the header would #ifndef TEST_FOO to unconditionally pass when
+// it's optionally defined in this header.
+//
+// IWYU pragma: always_keep
+
 #ifndef SUPPORT_TEST_MACROS_HPP
 #define SUPPORT_TEST_MACROS_HPP
 



More information about the libcxx-commits mailing list