xref: /llvm-project/llvm/unittests/ADT/AnyTest.cpp (revision f8a1c8b7c1d06a74fa38111454c42e22e118d584)
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