15a83710eSEric Fiselier //===----------------------------------------------------------------------===//
25a83710eSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a83710eSEric Fiselier //
75a83710eSEric Fiselier //===----------------------------------------------------------------------===//
85a83710eSEric Fiselier
931cbe0f2SLouis Dionne // UNSUPPORTED: c++03
101f4231f8SEric Fiselier
115a83710eSEric Fiselier // <string>
125a83710eSEric Fiselier
135a83710eSEric Fiselier // basic_string& operator=(basic_string&& c)
145a83710eSEric Fiselier // noexcept(
151378a5aeSMarshall Clow // allocator_traits<allocator_type>::propagate_on_container_move_assignment::value ||
16*425620ccSNikolas Klauser // allocator_traits<allocator_type>::is_always_equal::value); // C++17, constexpr since C++20
171378a5aeSMarshall Clow //
181378a5aeSMarshall Clow // before C++17, we use the conforming extension
191378a5aeSMarshall Clow // noexcept(
205a83710eSEric Fiselier // allocator_type::propagate_on_container_move_assignment::value &&
21*425620ccSNikolas Klauser // is_nothrow_move_assignable<allocator_type>::value); // constexpr since C++20
225a83710eSEric Fiselier
235a83710eSEric Fiselier #include <string>
245a83710eSEric Fiselier #include <cassert>
255a83710eSEric Fiselier
261378a5aeSMarshall Clow #include "test_macros.h"
275a83710eSEric Fiselier #include "test_allocator.h"
285a83710eSEric Fiselier
295a83710eSEric Fiselier template <class T>
305a83710eSEric Fiselier struct some_alloc
315a83710eSEric Fiselier {
325a83710eSEric Fiselier typedef T value_type;
335a83710eSEric Fiselier some_alloc(const some_alloc&);
3476b26852SMarshall Clow T *allocate(size_t);
355a83710eSEric Fiselier };
365a83710eSEric Fiselier
371378a5aeSMarshall Clow template <class T>
381378a5aeSMarshall Clow struct some_alloc2
391378a5aeSMarshall Clow {
401378a5aeSMarshall Clow typedef T value_type;
411378a5aeSMarshall Clow
some_alloc2some_alloc2421378a5aeSMarshall Clow some_alloc2() {}
431378a5aeSMarshall Clow some_alloc2(const some_alloc2&);
4476b26852SMarshall Clow T *allocate(size_t);
deallocatesome_alloc2451378a5aeSMarshall Clow void deallocate(void*, unsigned) {}
461378a5aeSMarshall Clow
471378a5aeSMarshall Clow typedef std::false_type propagate_on_container_move_assignment;
481378a5aeSMarshall Clow typedef std::true_type is_always_equal;
491378a5aeSMarshall Clow };
501378a5aeSMarshall Clow
511378a5aeSMarshall Clow template <class T>
521378a5aeSMarshall Clow struct some_alloc3
531378a5aeSMarshall Clow {
541378a5aeSMarshall Clow typedef T value_type;
551378a5aeSMarshall Clow
some_alloc3some_alloc3561378a5aeSMarshall Clow some_alloc3() {}
571378a5aeSMarshall Clow some_alloc3(const some_alloc3&);
5876b26852SMarshall Clow T *allocate(size_t);
deallocatesome_alloc3591378a5aeSMarshall Clow void deallocate(void*, unsigned) {}
601378a5aeSMarshall Clow
611378a5aeSMarshall Clow typedef std::false_type propagate_on_container_move_assignment;
621378a5aeSMarshall Clow typedef std::false_type is_always_equal;
631378a5aeSMarshall Clow };
641378a5aeSMarshall Clow
test()65*425620ccSNikolas Klauser TEST_CONSTEXPR_CXX20 bool test() {
665a83710eSEric Fiselier {
675a83710eSEric Fiselier typedef std::string C;
685a83710eSEric Fiselier static_assert(std::is_nothrow_move_assignable<C>::value, "");
695a83710eSEric Fiselier }
705a83710eSEric Fiselier {
715a83710eSEric Fiselier typedef std::basic_string<char, std::char_traits<char>, test_allocator<char>> C;
725a83710eSEric Fiselier static_assert(!std::is_nothrow_move_assignable<C>::value, "");
735a83710eSEric Fiselier }
745a83710eSEric Fiselier {
755a83710eSEric Fiselier typedef std::basic_string<char, std::char_traits<char>, some_alloc<char>> C;
761378a5aeSMarshall Clow #if TEST_STD_VER > 14
771378a5aeSMarshall Clow // if the allocators are always equal, then the move assignment can be noexcept
781378a5aeSMarshall Clow static_assert( std::is_nothrow_move_assignable<C>::value, "");
791378a5aeSMarshall Clow #else
801378a5aeSMarshall Clow static_assert(!std::is_nothrow_move_assignable<C>::value, "");
811378a5aeSMarshall Clow #endif
821378a5aeSMarshall Clow }
831378a5aeSMarshall Clow #if TEST_STD_VER > 14
841378a5aeSMarshall Clow {
851378a5aeSMarshall Clow // POCMA is false, always equal
861378a5aeSMarshall Clow typedef std::basic_string<char, std::char_traits<char>, some_alloc2<char>> C;
871378a5aeSMarshall Clow static_assert( std::is_nothrow_move_assignable<C>::value, "");
881378a5aeSMarshall Clow }
891378a5aeSMarshall Clow {
901378a5aeSMarshall Clow // POCMA is false, not always equal
911378a5aeSMarshall Clow typedef std::basic_string<char, std::char_traits<char>, some_alloc3<char>> C;
925a83710eSEric Fiselier static_assert(!std::is_nothrow_move_assignable<C>::value, "");
935a83710eSEric Fiselier }
945a83710eSEric Fiselier #endif
952df59c50SJF Bastien
96e85018b7SNikolas Klauser return true;
97e85018b7SNikolas Klauser }
98e85018b7SNikolas Klauser
main(int,char **)99e85018b7SNikolas Klauser int main(int, char**)
100e85018b7SNikolas Klauser {
101e85018b7SNikolas Klauser test();
102e85018b7SNikolas Klauser #if TEST_STD_VER > 17
103*425620ccSNikolas Klauser static_assert(test());
104e85018b7SNikolas Klauser #endif
105e85018b7SNikolas Klauser
1062df59c50SJF Bastien return 0;
1075a83710eSEric Fiselier }
108