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