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: with_system_cxx_lib=macosx10.12
13// XFAIL: with_system_cxx_lib=macosx10.11
14// XFAIL: with_system_cxx_lib=macosx10.10
15// XFAIL: with_system_cxx_lib=macosx10.9
16// XFAIL: with_system_cxx_lib=macosx10.7
17// XFAIL: with_system_cxx_lib=macosx10.8
18
19// <any>
20
21// any(any &&) noexcept;
22
23#include <any>
24#include <utility>
25#include <type_traits>
26#include <cassert>
27
28#include "any_helpers.h"
29#include "count_new.hpp"
30#include "test_macros.h"
31
32using std::any;
33using std::any_cast;
34
35// Moves are always noexcept. The throws_on_move object
36// must be stored dynamically so the pointer is moved and
37// not the stored object.
38void test_move_does_not_throw()
39{
40#if !defined(TEST_HAS_NO_EXCEPTIONS)
41    assert(throws_on_move::count == 0);
42    {
43        throws_on_move v(42);
44        any a(v);
45        assert(throws_on_move::count == 2);
46        // No allocations should be performed after this point.
47        DisableAllocationGuard g; ((void)g);
48        try {
49            any const a2(std::move(a));
50            assertEmpty(a);
51            assertContains<throws_on_move>(a2, 42);
52        } catch (...) {
53            assert(false);
54        }
55        assert(throws_on_move::count == 1);
56        assertEmpty(a);
57    }
58    assert(throws_on_move::count == 0);
59#endif
60}
61
62void test_move_empty() {
63    DisableAllocationGuard g; ((void)g); // no allocations should be performed.
64
65    any a1;
66    any a2(std::move(a1));
67
68    assertEmpty(a1);
69    assertEmpty(a2);
70}
71
72template <class Type>
73void test_move() {
74    assert(Type::count == 0);
75    Type::reset();
76    {
77        any a((Type(42)));
78        assert(Type::count == 1);
79        assert(Type::copied == 0);
80        assert(Type::moved == 1);
81
82        // Moving should not perform allocations since it must be noexcept.
83        DisableAllocationGuard g; ((void)g);
84
85        any a2(std::move(a));
86
87        assert(Type::moved == 1 || Type::moved == 2); // zero or more move operations can be performed.
88        assert(Type::copied == 0); // no copies can be performed.
89        assert(Type::count == 1 + a.has_value());
90        assertContains<Type>(a2, 42);
91        LIBCPP_ASSERT(!a.has_value()); // Moves are always destructive.
92        if (a.has_value())
93            assertContains<Type>(a, 0);
94    }
95    assert(Type::count == 0);
96}
97
98int main()
99{
100    // noexcept test
101    {
102        static_assert(
103            std::is_nothrow_move_constructible<any>::value
104          , "any must be nothrow move constructible"
105          );
106    }
107    test_move<small>();
108    test_move<large>();
109    test_move_empty();
110    test_move_does_not_throw();
111}
112