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