• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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