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. 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 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 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 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 EXPECT_DEBUG_DEATH(llvm::any_cast<int>(A), ""); 164 165 EXPECT_DEBUG_DEATH(llvm::any_cast<float>(B), ""); 166 EXPECT_DEBUG_DEATH(llvm::any_cast<int *>(B), ""); 167 168 EXPECT_DEBUG_DEATH(llvm::any_cast<std::string>(C), ""); 169 170 EXPECT_DEBUG_DEATH(llvm::any_cast<unsigned char>(D), ""); 171 } 172 173 } // anonymous namespace 174