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++98, c++03, c++11, c++14
10
11 // XFAIL: dylib-has-no-bad_any_cast && !libcpp-no-exceptions
12
13 // <any>
14
15 // template <class ValueType>
16 // ValueType const any_cast(any const&);
17 //
18 // template <class ValueType>
19 // ValueType any_cast(any &);
20 //
21 // template <class ValueType>
22 // ValueType any_cast(any &&);
23
24 #include <any>
25 #include <type_traits>
26 #include <cassert>
27
28 #include "any_helpers.h"
29 #include "count_new.h"
30 #include "test_macros.h"
31
32 using std::any;
33 using std::any_cast;
34 using std::bad_any_cast;
35
36
37 // Test that the operators are NOT marked noexcept.
test_cast_is_not_noexcept()38 void test_cast_is_not_noexcept() {
39 any a;
40 static_assert(!noexcept(any_cast<int>(static_cast<any&>(a))), "");
41 static_assert(!noexcept(any_cast<int>(static_cast<any const&>(a))), "");
42 static_assert(!noexcept(any_cast<int>(static_cast<any &&>(a))), "");
43 }
44
45 // Test that the return type of any_cast is correct.
test_cast_return_type()46 void test_cast_return_type() {
47 any a;
48 static_assert(std::is_same<decltype(any_cast<int>(a)), int>::value, "");
49 static_assert(std::is_same<decltype(any_cast<int const>(a)), int>::value, "");
50 static_assert(std::is_same<decltype(any_cast<int&>(a)), int&>::value, "");
51 static_assert(std::is_same<decltype(any_cast<int const&>(a)), int const&>::value, "");
52
53 static_assert(std::is_same<decltype(any_cast<int&&>(a)), int&&>::value, "");
54 static_assert(std::is_same<decltype(any_cast<int const&&>(a)), int const&&>::value, "");
55
56 static_assert(std::is_same<decltype(any_cast<int>(std::move(a))), int>::value, "");
57 static_assert(std::is_same<decltype(any_cast<int const>(std::move(a))), int>::value, "");
58 static_assert(std::is_same<decltype(any_cast<int&>(std::move(a))), int&>::value, "");
59 static_assert(std::is_same<decltype(any_cast<int const&>(std::move(a))), int const&>::value, "");
60
61 static_assert(std::is_same<decltype(any_cast<int&&>(std::move(a))), int&&>::value, "");
62 static_assert(std::is_same<decltype(any_cast<int const&&>(std::move(a))), int const&&>::value, "");
63
64 any const& ca = a;
65 static_assert(std::is_same<decltype(any_cast<int>(ca)), int>::value, "");
66 static_assert(std::is_same<decltype(any_cast<int const>(ca)), int>::value, "");
67 static_assert(std::is_same<decltype(any_cast<int const&>(ca)), int const&>::value, "");
68
69 static_assert(std::is_same<decltype(any_cast<int const&&>(ca)), int const&&>::value, "");
70 }
71
72 template <class Type, class ConstT = Type>
checkThrows(any & a)73 void checkThrows(any& a)
74 {
75 #if !defined(TEST_HAS_NO_EXCEPTIONS)
76 try {
77 TEST_IGNORE_NODISCARD any_cast<Type>(a);
78 assert(false);
79 } catch (bad_any_cast const &) {
80 // do nothing
81 } catch (...) {
82 assert(false);
83 }
84
85 try {
86 TEST_IGNORE_NODISCARD any_cast<ConstT>(static_cast<any const&>(a));
87 assert(false);
88 } catch (bad_any_cast const &) {
89 // do nothing
90 } catch (...) {
91 assert(false);
92 }
93
94 try {
95 using RefType = typename std::conditional<
96 std::is_lvalue_reference<Type>::value,
97 typename std::remove_reference<Type>::type&&,
98 Type
99 >::type;
100 TEST_IGNORE_NODISCARD any_cast<RefType>(static_cast<any&&>(a));
101 assert(false);
102 } catch (bad_any_cast const &) {
103 // do nothing
104 } catch (...) {
105 assert(false);
106 }
107 #else
108 (TEST_IGNORE_NODISCARD a);
109 #endif
110 }
111
test_cast_empty()112 void test_cast_empty() {
113 // None of these operations should allocate.
114 DisableAllocationGuard g; (TEST_IGNORE_NODISCARD g);
115 any a;
116 checkThrows<int>(a);
117 }
118
119 template <class Type>
test_cast_to_reference()120 void test_cast_to_reference() {
121 assert(Type::count == 0);
122 Type::reset();
123 {
124 any a((Type(42)));
125 any const& ca = a;
126 assert(Type::count == 1);
127 assert(Type::copied == 0);
128 assert(Type::moved == 1);
129
130 // Try a cast to a bad type.
131 // NOTE: Type cannot be an int.
132 checkThrows<int>(a);
133 checkThrows<int&, int const&>(a);
134 checkThrows<Type*, Type const*>(a);
135 checkThrows<Type const*>(a);
136
137 // Check getting a type by reference from a non-const lvalue any.
138 {
139 Type& v = any_cast<Type&>(a);
140 assert(v.value == 42);
141
142 Type const &cv = any_cast<Type const&>(a);
143 assert(&cv == &v);
144 }
145 // Check getting a type by reference from a const lvalue any.
146 {
147 Type const& v = any_cast<Type const&>(ca);
148 assert(v.value == 42);
149
150 Type const &cv = any_cast<Type const&>(ca);
151 assert(&cv == &v);
152 }
153 // Check getting a type by reference from a const rvalue any.
154 {
155 Type const& v = any_cast<Type const&>(std::move(ca));
156 assert(v.value == 42);
157
158 Type const &cv = any_cast<Type const&>(std::move(ca));
159 assert(&cv == &v);
160 }
161 // Check getting a type by reference from a const rvalue any.
162 {
163 Type&& v = any_cast<Type&&>(std::move(a));
164 assert(v.value == 42);
165 assert(any_cast<Type&>(a).value == 42);
166
167 Type&& cv = any_cast<Type&&>(std::move(a));
168 assert(&cv == &v);
169 assert(any_cast<Type&>(a).value == 42);
170 }
171 // Check getting a type by reference from a const rvalue any.
172 {
173 Type const&& v = any_cast<Type const&&>(std::move(a));
174 assert(v.value == 42);
175 assert(any_cast<Type&>(a).value == 42);
176
177 Type const&& cv = any_cast<Type const&&>(std::move(a));
178 assert(&cv == &v);
179 assert(any_cast<Type&>(a).value == 42);
180 }
181 // Check that the original object hasn't been changed.
182 assertContains<Type>(a, 42);
183
184 // Check that no objects have been created/copied/moved.
185 assert(Type::count == 1);
186 assert(Type::copied == 0);
187 assert(Type::moved == 1);
188 }
189 assert(Type::count == 0);
190 }
191
192 template <class Type>
test_cast_to_value()193 void test_cast_to_value() {
194 assert(Type::count == 0);
195 Type::reset();
196 {
197 any a((Type(42)));
198 assert(Type::count == 1);
199 assert(Type::copied == 0);
200 assert(Type::moved == 1);
201
202 // Try a cast to a bad type.
203 // NOTE: Type cannot be an int.
204 checkThrows<int>(a);
205 checkThrows<int&, int const&>(a);
206 checkThrows<Type*, Type const*>(a);
207 checkThrows<Type const*>(a);
208
209 Type::reset(); // NOTE: reset does not modify Type::count
210 // Check getting Type by value from a non-const lvalue any.
211 // This should cause the non-const copy constructor to be called.
212 {
213 Type t = any_cast<Type>(a);
214
215 assert(Type::count == 2);
216 assert(Type::copied == 1);
217 assert(Type::const_copied == 0);
218 assert(Type::non_const_copied == 1);
219 assert(Type::moved == 0);
220 assert(t.value == 42);
221 }
222 assert(Type::count == 1);
223 Type::reset();
224 // Check getting const Type by value from a non-const lvalue any.
225 // This should cause the const copy constructor to be called.
226 {
227 Type t = any_cast<Type const>(a);
228
229 assert(Type::count == 2);
230 assert(Type::copied == 1);
231 assert(Type::const_copied == 0);
232 assert(Type::non_const_copied == 1);
233 assert(Type::moved == 0);
234 assert(t.value == 42);
235 }
236 assert(Type::count == 1);
237 Type::reset();
238 // Check getting Type by value from a non-const lvalue any.
239 // This should cause the const copy constructor to be called.
240 {
241 Type t = any_cast<Type>(static_cast<any const&>(a));
242
243 assert(Type::count == 2);
244 assert(Type::copied == 1);
245 assert(Type::const_copied == 1);
246 assert(Type::non_const_copied == 0);
247 assert(Type::moved == 0);
248 assert(t.value == 42);
249 }
250 assert(Type::count == 1);
251 Type::reset();
252 // Check getting Type by value from a non-const rvalue any.
253 // This should cause the non-const copy constructor to be called.
254 {
255 Type t = any_cast<Type>(static_cast<any &&>(a));
256
257 assert(Type::count == 2);
258 assert(Type::moved == 1);
259 assert(Type::copied == 0);
260 assert(Type::const_copied == 0);
261 assert(Type::non_const_copied == 0);
262 assert(t.value == 42);
263 assert(any_cast<Type&>(a).value == 0);
264 any_cast<Type&>(a).value = 42; // reset the value
265 }
266 assert(Type::count == 1);
267 Type::reset();
268 // Check getting const Type by value from a non-const rvalue any.
269 // This should cause the const copy constructor to be called.
270 {
271 Type t = any_cast<Type const>(static_cast<any &&>(a));
272
273 assert(Type::count == 2);
274 assert(Type::copied == 0);
275 assert(Type::const_copied == 0);
276 assert(Type::non_const_copied == 0);
277 assert(Type::moved == 1);
278 assert(t.value == 42);
279 assert(any_cast<Type&>(a).value == 0);
280 any_cast<Type&>(a).value = 42; // reset the value
281 }
282 assert(Type::count == 1);
283 Type::reset();
284 // Check getting Type by value from a const rvalue any.
285 // This should cause the const copy constructor to be called.
286 {
287 Type t = any_cast<Type>(static_cast<any const&&>(a));
288
289 assert(Type::count == 2);
290 assert(Type::copied == 1);
291 assert(Type::const_copied == 1);
292 assert(Type::non_const_copied == 0);
293 assert(Type::moved == 0);
294 assert(t.value == 42);
295 assert(any_cast<Type&>(a).value == 42);
296 }
297 // Ensure we still only have 1 Type object alive.
298 assert(Type::count == 1);
299
300 // Check that the original object hasn't been changed.
301 assertContains<Type>(a, 42);
302 }
303 assert(Type::count == 0);
304 }
305
main(int,char **)306 int main(int, char**) {
307 test_cast_is_not_noexcept();
308 test_cast_return_type();
309 test_cast_empty();
310 test_cast_to_reference<small>();
311 test_cast_to_reference<large>();
312 test_cast_to_value<small>();
313 test_cast_to_value<large>();
314
315 return 0;
316 }
317