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
11
12// <experimental/any>
13
14// any& operator=(any const &);
15
16// Test copy assignment
17
18#include <experimental/any>
19#include <cassert>
20
21#include "experimental_any_helpers.h"
22#include "count_new.hpp"
23#include "test_macros.h"
24
25using std::experimental::any;
26using std::experimental::any_cast;
27
28template <class LHS, class RHS>
29void test_copy_assign() {
30    assert(LHS::count == 0);
31    assert(RHS::count == 0);
32    LHS::reset();
33    RHS::reset();
34    {
35        any lhs(LHS(1));
36        any const rhs(RHS(2));
37
38        assert(LHS::count == 1);
39        assert(RHS::count == 1);
40        assert(RHS::copied == 0);
41
42        lhs = rhs;
43
44        assert(RHS::copied == 1);
45        assert(LHS::count == 0);
46        assert(RHS::count == 2);
47
48        assertContains<RHS>(lhs, 2);
49        assertContains<RHS>(rhs, 2);
50    }
51    assert(LHS::count == 0);
52    assert(RHS::count == 0);
53}
54
55template <class LHS>
56void test_copy_assign_empty() {
57    assert(LHS::count == 0);
58    LHS::reset();
59    {
60        any lhs;
61        any const rhs(LHS(42));
62
63        assert(LHS::count == 1);
64        assert(LHS::copied == 0);
65
66        lhs = rhs;
67
68        assert(LHS::copied == 1);
69        assert(LHS::count == 2);
70
71        assertContains<LHS>(lhs, 42);
72        assertContains<LHS>(rhs, 42);
73    }
74    assert(LHS::count == 0);
75    LHS::reset();
76    {
77        any lhs(LHS(1));
78        any const rhs;
79
80        assert(LHS::count == 1);
81        assert(LHS::copied == 0);
82
83        lhs = rhs;
84
85        assert(LHS::copied == 0);
86        assert(LHS::count == 0);
87
88        assertEmpty<LHS>(lhs);
89        assertEmpty(rhs);
90    }
91    assert(LHS::count == 0);
92}
93
94void test_copy_assign_self() {
95    // empty
96    {
97        any a;
98        a = a;
99        assertEmpty(a);
100        assert(globalMemCounter.checkOutstandingNewEq(0));
101    }
102    assert(globalMemCounter.checkOutstandingNewEq(0));
103    // small
104    {
105        any a((small(1)));
106        assert(small::count == 1);
107
108        a = a;
109
110        assert(small::count == 1);
111        assertContains<small>(a, 1);
112        assert(globalMemCounter.checkOutstandingNewEq(0));
113    }
114    assert(small::count == 0);
115    assert(globalMemCounter.checkOutstandingNewEq(0));
116    // large
117    {
118        any a(large(1));
119        assert(large::count == 1);
120
121        a = a;
122
123        assert(large::count == 1);
124        assertContains<large>(a, 1);
125        assert(globalMemCounter.checkOutstandingNewEq(1));
126    }
127    assert(large::count == 0);
128    assert(globalMemCounter.checkOutstandingNewEq(0));
129}
130
131template <class Tp>
132void test_copy_assign_throws()
133{
134#if !defined(TEST_HAS_NO_EXCEPTIONS)
135    auto try_throw =
136    [](any& lhs, any const& rhs) {
137        try {
138            lhs = rhs;
139            assert(false);
140        } catch (my_any_exception const &) {
141            // do nothing
142        } catch (...) {
143            assert(false);
144        }
145    };
146    // const lvalue to empty
147    {
148        any lhs;
149        any const rhs((Tp(1)));
150        assert(Tp::count == 1);
151
152        try_throw(lhs, rhs);
153
154        assert(Tp::count == 1);
155        assertEmpty<Tp>(lhs);
156        assertContains<Tp>(rhs);
157    }
158    {
159        any lhs((small(2)));
160        any const rhs((Tp(1)));
161        assert(small::count == 1);
162        assert(Tp::count == 1);
163
164        try_throw(lhs, rhs);
165
166        assert(small::count == 1);
167        assert(Tp::count == 1);
168        assertContains<small>(lhs, 2);
169        assertContains<Tp>(rhs);
170    }
171    {
172        any lhs((large(2)));
173        any const rhs((Tp(1)));
174        assert(large::count == 1);
175        assert(Tp::count == 1);
176
177        try_throw(lhs, rhs);
178
179        assert(large::count == 1);
180        assert(Tp::count == 1);
181        assertContains<large>(lhs, 2);
182        assertContains<Tp>(rhs);
183    }
184#endif
185}
186
187int main() {
188    test_copy_assign<small1, small2>();
189    test_copy_assign<large1, large2>();
190    test_copy_assign<small, large>();
191    test_copy_assign<large, small>();
192    test_copy_assign_empty<small>();
193    test_copy_assign_empty<large>();
194    test_copy_assign_self();
195    test_copy_assign_throws<small_throws_on_copy>();
196    test_copy_assign_throws<large_throws_on_copy>();
197}
198