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 | // <any> |
12 | |
13 | // any& operator=(const any&); |
14 | |
15 | // Test copy assignment |
16 | |
17 | #include <any> |
18 | #include <cassert> |
19 | |
20 | #include "any_helpers.h" |
21 | #include "count_new.h" |
22 | #include "test_macros.h" |
23 | |
24 | template <class LHS, class RHS> |
25 | void test_copy_assign() { |
26 | assert(LHS::count == 0); |
27 | assert(RHS::count == 0); |
28 | LHS::reset(); |
29 | RHS::reset(); |
30 | { |
31 | std::any lhs = LHS(1); |
32 | const std::any rhs = RHS(2); |
33 | |
34 | assert(LHS::count == 1); |
35 | assert(RHS::count == 1); |
36 | assert(RHS::copied == 0); |
37 | |
38 | lhs = rhs; |
39 | |
40 | assert(RHS::copied == 1); |
41 | assert(LHS::count == 0); |
42 | assert(RHS::count == 2); |
43 | |
44 | assertContains<RHS>(lhs, 2); |
45 | assertContains<RHS>(rhs, 2); |
46 | } |
47 | assert(LHS::count == 0); |
48 | assert(RHS::count == 0); |
49 | } |
50 | |
51 | template <class LHS> |
52 | void test_copy_assign_empty() { |
53 | assert(LHS::count == 0); |
54 | LHS::reset(); |
55 | { |
56 | std::any lhs; |
57 | const std::any rhs = LHS(42); |
58 | |
59 | assert(LHS::count == 1); |
60 | assert(LHS::copied == 0); |
61 | |
62 | lhs = rhs; |
63 | |
64 | assert(LHS::copied == 1); |
65 | assert(LHS::count == 2); |
66 | |
67 | assertContains<LHS>(lhs, 42); |
68 | assertContains<LHS>(rhs, 42); |
69 | } |
70 | assert(LHS::count == 0); |
71 | LHS::reset(); |
72 | { |
73 | std::any lhs = LHS(1); |
74 | const std::any rhs; |
75 | |
76 | assert(LHS::count == 1); |
77 | assert(LHS::copied == 0); |
78 | |
79 | lhs = rhs; |
80 | |
81 | assert(LHS::copied == 0); |
82 | assert(LHS::count == 0); |
83 | |
84 | assertEmpty<LHS>(lhs); |
85 | assertEmpty(rhs); |
86 | } |
87 | assert(LHS::count == 0); |
88 | } |
89 | |
90 | void test_copy_assign_self() { |
91 | // empty |
92 | { |
93 | std::any a; |
94 | a = (std::any&)a; |
95 | assertEmpty(a); |
96 | assert(globalMemCounter.checkOutstandingNewEq(0)); |
97 | } |
98 | assert(globalMemCounter.checkOutstandingNewEq(0)); |
99 | // small |
100 | { |
101 | std::any a = small(1); |
102 | assert(small::count == 1); |
103 | |
104 | a = (std::any&)a; |
105 | |
106 | assert(small::count == 1); |
107 | assertContains<small>(a, 1); |
108 | assert(globalMemCounter.checkOutstandingNewEq(0)); |
109 | } |
110 | assert(small::count == 0); |
111 | assert(globalMemCounter.checkOutstandingNewEq(0)); |
112 | // large |
113 | { |
114 | std::any a = large(1); |
115 | assert(large::count == 1); |
116 | |
117 | a = (std::any&)a; |
118 | |
119 | assert(large::count == 1); |
120 | assertContains<large>(a, 1); |
121 | assert(globalMemCounter.checkOutstandingNewEq(1)); |
122 | } |
123 | assert(large::count == 0); |
124 | assert(globalMemCounter.checkOutstandingNewEq(0)); |
125 | } |
126 | |
127 | template <class Tp> |
128 | void test_copy_assign_throws() |
129 | { |
130 | #if !defined(TEST_HAS_NO_EXCEPTIONS) |
131 | auto try_throw = |
132 | [](std::any& lhs, const std::any& rhs) { |
133 | try { |
134 | lhs = rhs; |
135 | assert(false); |
136 | } catch (const my_any_exception&) { |
137 | // do nothing |
138 | } catch (...) { |
139 | assert(false); |
140 | } |
141 | }; |
142 | // const lvalue to empty |
143 | { |
144 | std::any lhs; |
145 | const std::any rhs = Tp(1); |
146 | assert(Tp::count == 1); |
147 | |
148 | try_throw(lhs, rhs); |
149 | |
150 | assert(Tp::count == 1); |
151 | assertEmpty<Tp>(lhs); |
152 | assertContains<Tp>(rhs, 1); |
153 | } |
154 | { |
155 | std::any lhs = small(2); |
156 | const std::any rhs = Tp(1); |
157 | assert(small::count == 1); |
158 | assert(Tp::count == 1); |
159 | |
160 | try_throw(lhs, rhs); |
161 | |
162 | assert(small::count == 1); |
163 | assert(Tp::count == 1); |
164 | assertContains<small>(lhs, 2); |
165 | assertContains<Tp>(rhs, 1); |
166 | } |
167 | { |
168 | std::any lhs = large(2); |
169 | const std::any rhs = Tp(1); |
170 | assert(large::count == 1); |
171 | assert(Tp::count == 1); |
172 | |
173 | try_throw(lhs, rhs); |
174 | |
175 | assert(large::count == 1); |
176 | assert(Tp::count == 1); |
177 | assertContains<large>(lhs, 2); |
178 | assertContains<Tp>(rhs, 1); |
179 | } |
180 | #endif |
181 | } |
182 | |
183 | int main(int, char**) { |
184 | globalMemCounter.reset(); |
185 | test_copy_assign<small1, small2>(); |
186 | test_copy_assign<large1, large2>(); |
187 | test_copy_assign<small, large>(); |
188 | test_copy_assign<large, small>(); |
189 | test_copy_assign_empty<small>(); |
190 | test_copy_assign_empty<large>(); |
191 | test_copy_assign_self(); |
192 | test_copy_assign_throws<small_throws_on_copy>(); |
193 | test_copy_assign_throws<large_throws_on_copy>(); |
194 | |
195 | return 0; |
196 | } |
197 | |