1 | //===- llvm/unittest/Support/AnyTest.cpp - Any tests ---===// |
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 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "llvm/ADT/Any.h" |
10 | #include "gtest/gtest.h" |
11 | #include <cstdlib> |
12 | |
13 | using namespace llvm; |
14 | |
15 | namespace { |
16 | |
17 | // Make sure we can construct, copy-construct, move-construct, and assign Any's. |
18 | TEST(AnyTest, ConstructionAndAssignment) { |
19 | llvm::Any A; |
20 | llvm::Any B{7}; |
21 | llvm::Any C{8}; |
22 | llvm::Any D{"hello" }; |
23 | llvm::Any E{3.7}; |
24 | |
25 | // An empty Any is not anything. |
26 | EXPECT_FALSE(A.has_value()); |
27 | EXPECT_FALSE(llvm::any_cast<int>(&A)); |
28 | |
29 | // An int is an int but not something else. |
30 | EXPECT_TRUE(B.has_value()); |
31 | EXPECT_TRUE(llvm::any_cast<int>(&B)); |
32 | EXPECT_FALSE(llvm::any_cast<float>(&B)); |
33 | |
34 | EXPECT_TRUE(C.has_value()); |
35 | EXPECT_TRUE(llvm::any_cast<int>(&C)); |
36 | |
37 | // A const char * is a const char * but not an int. |
38 | EXPECT_TRUE(D.has_value()); |
39 | EXPECT_TRUE(llvm::any_cast<const char *>(&D)); |
40 | EXPECT_FALSE(llvm::any_cast<int>(&D)); |
41 | |
42 | // A double is a double but not a float. |
43 | EXPECT_TRUE(E.has_value()); |
44 | EXPECT_TRUE(llvm::any_cast<double>(&E)); |
45 | EXPECT_FALSE(llvm::any_cast<float>(&E)); |
46 | |
47 | // After copy constructing from an int, the new item and old item are both |
48 | // ints. |
49 | llvm::Any F(B); |
50 | EXPECT_TRUE(B.has_value()); |
51 | EXPECT_TRUE(F.has_value()); |
52 | EXPECT_TRUE(llvm::any_cast<int>(&F)); |
53 | EXPECT_TRUE(llvm::any_cast<int>(&B)); |
54 | |
55 | // After move constructing from an int, the new item is an int and the old one |
56 | // isn't. |
57 | llvm::Any G(std::move(C)); |
58 | EXPECT_FALSE(C.has_value()); |
59 | EXPECT_TRUE(G.has_value()); |
60 | EXPECT_TRUE(llvm::any_cast<int>(&G)); |
61 | EXPECT_FALSE(llvm::any_cast<int>(&C)); |
62 | |
63 | // After copy-assigning from an int, the new item and old item are both ints. |
64 | A = F; |
65 | EXPECT_TRUE(A.has_value()); |
66 | EXPECT_TRUE(F.has_value()); |
67 | EXPECT_TRUE(llvm::any_cast<int>(&A)); |
68 | EXPECT_TRUE(llvm::any_cast<int>(&F)); |
69 | |
70 | // After move-assigning from an int, the new item and old item are both ints. |
71 | B = std::move(G); |
72 | EXPECT_TRUE(B.has_value()); |
73 | EXPECT_FALSE(G.has_value()); |
74 | EXPECT_TRUE(llvm::any_cast<int>(&B)); |
75 | EXPECT_FALSE(llvm::any_cast<int>(&G)); |
76 | } |
77 | |
78 | TEST(AnyTest, GoodAnyCast) { |
79 | llvm::Any A; |
80 | llvm::Any B{7}; |
81 | llvm::Any C{8}; |
82 | llvm::Any D{"hello" }; |
83 | llvm::Any E{'x'}; |
84 | |
85 | // Check each value twice to make sure it isn't damaged by the cast. |
86 | EXPECT_EQ(7, llvm::any_cast<int>(B)); |
87 | EXPECT_EQ(7, llvm::any_cast<int>(B)); |
88 | |
89 | EXPECT_STREQ("hello" , llvm::any_cast<const char *>(D)); |
90 | EXPECT_STREQ("hello" , llvm::any_cast<const char *>(D)); |
91 | |
92 | EXPECT_EQ('x', llvm::any_cast<char>(E)); |
93 | EXPECT_EQ('x', llvm::any_cast<char>(E)); |
94 | |
95 | llvm::Any F(B); |
96 | EXPECT_EQ(7, llvm::any_cast<int>(F)); |
97 | EXPECT_EQ(7, llvm::any_cast<int>(F)); |
98 | |
99 | llvm::Any G(std::move(C)); |
100 | EXPECT_EQ(8, llvm::any_cast<int>(G)); |
101 | EXPECT_EQ(8, llvm::any_cast<int>(G)); |
102 | |
103 | A = F; |
104 | EXPECT_EQ(7, llvm::any_cast<int>(A)); |
105 | EXPECT_EQ(7, llvm::any_cast<int>(A)); |
106 | |
107 | E = std::move(G); |
108 | EXPECT_EQ(8, llvm::any_cast<int>(E)); |
109 | EXPECT_EQ(8, llvm::any_cast<int>(E)); |
110 | |
111 | // Make sure we can any_cast from an rvalue and that it's properly destroyed |
112 | // in the process. |
113 | EXPECT_EQ(8, llvm::any_cast<int>(std::move(E))); |
114 | EXPECT_TRUE(E.has_value()); |
115 | |
116 | // Make sure moving from pointers gives back pointers, and that we can modify |
117 | // the underlying value through those pointers. |
118 | EXPECT_EQ(7, *llvm::any_cast<int>(&A)); |
119 | int *N = llvm::any_cast<int>(Value: &A); |
120 | *N = 42; |
121 | EXPECT_EQ(42, llvm::any_cast<int>(A)); |
122 | |
123 | // Make sure that we can any_cast to a reference and this is considered a good |
124 | // cast, resulting in an lvalue which can be modified. |
125 | llvm::any_cast<int &>(Value&: A) = 43; |
126 | EXPECT_EQ(43, llvm::any_cast<int>(A)); |
127 | } |
128 | |
129 | TEST(AnyTest, CopiesAndMoves) { |
130 | struct TestType { |
131 | TestType() = default; |
132 | TestType(const TestType &Other) |
133 | : Copies(Other.Copies + 1), Moves(Other.Moves) {} |
134 | TestType(TestType &&Other) : Copies(Other.Copies), Moves(Other.Moves + 1) {} |
135 | int Copies = 0; |
136 | int Moves = 0; |
137 | }; |
138 | |
139 | // One move to get TestType into the Any, and one move on the cast. |
140 | TestType T1 = llvm::any_cast<TestType>(Value: Any{TestType()}); |
141 | EXPECT_EQ(0, T1.Copies); |
142 | EXPECT_EQ(2, T1.Moves); |
143 | |
144 | // One move to get TestType into the Any, and one copy on the cast. |
145 | Any A{TestType()}; |
146 | TestType T2 = llvm::any_cast<TestType>(Value&: A); |
147 | EXPECT_EQ(1, T2.Copies); |
148 | EXPECT_EQ(1, T2.Moves); |
149 | |
150 | // One move to get TestType into the Any, and one move on the cast. |
151 | TestType T3 = llvm::any_cast<TestType>(Value: std::move(A)); |
152 | EXPECT_EQ(0, T3.Copies); |
153 | EXPECT_EQ(2, T3.Moves); |
154 | } |
155 | |
156 | TEST(AnyTest, BadAnyCast) { |
157 | llvm::Any A; |
158 | llvm::Any B{7}; |
159 | llvm::Any C{"hello" }; |
160 | llvm::Any D{'x'}; |
161 | |
162 | #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST |
163 | EXPECT_DEATH(llvm::any_cast<int>(A), "" ); |
164 | |
165 | EXPECT_DEATH(llvm::any_cast<float>(B), "" ); |
166 | EXPECT_DEATH(llvm::any_cast<int *>(B), "" ); |
167 | |
168 | EXPECT_DEATH(llvm::any_cast<std::string>(C), "" ); |
169 | |
170 | EXPECT_DEATH(llvm::any_cast<unsigned char>(D), "" ); |
171 | #endif |
172 | } |
173 | |
174 | } // anonymous namespace |
175 | |