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