1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14
10 
11 // Throwing bad_any_cast is supported starting in macosx10.13
12 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12}} && !no-exceptions
13 
14 // <any>
15 
16 // any(any &&) noexcept;
17 
18 #include <any>
19 #include <utility>
20 #include <type_traits>
21 #include <cassert>
22 
23 #include "any_helpers.h"
24 #include "count_new.h"
25 #include "test_macros.h"
26 
27 // Moves are always noexcept. The throws_on_move object
28 // must be stored dynamically so the pointer is moved and
29 // not the stored object.
test_move_does_not_throw()30 void test_move_does_not_throw()
31 {
32 #if !defined(TEST_HAS_NO_EXCEPTIONS)
33     assert(throws_on_move::count == 0);
34     {
35         throws_on_move v(42);
36         std::any a = v;
37         assert(throws_on_move::count == 2);
38         // No allocations should be performed after this point.
39         DisableAllocationGuard g; ((void)g);
40         try {
41             const std::any a2 = std::move(a);
42             assertEmpty(a);
43             assertContains<throws_on_move>(a2, 42);
44         } catch (...) {
45             assert(false);
46         }
47         assert(throws_on_move::count == 1);
48         assertEmpty(a);
49     }
50     assert(throws_on_move::count == 0);
51 #endif
52 }
53 
test_move_empty()54 void test_move_empty() {
55     DisableAllocationGuard g; ((void)g); // no allocations should be performed.
56 
57     std::any a1;
58     std::any a2 = std::move(a1);
59 
60     assertEmpty(a1);
61     assertEmpty(a2);
62 }
63 
64 template <class Type>
test_move()65 void test_move() {
66     assert(Type::count == 0);
67     Type::reset();
68     {
69         std::any a = Type(42);
70         assert(Type::count == 1);
71         assert(Type::copied == 0);
72         assert(Type::moved == 1);
73 
74         // Moving should not perform allocations since it must be noexcept.
75         DisableAllocationGuard g; ((void)g);
76 
77         std::any a2 = std::move(a);
78 
79         assert(Type::moved == 1 || Type::moved == 2); // zero or more move operations can be performed.
80         assert(Type::copied == 0); // no copies can be performed.
81         assert(Type::count == 1 + a.has_value());
82         assertContains<Type>(a2, 42);
83         LIBCPP_ASSERT(!a.has_value()); // Moves are always destructive.
84         if (a.has_value())
85             assertContains<Type>(a, 0);
86     }
87     assert(Type::count == 0);
88 }
89 
main(int,char **)90 int main(int, char**)
91 {
92     // noexcept test
93     static_assert(std::is_nothrow_move_constructible<std::any>::value);
94 
95     test_move<small>();
96     test_move<large>();
97     test_move_empty();
98     test_move_does_not_throw();
99 
100   return 0;
101 }
102