Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / test / support / experimental_any_helpers.h
blobc7fb9cfb1c1784bec9cddf50c201b9c86663a374
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef EXPERIMENTAL_ANY_HELPERS_H
10 #define EXPERIMENTAL_ANY_HELPERS_H
12 #include <experimental/any>
13 #include <typeinfo>
14 #include <type_traits>
15 #include <cassert>
17 #include "test_macros.h"
19 template <class T>
20 struct IsSmallObject
21 : public std::integral_constant<bool
22 , sizeof(T) <= (sizeof(void*)*3)
23 && std::alignment_of<void*>::value
24 % std::alignment_of<T>::value == 0
25 && std::is_nothrow_move_constructible<T>::value
27 {};
30 // Return 'true' if 'Type' will be considered a small type by 'any'
31 template <class Type>
32 bool isSmallType() {
33 #if defined(_LIBCPP_VERSION)
34 return std::experimental::__any_imp::_IsSmallObject<Type>::value;
35 #else
36 return IsSmallObject<Type>::value;
37 #endif
41 // Assert that an object is empty. If the object used to contain an object
42 // of type 'LastType' check that it can no longer be accessed.
43 template <class LastType = int>
44 void assertEmpty(std::experimental::any const& a) {
45 assert(a.empty());
46 RTTI_ASSERT(a.type() == typeid(void));
47 assert(std::experimental::any_cast<LastType const>(&a) == nullptr);
50 // Assert that an 'any' object stores the specified 'Type' and 'value'.
51 template <class Type>
52 _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
53 void assertContains(std::experimental::any const& a, int value = 1) {
54 assert(!a.empty());
55 RTTI_ASSERT(a.type() == typeid(Type));
56 assert(std::experimental::any_cast<Type const &>(a).value == value);
59 // Modify the value of a "test type" stored within an any to the specified
60 // 'value'.
61 template <class Type>
62 _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
63 void modifyValue(std::experimental::any& a, int value) {
64 assert(!a.empty());
65 RTTI_ASSERT(a.type() == typeid(Type));
66 std::experimental::any_cast<Type&>(a).value = value;
69 // A test type that will trigger the small object optimization within 'any'.
70 template <int Dummy = 0>
71 struct small_type
73 static int count;
74 static int copied;
75 static int moved;
76 static int const_copied;
77 static int non_const_copied;
79 static void reset() {
80 small_type::copied = 0;
81 small_type::moved = 0;
82 small_type::const_copied = 0;
83 small_type::non_const_copied = 0;
86 int value;
88 explicit small_type(int val) : value(val) {
89 ++count;
92 small_type(small_type const & other) throw() {
93 value = other.value;
94 ++count;
95 ++copied;
96 ++const_copied;
99 small_type(small_type& other) throw() {
100 value = other.value;
101 ++count;
102 ++copied;
103 ++non_const_copied;
106 small_type(small_type && other) throw() {
107 value = other.value;
108 other.value = 0;
109 ++count;
110 ++moved;
113 ~small_type() {
114 value = -1;
115 --count;
118 private:
119 small_type& operator=(small_type const&) = delete;
120 small_type& operator=(small_type&&) = delete;
123 template <int Dummy>
124 int small_type<Dummy>::count = 0;
126 template <int Dummy>
127 int small_type<Dummy>::copied = 0;
129 template <int Dummy>
130 int small_type<Dummy>::moved = 0;
132 template <int Dummy>
133 int small_type<Dummy>::const_copied = 0;
135 template <int Dummy>
136 int small_type<Dummy>::non_const_copied = 0;
138 typedef small_type<> small;
139 typedef small_type<1> small1;
140 typedef small_type<2> small2;
143 // A test type that will NOT trigger the small object optimization in any.
144 template <int Dummy = 0>
145 struct large_type
147 static int count;
148 static int copied;
149 static int moved;
150 static int const_copied;
151 static int non_const_copied;
153 static void reset() {
154 large_type::copied = 0;
155 large_type::moved = 0;
156 large_type::const_copied = 0;
157 large_type::non_const_copied = 0;
160 int value;
162 large_type(int val) : value(val) {
163 ++count;
164 data[0] = 0;
167 large_type(large_type const & other) {
168 value = other.value;
169 ++count;
170 ++copied;
171 ++const_copied;
174 large_type(large_type & other) {
175 value = other.value;
176 ++count;
177 ++copied;
178 ++non_const_copied;
181 large_type(large_type && other) {
182 value = other.value;
183 other.value = 0;
184 ++count;
185 ++moved;
188 ~large_type() {
189 value = 0;
190 --count;
193 private:
194 large_type& operator=(large_type const&) = delete;
195 large_type& operator=(large_type &&) = delete;
196 int data[10];
199 template <int Dummy>
200 int large_type<Dummy>::count = 0;
202 template <int Dummy>
203 int large_type<Dummy>::copied = 0;
205 template <int Dummy>
206 int large_type<Dummy>::moved = 0;
208 template <int Dummy>
209 int large_type<Dummy>::const_copied = 0;
211 template <int Dummy>
212 int large_type<Dummy>::non_const_copied = 0;
214 typedef large_type<> large;
215 typedef large_type<1> large1;
216 typedef large_type<2> large2;
218 // The exception type thrown by 'small_throws_on_copy', 'large_throws_on_copy'
219 // and 'throws_on_move'.
220 struct my_any_exception {};
222 void throwMyAnyExpression() {
223 #if !defined(TEST_HAS_NO_EXCEPTIONS)
224 throw my_any_exception();
225 #else
226 assert(false && "Exceptions are disabled");
227 #endif
230 // A test type that will trigger the small object optimization within 'any'.
231 // this type throws if it is copied.
232 struct small_throws_on_copy
234 static int count;
235 int value;
237 explicit small_throws_on_copy(int val = 0) : value(val) {
238 ++count;
241 small_throws_on_copy(small_throws_on_copy const &) {
242 throwMyAnyExpression();
245 small_throws_on_copy(small_throws_on_copy && other) throw() {
246 value = other.value;
247 ++count;
250 ~small_throws_on_copy() {
251 --count;
253 private:
254 small_throws_on_copy& operator=(small_throws_on_copy const&) = delete;
255 small_throws_on_copy& operator=(small_throws_on_copy &&) = delete;
258 int small_throws_on_copy::count = 0;
260 // A test type that will NOT trigger the small object optimization within 'any'.
261 // this type throws if it is copied.
262 struct large_throws_on_copy
264 static int count;
265 int value = 0;
267 explicit large_throws_on_copy(int val = 0) : value(val) {
268 data[0] = 0;
269 ++count;
272 large_throws_on_copy(large_throws_on_copy const &) {
273 throwMyAnyExpression();
276 large_throws_on_copy(large_throws_on_copy && other) throw() {
277 value = other.value;
278 ++count;
281 ~large_throws_on_copy() {
282 --count;
285 private:
286 large_throws_on_copy& operator=(large_throws_on_copy const&) = delete;
287 large_throws_on_copy& operator=(large_throws_on_copy &&) = delete;
288 int data[10];
291 int large_throws_on_copy::count = 0;
293 // A test type that throws when it is moved. This object will NOT trigger
294 // the small object optimization in 'any'.
295 struct throws_on_move
297 static int count;
298 int value;
300 explicit throws_on_move(int val = 0) : value(val) { ++count; }
302 throws_on_move(throws_on_move const & other) {
303 value = other.value;
304 ++count;
307 throws_on_move(throws_on_move &&) {
308 throwMyAnyExpression();
311 ~throws_on_move() {
312 --count;
314 private:
315 throws_on_move& operator=(throws_on_move const&) = delete;
316 throws_on_move& operator=(throws_on_move &&) = delete;
319 int throws_on_move::count = 0;
322 #endif