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