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