diff --git a/libcxx/include/sstream b/libcxx/include/sstream --- a/libcxx/include/sstream +++ b/libcxx/include/sstream @@ -36,7 +36,8 @@ // [stringbuf.assign] Assign and swap: basic_stringbuf& operator=(basic_stringbuf&& rhs); - void swap(basic_stringbuf& rhs); + void swap(basic_stringbuf& rhs); // before C++20 + void swap(basic_stringbuf& rhs) noexcept(see below); // C++20 // [stringbuf.members] Member functions: basic_string str() const; @@ -57,8 +58,8 @@ // [stringbuf.assign] non member swap template - void swap(basic_stringbuf& x, - basic_stringbuf& y); +void swap(basic_stringbuf& x, + basic_stringbuf& y); // noexcept(see below) since C++20 typedef basic_stringbuf stringbuf; typedef basic_stringbuf wstringbuf; @@ -97,8 +98,8 @@ }; template - void swap(basic_istringstream& x, - basic_istringstream& y); +void swap(basic_istringstream& x, + basic_istringstream& y); typedef basic_istringstream istringstream; typedef basic_istringstream wistringstream; @@ -138,8 +139,8 @@ }; template - void swap(basic_ostringstream& x, - basic_ostringstream& y); +void swap(basic_ostringstream& x, + basic_ostringstream& y); typedef basic_ostringstream ostringstream; typedef basic_ostringstream wostringstream; @@ -179,8 +180,8 @@ }; template - void swap(basic_stringstream& x, - basic_stringstream& y); +void swap(basic_stringstream& x, + basic_stringstream& y); typedef basic_stringstream stringstream; typedef basic_stringstream wstringstream; @@ -252,7 +253,12 @@ // [stringbuf.assign] Assign and swap: basic_stringbuf& operator=(basic_stringbuf&& __rhs); - void swap(basic_stringbuf& __rhs); + void swap(basic_stringbuf& __rhs) +#if _LIBCPP_STD_VER >= 20 + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value) +#endif + ; // [stringbuf.members] Member functions: string_type str() const; @@ -368,6 +374,10 @@ template void basic_stringbuf<_CharT, _Traits, _Allocator>::swap(basic_stringbuf& __rhs) +#if _LIBCPP_STD_VER >= 20 + noexcept(allocator_traits<_Allocator>::propagate_on_container_swap::value || + allocator_traits<_Allocator>::is_always_equal::value) +#endif { char_type* __p = const_cast(__rhs.__str_.data()); ptrdiff_t __rbinp = -1; @@ -447,6 +457,9 @@ void swap(basic_stringbuf<_CharT, _Traits, _Allocator>& __x, basic_stringbuf<_CharT, _Traits, _Allocator>& __y) +#if _LIBCPP_STD_VER >= 20 + noexcept(noexcept(__x.swap(__y))) +#endif { __x.swap(__y); } diff --git a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/member_swap_noexcept.pass.cpp b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/member_swap_noexcept.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/member_swap_noexcept.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template , class Allocator = allocator > +// class basic_stringbuf + +// void swap(basic_stringbuf& rhs) +// noexcept(allocator_traits::propagate_on_container_swap::value || +// allocator_traits::is_always_equal::value); + +#include +#include + +#include "test_macros.h" + +template +struct some_alloc { + using value_type = T; + + [[nodiscard]] constexpr T* allocate(std::size_t) { return nullptr; } + void deallocate(void*, unsigned) {} + + using propagate_on_container_swap = std::true_type; +}; + +template +struct some_alloc2 : some_alloc { + using propagate_on_container_swap = std::false_type; + using is_always_equal = std::true_type; +}; + +template +struct some_alloc3 : some_alloc2 { + using is_always_equal = std::false_type; +}; + +template +static void test() { + { + std::basic_stringbuf, some_alloc> buf1; + std::basic_stringbuf, some_alloc> buf; + static_assert(noexcept(buf.swap(buf1))); + } + { + std::basic_stringbuf, some_alloc2> buf1; + std::basic_stringbuf, some_alloc2> buf; + static_assert(noexcept(buf.swap(buf1))); + } + { + std::basic_stringbuf, some_alloc3> buf1; + std::basic_stringbuf, some_alloc3> buf; + static_assert(!noexcept(buf.swap(buf1))); + } +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + return 0; +} diff --git a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/nonmember_swap_noexcept.pass.cpp b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/nonmember_swap_noexcept.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/nonmember_swap_noexcept.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template +// void swap(basic_stringbuf& x, +// basic_stringbuf& y) +// noexcept(allocator_traits::propagate_on_container_swap::value || +// allocator_traits::is_always_equal::value); + +#include +#include + +#include "test_macros.h" + +template +struct some_alloc { + using value_type = T; + + [[nodiscard]] constexpr T* allocate(std::size_t) { return nullptr; } + void deallocate(void*, unsigned) {} + + using propagate_on_container_swap = std::true_type; +}; + +template +struct some_alloc2 : some_alloc { + using propagate_on_container_swap = std::false_type; + using is_always_equal = std::true_type; +}; + +template +struct some_alloc3 : some_alloc2 { + using is_always_equal = std::false_type; +}; + +template +static void test() { + { + std::basic_stringbuf, some_alloc> buf1; + std::basic_stringbuf, some_alloc> buf; + static_assert(noexcept(swap(buf, buf1))); + } + { + std::basic_stringbuf, some_alloc2> buf1; + std::basic_stringbuf, some_alloc2> buf; + static_assert(noexcept(swap(buf, buf1))); + } + { + std::basic_stringbuf, some_alloc3> buf1; + std::basic_stringbuf, some_alloc3> buf; + static_assert(!noexcept(swap(buf, buf1))); + } +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + return 0; +}