From 29340e59eaca6d829c3ff719975ab565cdbbf062 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 6 Dec 2023 01:45:08 +0800 Subject: [PATCH 01/12] Don't swap `basic_stringbuf` in move assignment... and allocator-extended move construction. --- stl/inc/sstream | 134 +++++++++++++----- .../GH_001858_iostream_exception/test.cpp | 20 +++ .../test.cpp | 17 +++ 3 files changed, 135 insertions(+), 36 deletions(-) diff --git a/stl/inc/sstream b/stl/inc/sstream index c78711c54a..a4fbc50ee1 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -67,23 +67,88 @@ public: : basic_stringbuf(_Str, _Mode, _Alloc{}) {} basic_stringbuf(basic_stringbuf&& _Right, const _Alloc& _Al_) : _Mystate(0), _Al(_Al_) { - _Assign_rv(_STD move(_Right)); + if constexpr (!allocator_traits<_Alloc>::is_always_equal::value) { + if (_Al != _Right._Al) { + _Copy_into_self_and_tidy(_STD move(_Right)); + return; + } + } + + _Take_contents(_STD move(_Right)); } #endif // _HAS_CXX20 - basic_stringbuf(basic_stringbuf&& _Right) : _Mystate(0) { - _Assign_rv(_STD move(_Right)); + basic_stringbuf(basic_stringbuf&& _Right) + : _Seekhigh(_STD exchange(_Right._Seekhigh, nullptr)), _Mystate(_STD exchange(_Right._Mystate, 0)), + _Al(_Right._Al) { + _Take_contents(_STD move(_Right)); } - basic_stringbuf& operator=(basic_stringbuf&& _Right) noexcept /* strengthened */ { - _Assign_rv(_STD move(_Right)); + basic_stringbuf& operator=(basic_stringbuf&& _Right) noexcept( + _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) /* strengthened */ { + if (this != _STD addressof(_Right)) { + _Assign_rv_no_alias(_STD move(_Right)); + } return *this; } - void _Assign_rv(basic_stringbuf&& _Right) noexcept { - if (this != _STD addressof(_Right)) { - _Tidy(); - this->swap(_Right); + void _Take_contents(basic_stringbuf&& _Right) noexcept { + // pre: *this holds no dynamic buffer and _Al == _Right._Al + _Mystate = _STD exchange(_Right._Mystate, 0); + _Seekhigh = _STD exchange(_Right._Seekhigh, nullptr); + _Mysb::swap(_Right); + } + + void _Copy_into_self_and_tidy(basic_stringbuf&& _Right) { + // pre: *this holds no dynamic buffer and _Al != _Right._Al + if ((_Right._Mystate & _Allocated) == 0) { + return; + } + + const auto _Right_data = _Right._Mysb::eback(); + const auto _Right_capacity = static_cast::size_type>( + (_Right._Mysb::pptr() ? _Right._Mysb::epptr() : _Right._Mysb::egptr()) - _Right_data); + + auto _New_capacity = _Right_capacity; + const auto _New_data = _STD _Unfancy(_STD _Allocate_at_least_helper(_Al, _New_capacity)); + + _Mysb::setg(_New_data, _New_data + (_Right._Mysb::gptr() - _Right_data), + _New_data + (_Right._Mysb::egptr() - _Right_data)); + if (_Right._Mysb::pbase() != nullptr) { + const auto _Pbase_diff = _Right._Mysb::pbase() - _Right_data; + const auto _Pptr_diff = _Right._Mysb::pptr() - _Right_data; + const auto _Epptr_diff = _Right._Mysb::epptr() - _Right_data; + _Mysb::setp(_New_data + _Pbase_diff, _New_data + _Pptr_diff, _New_data + _Epptr_diff); + } else { + _Mysb::setp(nullptr, nullptr, nullptr); + } + + const auto _Right_view = _Right._Get_buffer_view(); + if (_Right_view._Ptr != nullptr) { + _Traits::copy(_New_data + (_Right_view._Ptr - _Right_data), _Right_view._Ptr, _Right_view._Size); + } + + _Seekhigh = _New_data + _New_capacity; + _Mystate = _Right._Mystate; + + _Right._Tidy(); + } + + void _Assign_rv_no_alias(basic_stringbuf&& _Right) noexcept( + _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) { + // pre: this != std::addressof(_Right) + _Tidy(); + if constexpr (_Choose_pocma_v<_Alloc> == _Pocma_values::_No_propagate_allocators) { + if (_Al == _Right._Al) { + _Take_contents(_STD move(_Right)); + } else { + _Copy_into_self_and_tidy(_STD move(_Right)); + } + } else { + if constexpr (_Choose_pocma_v<_Alloc> == _Pocma_values::_Propagate_allocators) { + _Al = _STD move(_Al); + } + _Take_contents(_STD move(_Right)); } } @@ -584,20 +649,19 @@ public: : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Str, _Mode | ios_base::in) {} #endif // _HAS_CXX20 - basic_istringstream(basic_istringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)) { - _Assign_rv(_STD move(_Right)); - } - - basic_istringstream& operator=(basic_istringstream&& _Right) noexcept /* strengthened */ { - _Assign_rv(_STD move(_Right)); - return *this; + basic_istringstream(basic_istringstream&& _Right) + : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Right._Stringbuffer.get_allocator()) { + _Mybase::swap(_Right); + _Stringbuffer._Take_contents(_STD move(_Right._Stringbuffer)); } - void _Assign_rv(basic_istringstream&& _Right) noexcept { + basic_istringstream& operator=(basic_istringstream&& _Right) noexcept( + _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) /* strengthened */ { if (this != _STD addressof(_Right)) { _Mybase::swap(_Right); - _Stringbuffer._Assign_rv(_STD move(_Right._Stringbuffer)); + _Stringbuffer._Assign_rv_no_alias(_STD move(_Right._Stringbuffer)); } + return *this; } void swap(basic_istringstream& _Right) noexcept /* strengthened */ { @@ -704,20 +768,19 @@ public: : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Str, _Mode | ios_base::out) {} #endif // _HAS_CXX20 - basic_ostringstream(basic_ostringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)) { - _Assign_rv(_STD move(_Right)); + basic_ostringstream(basic_ostringstream&& _Right) + : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Right._Stringbuffer.get_allocator()) { + _Mybase::swap(_Right); + _Stringbuffer._Take_contents(_STD move(_Right._Stringbuffer)); } - basic_ostringstream& operator=(basic_ostringstream&& _Right) noexcept /* strengthened */ { - _Assign_rv(_STD move(_Right)); - return *this; - } - - void _Assign_rv(basic_ostringstream&& _Right) noexcept { + basic_ostringstream& operator=(basic_ostringstream&& _Right) noexcept( + _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) /* strengthened */ { if (this != _STD addressof(_Right)) { _Mybase::swap(_Right); - _Stringbuffer._Assign_rv(_STD move(_Right._Stringbuffer)); + _Stringbuffer._Assign_rv_no_alias(_STD move(_Right._Stringbuffer)); } + return *this; } void swap(basic_ostringstream& _Right) noexcept /* strengthened */ { @@ -830,20 +893,19 @@ public: : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Str, _Mode) {} #endif // _HAS_CXX20 - basic_stringstream(basic_stringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)) { - _Assign_rv(_STD move(_Right)); + basic_stringstream(basic_stringstream&& _Right) + : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Right._Stringbuffer.get_allocator()) { + _Mybase::swap(_Right); + _Stringbuffer._Take_contents(_STD move(_Right._Stringbuffer)); } - basic_stringstream& operator=(basic_stringstream&& _Right) noexcept /* strengthened */ { - _Assign_rv(_STD move(_Right)); - return *this; - } - - void _Assign_rv(basic_stringstream&& _Right) noexcept { + basic_stringstream& operator=(basic_stringstream&& _Right) noexcept( + _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) /* strengthened */ { if (this != _STD addressof(_Right)) { _Mybase::swap(_Right); - _Stringbuffer._Assign_rv(_STD move(_Right._Stringbuffer)); + _Stringbuffer._Assign_rv_no_alias(_STD move(_Right._Stringbuffer)); } + return *this; } void swap(basic_stringstream& _Right) noexcept /* strengthened */ { diff --git a/tests/std/tests/GH_001858_iostream_exception/test.cpp b/tests/std/tests/GH_001858_iostream_exception/test.cpp index 5ddb356a1e..dee3e95d3f 100644 --- a/tests/std/tests/GH_001858_iostream_exception/test.cpp +++ b/tests/std/tests/GH_001858_iostream_exception/test.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -322,6 +323,25 @@ STATIC_ASSERT(is_nothrow_move_assignable_v); STATIC_ASSERT(is_nothrow_move_assignable_v); STATIC_ASSERT(is_nothrow_move_assignable_v); +// GH-4232: : basic_stringbuf shouldn't implement moving with swapping +// These operations need to be able to throw exceptions when the source and target allocators are unequal. +STATIC_ASSERT( + !is_nothrow_move_assignable_v, pmr::polymorphic_allocator>>); +STATIC_ASSERT( + !is_nothrow_move_assignable_v, pmr::polymorphic_allocator>>); +STATIC_ASSERT( + !is_nothrow_move_assignable_v, pmr::polymorphic_allocator>>); +STATIC_ASSERT(!is_nothrow_move_assignable_v< + basic_istringstream, pmr::polymorphic_allocator>>); +STATIC_ASSERT( + !is_nothrow_move_assignable_v, pmr::polymorphic_allocator>>); +STATIC_ASSERT(!is_nothrow_move_assignable_v< + basic_ostringstream, pmr::polymorphic_allocator>>); +STATIC_ASSERT( + !is_nothrow_move_assignable_v, pmr::polymorphic_allocator>>); +STATIC_ASSERT(!is_nothrow_move_assignable_v< + basic_stringstream, pmr::polymorphic_allocator>>); + STATIC_ASSERT(is_nothrow_std_swappable); STATIC_ASSERT(is_nothrow_std_swappable); STATIC_ASSERT(is_nothrow_std_swappable); diff --git a/tests/std/tests/P0408R7_efficient_access_to_stringbuf_buffer/test.cpp b/tests/std/tests/P0408R7_efficient_access_to_stringbuf_buffer/test.cpp index 421f9ec0f9..a4fc8a0bb3 100644 --- a/tests/std/tests/P0408R7_efficient_access_to_stringbuf_buffer/test.cpp +++ b/tests/std/tests/P0408R7_efficient_access_to_stringbuf_buffer/test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -116,6 +117,22 @@ struct test_pmr_allocator { } Stream stream2{init_value, init_value.get_allocator()}; assert(stream2.rdbuf()->get_allocator() == init_value.get_allocator()); + + // GH-4232: : basic_stringbuf shouldn't implement moving with swapping + + // Move to another stream buffer with different allocators + using SBuf = remove_pointer_t; + SBuf& sbuf = *stream.rdbuf(); + SBuf sbuf2{move(sbuf), init_value.get_allocator()}; + assert(sbuf2.get_allocator() != sbuf.get_allocator()); + assert(stream.view().empty()); + assert(sbuf2.view() == init_value); + + // Move assignment between different memory resources + sbuf = move(sbuf2); + assert(sbuf2.get_allocator() != sbuf.get_allocator()); + assert(sbuf2.view().empty()); + assert(stream.view() == init_value); } }; From 1d58403846894a3aa651aff75c59b2060e04a627 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 6 Dec 2023 02:30:09 +0800 Subject: [PATCH 02/12] Conditional compilation --- stl/inc/sstream | 44 ++++++++++++++++--- .../GH_001858_iostream_exception/test.cpp | 2 + 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/stl/inc/sstream b/stl/inc/sstream index a4fbc50ee1..25b6670244 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -18,6 +18,12 @@ _STL_DISABLE_CLANG_WARNINGS #undef new _STD_BEGIN +#if !_HAS_CXX20 +struct _Stringbuf_from_allocator_tag { + explicit _Stringbuf_from_allocator_tag() = default; +}; +#endif // !_HAS_CXX20 + _EXPORT_STD template class basic_stringbuf : public basic_streambuf<_Elem, _Traits> { // stream buffer maintaining an allocated character array @@ -76,7 +82,13 @@ public: _Take_contents(_STD move(_Right)); } -#endif // _HAS_CXX20 +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv + basic_stringbuf(_Stringbuf_from_allocator_tag _Tag, const _Alloc& _Al_) + : basic_stringbuf(_Tag, ios_base::in | ios_base::out, _Al_) {} + + basic_stringbuf(_Stringbuf_from_allocator_tag, ios_base::openmode _Mode, const _Alloc& _Al_) + : _Seekhigh(nullptr), _Mystate(_Getstate(_Mode)), _Al(_Al_) {} +#endif // ^^^ !_HAS_CXX20 ^^^ basic_stringbuf(basic_stringbuf&& _Right) : _Seekhigh(_STD exchange(_Right._Seekhigh, nullptr)), _Mystate(_STD exchange(_Right._Mystate, 0)), @@ -287,7 +299,11 @@ public: _NODISCARD allocator_type get_allocator() const noexcept { return _Al; } -#endif // _HAS_CXX20 +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv + _NODISCARD allocator_type _Get_allocator() const noexcept { + return _Al; + } +#endif // ^^^ !_HAS_CXX20 ^^^ protected: int_type overflow(int_type _Meta = _Traits::eof()) override { // put an element to stream @@ -650,7 +666,13 @@ public: #endif // _HAS_CXX20 basic_istringstream(basic_istringstream&& _Right) - : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Right._Stringbuffer.get_allocator()) { + : _Mybase(_STD addressof(_Stringbuffer)), +#if _HAS_CXX20 + _Stringbuffer(_Right._Stringbuffer.get_allocator()) +#else // ^^^ _HAS_CXX20 / !_HAX_CXX20 vvv + _Stringbuffer(_Stringbuf_from_allocator_tag{}, _Right._Stringbuffer._Get_allocator()) +#endif // ^^^ !_HAS_CXX20 ^^^ + { _Mybase::swap(_Right); _Stringbuffer._Take_contents(_STD move(_Right._Stringbuffer)); } @@ -769,7 +791,13 @@ public: #endif // _HAS_CXX20 basic_ostringstream(basic_ostringstream&& _Right) - : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Right._Stringbuffer.get_allocator()) { + : _Mybase(_STD addressof(_Stringbuffer)), +#if _HAS_CXX20 + _Stringbuffer(_Right._Stringbuffer.get_allocator()) +#else // ^^^ _HAS_CXX20 / !_HAX_CXX20 vvv + _Stringbuffer(_Stringbuf_from_allocator_tag{}, _Right._Stringbuffer._Get_allocator()) +#endif // ^^^ !_HAS_CXX20 ^^^ + { _Mybase::swap(_Right); _Stringbuffer._Take_contents(_STD move(_Right._Stringbuffer)); } @@ -894,7 +922,13 @@ public: #endif // _HAS_CXX20 basic_stringstream(basic_stringstream&& _Right) - : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Right._Stringbuffer.get_allocator()) { + : _Mybase(_STD addressof(_Stringbuffer)), +#if _HAS_CXX20 + _Stringbuffer(_Right._Stringbuffer.get_allocator()) +#else // ^^^ _HAS_CXX20 / !_HAX_CXX20 vvv + _Stringbuffer(_Stringbuf_from_allocator_tag{}, _Right._Stringbuffer._Get_allocator()) +#endif // ^^^ !_HAS_CXX20 ^^^ + { _Mybase::swap(_Right); _Stringbuffer._Take_contents(_STD move(_Right._Stringbuffer)); } diff --git a/tests/std/tests/GH_001858_iostream_exception/test.cpp b/tests/std/tests/GH_001858_iostream_exception/test.cpp index dee3e95d3f..1e3e631a03 100644 --- a/tests/std/tests/GH_001858_iostream_exception/test.cpp +++ b/tests/std/tests/GH_001858_iostream_exception/test.cpp @@ -325,6 +325,7 @@ STATIC_ASSERT(is_nothrow_move_assignable_v); // GH-4232: : basic_stringbuf shouldn't implement moving with swapping // These operations need to be able to throw exceptions when the source and target allocators are unequal. +#if _HAS_CXX17 STATIC_ASSERT( !is_nothrow_move_assignable_v, pmr::polymorphic_allocator>>); STATIC_ASSERT( @@ -341,6 +342,7 @@ STATIC_ASSERT( !is_nothrow_move_assignable_v, pmr::polymorphic_allocator>>); STATIC_ASSERT(!is_nothrow_move_assignable_v< basic_stringstream, pmr::polymorphic_allocator>>); +#endif // _HAS_CXX17 STATIC_ASSERT(is_nothrow_std_swappable); STATIC_ASSERT(is_nothrow_std_swappable); From f17e9f814379003bc4056ac1a27d21cb3d340575 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 6 Dec 2023 09:54:43 +0800 Subject: [PATCH 03/12] Avoid double `exchange` --- stl/inc/sstream | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/sstream b/stl/inc/sstream index 25b6670244..8bdd50d05e 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -93,7 +93,7 @@ public: basic_stringbuf(basic_stringbuf&& _Right) : _Seekhigh(_STD exchange(_Right._Seekhigh, nullptr)), _Mystate(_STD exchange(_Right._Mystate, 0)), _Al(_Right._Al) { - _Take_contents(_STD move(_Right)); + _Mysb::swap(_Right); } basic_stringbuf& operator=(basic_stringbuf&& _Right) noexcept( From 0d24cf6f007068e43b3c51c07c82d5b83b72c922 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 6 Dec 2023 14:23:05 +0800 Subject: [PATCH 04/12] Avoid additional functions --- stl/inc/sstream | 50 +++++-------------------------------------------- 1 file changed, 5 insertions(+), 45 deletions(-) diff --git a/stl/inc/sstream b/stl/inc/sstream index 8bdd50d05e..8edc8b5bb3 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -18,12 +18,6 @@ _STL_DISABLE_CLANG_WARNINGS #undef new _STD_BEGIN -#if !_HAS_CXX20 -struct _Stringbuf_from_allocator_tag { - explicit _Stringbuf_from_allocator_tag() = default; -}; -#endif // !_HAS_CXX20 - _EXPORT_STD template class basic_stringbuf : public basic_streambuf<_Elem, _Traits> { // stream buffer maintaining an allocated character array @@ -82,13 +76,7 @@ public: _Take_contents(_STD move(_Right)); } -#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv - basic_stringbuf(_Stringbuf_from_allocator_tag _Tag, const _Alloc& _Al_) - : basic_stringbuf(_Tag, ios_base::in | ios_base::out, _Al_) {} - - basic_stringbuf(_Stringbuf_from_allocator_tag, ios_base::openmode _Mode, const _Alloc& _Al_) - : _Seekhigh(nullptr), _Mystate(_Getstate(_Mode)), _Al(_Al_) {} -#endif // ^^^ !_HAS_CXX20 ^^^ +#endif // _HAS_CXX20 basic_stringbuf(basic_stringbuf&& _Right) : _Seekhigh(_STD exchange(_Right._Seekhigh, nullptr)), _Mystate(_STD exchange(_Right._Mystate, 0)), @@ -299,11 +287,7 @@ public: _NODISCARD allocator_type get_allocator() const noexcept { return _Al; } -#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv - _NODISCARD allocator_type _Get_allocator() const noexcept { - return _Al; - } -#endif // ^^^ !_HAS_CXX20 ^^^ +#endif // _HAS_CXX20 protected: int_type overflow(int_type _Meta = _Traits::eof()) override { // put an element to stream @@ -667,15 +651,7 @@ public: basic_istringstream(basic_istringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)), -#if _HAS_CXX20 - _Stringbuffer(_Right._Stringbuffer.get_allocator()) -#else // ^^^ _HAS_CXX20 / !_HAX_CXX20 vvv - _Stringbuffer(_Stringbuf_from_allocator_tag{}, _Right._Stringbuffer._Get_allocator()) -#endif // ^^^ !_HAS_CXX20 ^^^ - { - _Mybase::swap(_Right); - _Stringbuffer._Take_contents(_STD move(_Right._Stringbuffer)); - } + _Stringbuffer((void) _Mybase::swap(_Right), _STD move(_Right._Stringbuffer)) {} basic_istringstream& operator=(basic_istringstream&& _Right) noexcept( _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) /* strengthened */ { @@ -792,15 +768,7 @@ public: basic_ostringstream(basic_ostringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)), -#if _HAS_CXX20 - _Stringbuffer(_Right._Stringbuffer.get_allocator()) -#else // ^^^ _HAS_CXX20 / !_HAX_CXX20 vvv - _Stringbuffer(_Stringbuf_from_allocator_tag{}, _Right._Stringbuffer._Get_allocator()) -#endif // ^^^ !_HAS_CXX20 ^^^ - { - _Mybase::swap(_Right); - _Stringbuffer._Take_contents(_STD move(_Right._Stringbuffer)); - } + _Stringbuffer((void) _Mybase::swap(_Right), _STD move(_Right._Stringbuffer)) {} basic_ostringstream& operator=(basic_ostringstream&& _Right) noexcept( _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) /* strengthened */ { @@ -923,15 +891,7 @@ public: basic_stringstream(basic_stringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)), -#if _HAS_CXX20 - _Stringbuffer(_Right._Stringbuffer.get_allocator()) -#else // ^^^ _HAS_CXX20 / !_HAX_CXX20 vvv - _Stringbuffer(_Stringbuf_from_allocator_tag{}, _Right._Stringbuffer._Get_allocator()) -#endif // ^^^ !_HAS_CXX20 ^^^ - { - _Mybase::swap(_Right); - _Stringbuffer._Take_contents(_STD move(_Right._Stringbuffer)); - } + _Stringbuffer((void) _Mybase::swap(_Right), _STD move(_Right._Stringbuffer)) {} basic_stringstream& operator=(basic_stringstream&& _Right) noexcept( _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) /* strengthened */ { From ee2592a5ebecda7cc1b991fe96df20000402c6ee Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 6 Dec 2023 14:56:26 +0800 Subject: [PATCH 05/12] Missed parentheses --- stl/inc/sstream | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/sstream b/stl/inc/sstream index 8edc8b5bb3..6228ba8ac7 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -651,7 +651,7 @@ public: basic_istringstream(basic_istringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)), - _Stringbuffer((void) _Mybase::swap(_Right), _STD move(_Right._Stringbuffer)) {} + _Stringbuffer(((void) _Mybase::swap(_Right), _STD move(_Right._Stringbuffer))) {} basic_istringstream& operator=(basic_istringstream&& _Right) noexcept( _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) /* strengthened */ { @@ -768,7 +768,7 @@ public: basic_ostringstream(basic_ostringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)), - _Stringbuffer((void) _Mybase::swap(_Right), _STD move(_Right._Stringbuffer)) {} + _Stringbuffer(((void) _Mybase::swap(_Right), _STD move(_Right._Stringbuffer))) {} basic_ostringstream& operator=(basic_ostringstream&& _Right) noexcept( _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) /* strengthened */ { @@ -891,7 +891,7 @@ public: basic_stringstream(basic_stringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)), - _Stringbuffer((void) _Mybase::swap(_Right), _STD move(_Right._Stringbuffer)) {} + _Stringbuffer(((void) _Mybase::swap(_Right), _STD move(_Right._Stringbuffer))) {} basic_stringstream& operator=(basic_stringstream&& _Right) noexcept( _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) /* strengthened */ { From 931310e812060664fe17daf9a863dbc39f51f855 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Thu, 7 Dec 2023 10:20:33 +0800 Subject: [PATCH 06/12] Fix bad self move assignment --- stl/inc/sstream | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/sstream b/stl/inc/sstream index 6228ba8ac7..238b70f7bf 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -146,7 +146,7 @@ public: } } else { if constexpr (_Choose_pocma_v<_Alloc> == _Pocma_values::_Propagate_allocators) { - _Al = _STD move(_Al); + _Al = _STD move(_Right._Al); } _Take_contents(_STD move(_Right)); } From 3f5a32702b955f1c9f786e5265edf93d7c994d2a Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sun, 17 Dec 2023 02:36:28 +0800 Subject: [PATCH 07/12] Unblock one libcxx test --- tests/libcxx/expected_results.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index aa7119f94a..30e68a87ac 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -513,9 +513,6 @@ std/strings/basic.string/string.modifiers/robust_against_adl.pass.cpp FAIL # GH-3100: etc.: ADL should be avoided when calling _Construct_in_place and its friends std/utilities/function.objects/func.wrap/func.wrap.func/robust_against_adl.pass.cpp FAIL -# GH-4232: : basic_stringbuf shouldn't implement moving with swapping -std/input.output/string.streams/stringbuf/stringbuf.cons/move.alloc.pass.cpp FAIL - # GH-4238: : file_clock::to_utc() overflows for file_time # This test also has a bogus assumption about the file_time epoch, and file_time is doomed on Windows. std/time/time.clock/time.clock.file/ostream.pass.cpp FAIL From 45fd4024a0e3168ebda4504ce7b79bcad0b8a074 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 23 Jan 2024 18:06:56 -0800 Subject: [PATCH 08/12] `` is C++17. --- tests/std/tests/GH_001858_iostream_exception/test.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/std/tests/GH_001858_iostream_exception/test.cpp b/tests/std/tests/GH_001858_iostream_exception/test.cpp index 1e3e631a03..9b9bc47ef2 100644 --- a/tests/std/tests/GH_001858_iostream_exception/test.cpp +++ b/tests/std/tests/GH_001858_iostream_exception/test.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -16,6 +15,10 @@ #include #include +#if _HAS_CXX17 +#include +#endif // _HAS_CXX17 + #if _HAS_CXX20 #include #endif // _HAS_CXX20 From 2d51a1adbb72a0ce35424962b9755315e2ec64d1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 23 Jan 2024 18:30:29 -0800 Subject: [PATCH 09/12] Style: Exchange `_Seekhigh` before `_Mystate`. --- stl/inc/sstream | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/sstream b/stl/inc/sstream index 6df07aa77a..742014dc08 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -94,8 +94,8 @@ public: void _Take_contents(basic_stringbuf&& _Right) noexcept { // pre: *this holds no dynamic buffer and _Al == _Right._Al - _Mystate = _STD exchange(_Right._Mystate, 0); _Seekhigh = _STD exchange(_Right._Seekhigh, nullptr); + _Mystate = _STD exchange(_Right._Mystate, 0); _Mysb::swap(_Right); } From 98fcc227a4ddaa75e62694a75974e15f9e35702f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 23 Jan 2024 18:33:20 -0800 Subject: [PATCH 10/12] Bugfix: Initialize `_Seekhigh`. --- stl/inc/sstream | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/sstream b/stl/inc/sstream index 742014dc08..6fb0181888 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -66,7 +66,7 @@ public: const basic_string<_Elem, _Traits, _Alloc2>& _Str, ios_base::openmode _Mode = ios_base::in | ios_base::out) : basic_stringbuf(_Str, _Mode, _Alloc{}) {} - basic_stringbuf(basic_stringbuf&& _Right, const _Alloc& _Al_) : _Mystate(0), _Al(_Al_) { + basic_stringbuf(basic_stringbuf&& _Right, const _Alloc& _Al_) : _Seekhigh(nullptr), _Mystate(0), _Al(_Al_) { if constexpr (!allocator_traits<_Alloc>::is_always_equal::value) { if (_Al != _Right._Al) { _Copy_into_self_and_tidy(_STD move(_Right)); From bada8fa5e877ef748919946ea71d80768ced47a7 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 23 Jan 2024 19:13:30 -0800 Subject: [PATCH 11/12] Bugfix: Use `_Pocma()`, which we want even when `is_always_equal`. --- stl/inc/sstream | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stl/inc/sstream b/stl/inc/sstream index 6fb0181888..669ff8d1d1 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -145,9 +145,7 @@ public: _Copy_into_self_and_tidy(_STD move(_Right)); } } else { - if constexpr (_Choose_pocma_v<_Alloc> == _Pocma_values::_Propagate_allocators) { - _Al = _STD move(_Right._Al); - } + _Pocma(_Al, _Right._Al); _Take_contents(_STD move(_Right)); } } From f1c6d4cf225b3cb9fa58f1acb68495e50b437fa0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 23 Jan 2024 19:14:15 -0800 Subject: [PATCH 12/12] Simplify: `_Mybase::swap` always returns `void`. --- stl/inc/sstream | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/sstream b/stl/inc/sstream index 669ff8d1d1..2a0ae5136d 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -649,7 +649,7 @@ public: basic_istringstream(basic_istringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)), - _Stringbuffer(((void) _Mybase::swap(_Right), _STD move(_Right._Stringbuffer))) {} + _Stringbuffer((_Mybase::swap(_Right), _STD move(_Right._Stringbuffer))) {} basic_istringstream& operator=(basic_istringstream&& _Right) noexcept( _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) /* strengthened */ { @@ -766,7 +766,7 @@ public: basic_ostringstream(basic_ostringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)), - _Stringbuffer(((void) _Mybase::swap(_Right), _STD move(_Right._Stringbuffer))) {} + _Stringbuffer((_Mybase::swap(_Right), _STD move(_Right._Stringbuffer))) {} basic_ostringstream& operator=(basic_ostringstream&& _Right) noexcept( _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) /* strengthened */ { @@ -889,7 +889,7 @@ public: basic_stringstream(basic_stringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)), - _Stringbuffer(((void) _Mybase::swap(_Right), _STD move(_Right._Stringbuffer))) {} + _Stringbuffer((_Mybase::swap(_Right), _STD move(_Right._Stringbuffer))) {} basic_stringstream& operator=(basic_stringstream&& _Right) noexcept( _Choose_pocma_v<_Alloc> != _Pocma_values::_No_propagate_allocators) /* strengthened */ {