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<char_type, traits_type, allocator_type> str() const; @@ -57,8 +58,8 @@ // [stringbuf.assign] non member swap template <class charT, class traits, class Allocator> - void swap(basic_stringbuf<charT, traits, Allocator>& x, - basic_stringbuf<charT, traits, Allocator>& y); +void swap(basic_stringbuf<charT, traits, Allocator>& x, + basic_stringbuf<charT, traits, Allocator>& y); // noexcept(see below) since C++20 typedef basic_stringbuf<char> stringbuf; typedef basic_stringbuf<wchar_t> wstringbuf; @@ -97,8 +98,8 @@ }; template <class charT, class traits, class Allocator> - void swap(basic_istringstream<charT, traits, Allocator>& x, - basic_istringstream<charT, traits, Allocator>& y); +void swap(basic_istringstream<charT, traits, Allocator>& x, + basic_istringstream<charT, traits, Allocator>& y); typedef basic_istringstream<char> istringstream; typedef basic_istringstream<wchar_t> wistringstream; @@ -138,8 +139,8 @@ }; template <class charT, class traits, class Allocator> - void swap(basic_ostringstream<charT, traits, Allocator>& x, - basic_ostringstream<charT, traits, Allocator>& y); +void swap(basic_ostringstream<charT, traits, Allocator>& x, + basic_ostringstream<charT, traits, Allocator>& y); typedef basic_ostringstream<char> ostringstream; typedef basic_ostringstream<wchar_t> wostringstream; @@ -179,8 +180,8 @@ }; template <class charT, class traits, class Allocator> - void swap(basic_stringstream<charT, traits, Allocator>& x, - basic_stringstream<charT, traits, Allocator>& y); +void swap(basic_stringstream<charT, traits, Allocator>& x, + basic_stringstream<charT, traits, Allocator>& y); typedef basic_stringstream<char> stringstream; typedef basic_stringstream<wchar_t> 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<allocator_type>::propagate_on_container_swap::value || + allocator_traits<allocator_type>::is_always_equal::value) +#endif + ; // [stringbuf.members] Member functions: string_type str() const; @@ -368,6 +374,10 @@ template <class _CharT, class _Traits, class _Allocator> 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<char_type*>(__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 + +// <sstream> + +// template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> > +// class basic_stringbuf + +// void swap(basic_stringbuf& rhs) +// noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value || +// allocator_traits<allocator_type>::is_always_equal::value); + +#include <sstream> +#include <cassert> + +#include "test_macros.h" + +template <class T> +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 <class T> +struct some_alloc2 : some_alloc<T> { + using propagate_on_container_swap = std::false_type; + using is_always_equal = std::true_type; +}; + +template <class T> +struct some_alloc3 : some_alloc2<T> { + using is_always_equal = std::false_type; +}; + +template <class CharT> +static void test() { + { + std::basic_stringbuf<CharT, std::char_traits<CharT>, some_alloc<CharT>> buf1; + std::basic_stringbuf<CharT, std::char_traits<CharT>, some_alloc<CharT>> buf; + static_assert(noexcept(buf.swap(buf1))); + } + { + std::basic_stringbuf<CharT, std::char_traits<CharT>, some_alloc2<CharT>> buf1; + std::basic_stringbuf<CharT, std::char_traits<CharT>, some_alloc2<CharT>> buf; + static_assert(noexcept(buf.swap(buf1))); + } + { + std::basic_stringbuf<CharT, std::char_traits<CharT>, some_alloc3<CharT>> buf1; + std::basic_stringbuf<CharT, std::char_traits<CharT>, some_alloc3<CharT>> buf; + static_assert(!noexcept(buf.swap(buf1))); + } +} + +int main(int, char**) { + test<char>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test<wchar_t>(); +#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 + +// <sstream> + +// template <class charT, class traits, class Allocator> +// void swap(basic_stringbuf<charT, traits, Allocator>& x, +// basic_stringbuf<charT, traits, Allocator>& y) +// noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value || +// allocator_traits<allocator_type>::is_always_equal::value); + +#include <sstream> +#include <cassert> + +#include "test_macros.h" + +template <class T> +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 <class T> +struct some_alloc2 : some_alloc<T> { + using propagate_on_container_swap = std::false_type; + using is_always_equal = std::true_type; +}; + +template <class T> +struct some_alloc3 : some_alloc2<T> { + using is_always_equal = std::false_type; +}; + +template <class CharT> +static void test() { + { + std::basic_stringbuf<CharT, std::char_traits<CharT>, some_alloc<CharT>> buf1; + std::basic_stringbuf<CharT, std::char_traits<CharT>, some_alloc<CharT>> buf; + static_assert(noexcept(swap(buf, buf1))); + } + { + std::basic_stringbuf<CharT, std::char_traits<CharT>, some_alloc2<CharT>> buf1; + std::basic_stringbuf<CharT, std::char_traits<CharT>, some_alloc2<CharT>> buf; + static_assert(noexcept(swap(buf, buf1))); + } + { + std::basic_stringbuf<CharT, std::char_traits<CharT>, some_alloc3<CharT>> buf1; + std::basic_stringbuf<CharT, std::char_traits<CharT>, some_alloc3<CharT>> buf; + static_assert(!noexcept(swap(buf, buf1))); + } +} + +int main(int, char**) { + test<char>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test<wchar_t>(); +#endif + return 0; +}