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

via libcxx-commits libcxx-commits at lists.llvm.org
Sun Aug 4 06:32:59 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

<details>
<summary>Changes</summary>

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

---

Patch is 95.08 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/101889.diff


50 Files Affected:

- (modified) libcxx/docs/Status/Cxx20Issues.csv (+1-1) 
- (modified) libcxx/include/fstream (+25-18) 
- (modified) libcxx/include/ios (+6-5) 
- (modified) libcxx/include/sstream (+17-15) 
- (modified) libcxx/include/string (+5-5) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/default.pass.cpp (+7-1) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/move.pass.cpp (+26) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/path.pass.cpp (+24) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/pointer.pass.cpp (+24) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/string.pass.cpp (+24) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/default.pass.cpp (+7-1) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/move.pass.cpp (+16) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/path.pass.cpp (+13) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/pointer.pass.cpp (+13) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/ifstream.cons/string.pass.cpp (+13) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/default.pass.cpp (+7-1) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/move.pass.cpp (+28) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/path.pass.cpp (+65-4) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp (+72-8) 
- (modified) libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/string.pass.cpp (+71-8) 
- (modified) libcxx/test/std/input.output/iostreams.base/ios/basic.ios.members/copyfmt.pass.cpp (+9) 
- (modified) libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/default.pass.cpp (+30-4) 
- (modified) libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/mode.alloc.pass.cpp (+9-6) 
- (modified) libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/move.pass.cpp (+27) 
- (modified) libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string-alloc.mode.pass.cpp (+8-5) 
- (modified) libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.alloc.pass.cpp (+8-6) 
- (modified) libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.mode.alloc.pass.cpp (+8-6) 
- (modified) libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.move.mode.pass.cpp (+14) 
- (modified) libcxx/test/std/input.output/string.streams/istringstream/istringstream.cons/string.pass.cpp (+52-4) 
- (modified) libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/default.pass.cpp (+30-4) 
- (modified) libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/mode.alloc.pass.cpp (+9-6) 
- (modified) libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/move.pass.cpp (+25-2) 
- (modified) libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string-alloc.mode.pass.cpp (+8-5) 
- (modified) libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.alloc.pass.cpp (+8-6) 
- (modified) libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.mode.alloc.pass.cpp (+9-7) 
- (modified) libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.move.mode.pass.cpp (+16-9) 
- (modified) libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.pass.cpp (+44-4) 
- (modified) libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/default.pass.cpp (+17-4) 
- (modified) libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/mode.alloc.pass.cpp (+9-7) 
- (modified) libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/move.pass.cpp (+33-2) 
- (modified) libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string-alloc.mode.pass.cpp (+8-5) 
- (modified) libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.alloc.pass.cpp (+8-6) 
- (modified) libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.mode.alloc.pass.cpp (+9-6) 
- (modified) libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.move.mode.pass.cpp (+15-2) 
- (modified) libcxx/test/std/input.output/string.streams/stringstream/stringstream.cons/string.pass.cpp (+30-2) 
- (modified) libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp (+13) 
- (modified) libcxx/test/std/strings/basic.string/string.cons/substr_rvalue.pass.cpp (+3) 
- (modified) libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp (+2) 
- (modified) libcxx/test/support/operator_hijacker.h (+16-2) 
- (modified) libcxx/test/support/test_macros.h (+6) 


``````````diff
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 << "...
[truncated]

``````````

</details>


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


More information about the libcxx-commits mailing list