1 //===---------- llvm/unittest/Support/Casting.cpp - Casting 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/Support/Casting.h" 10 #include "llvm/IR/User.h" 11 #include "llvm/Support/Debug.h" 12 #include "llvm/Support/raw_ostream.h" 13 #include "gtest/gtest.h" 14 #include <cstdlib> 15 16 namespace llvm { 17 // Used to test illegal cast. If a cast doesn't match any of the "real" ones, 18 // it will match this one. 19 struct IllegalCast; 20 template <typename T> IllegalCast *cast(...) { return nullptr; } 21 22 // set up two example classes 23 // with conversion facility 24 // 25 struct bar { 26 bar() {} 27 struct foo *baz(); 28 struct foo *caz(); 29 struct foo *daz(); 30 struct foo *naz(); 31 private: 32 bar(const bar &); 33 }; 34 struct foo { 35 void ext() const; 36 /* static bool classof(const bar *X) { 37 cerr << "Classof: " << X << "\n"; 38 return true; 39 }*/ 40 }; 41 42 struct base { 43 virtual ~base() {} 44 }; 45 46 struct derived : public base { 47 static bool classof(const base *B) { return true; } 48 }; 49 50 template <> struct isa_impl<foo, bar> { 51 static inline bool doit(const bar &Val) { 52 dbgs() << "Classof: " << &Val << "\n"; 53 return true; 54 } 55 }; 56 57 template <typename T> struct isa_impl<foo, T> { 58 static inline bool doit(const T &Val) { return false; } 59 }; 60 61 foo *bar::baz() { 62 return cast<foo>(this); 63 } 64 65 foo *bar::caz() { 66 return cast_or_null<foo>(this); 67 } 68 69 foo *bar::daz() { 70 return dyn_cast<foo>(this); 71 } 72 73 foo *bar::naz() { 74 return dyn_cast_or_null<foo>(this); 75 } 76 77 78 bar *fub(); 79 80 template <> struct simplify_type<foo> { 81 typedef int SimpleType; 82 static SimpleType getSimplifiedValue(foo &Val) { return 0; } 83 }; 84 85 } // End llvm namespace 86 87 using namespace llvm; 88 89 90 // Test the peculiar behavior of Use in simplify_type. 91 static_assert(std::is_same<simplify_type<Use>::SimpleType, Value *>::value, 92 "Use doesn't simplify correctly!"); 93 static_assert(std::is_same<simplify_type<Use *>::SimpleType, Value *>::value, 94 "Use doesn't simplify correctly!"); 95 96 // Test that a regular class behaves as expected. 97 static_assert(std::is_same<simplify_type<foo>::SimpleType, int>::value, 98 "Unexpected simplify_type result!"); 99 static_assert(std::is_same<simplify_type<foo *>::SimpleType, foo *>::value, 100 "Unexpected simplify_type result!"); 101 102 namespace { 103 104 const foo *null_foo = nullptr; 105 106 bar B; 107 extern bar &B1; 108 bar &B1 = B; 109 extern const bar *B2; 110 // test various configurations of const 111 const bar &B3 = B1; 112 const bar *const B4 = B2; 113 114 TEST(CastingTest, isa) { 115 EXPECT_TRUE(isa<foo>(B1)); 116 EXPECT_TRUE(isa<foo>(B2)); 117 EXPECT_TRUE(isa<foo>(B3)); 118 EXPECT_TRUE(isa<foo>(B4)); 119 } 120 121 TEST(CastingTest, isa_and_nonnull) { 122 EXPECT_TRUE(isa_and_nonnull<foo>(B2)); 123 EXPECT_TRUE(isa_and_nonnull<foo>(B4)); 124 EXPECT_FALSE(isa_and_nonnull<foo>(fub())); 125 } 126 127 TEST(CastingTest, cast) { 128 foo &F1 = cast<foo>(B1); 129 EXPECT_NE(&F1, null_foo); 130 const foo *F3 = cast<foo>(B2); 131 EXPECT_NE(F3, null_foo); 132 const foo *F4 = cast<foo>(B2); 133 EXPECT_NE(F4, null_foo); 134 const foo &F5 = cast<foo>(B3); 135 EXPECT_NE(&F5, null_foo); 136 const foo *F6 = cast<foo>(B4); 137 EXPECT_NE(F6, null_foo); 138 // Can't pass null pointer to cast<>. 139 // foo *F7 = cast<foo>(fub()); 140 // EXPECT_EQ(F7, null_foo); 141 foo *F8 = B1.baz(); 142 EXPECT_NE(F8, null_foo); 143 144 std::unique_ptr<const bar> BP(B2); 145 auto FP = cast<foo>(std::move(BP)); 146 static_assert(std::is_same<std::unique_ptr<const foo>, decltype(FP)>::value, 147 "Incorrect deduced return type!"); 148 EXPECT_NE(FP.get(), null_foo); 149 FP.release(); 150 } 151 152 TEST(CastingTest, cast_or_null) { 153 const foo *F11 = cast_or_null<foo>(B2); 154 EXPECT_NE(F11, null_foo); 155 const foo *F12 = cast_or_null<foo>(B2); 156 EXPECT_NE(F12, null_foo); 157 const foo *F13 = cast_or_null<foo>(B4); 158 EXPECT_NE(F13, null_foo); 159 const foo *F14 = cast_or_null<foo>(fub()); // Shouldn't print. 160 EXPECT_EQ(F14, null_foo); 161 foo *F15 = B1.caz(); 162 EXPECT_NE(F15, null_foo); 163 164 std::unique_ptr<const bar> BP(fub()); 165 auto FP = cast_or_null<foo>(std::move(BP)); 166 EXPECT_EQ(FP.get(), null_foo); 167 } 168 169 TEST(CastingTest, dyn_cast) { 170 const foo *F1 = dyn_cast<foo>(B2); 171 EXPECT_NE(F1, null_foo); 172 const foo *F2 = dyn_cast<foo>(B2); 173 EXPECT_NE(F2, null_foo); 174 const foo *F3 = dyn_cast<foo>(B4); 175 EXPECT_NE(F3, null_foo); 176 // Can't pass null pointer to dyn_cast<>. 177 // foo *F4 = dyn_cast<foo>(fub()); 178 // EXPECT_EQ(F4, null_foo); 179 foo *F5 = B1.daz(); 180 EXPECT_NE(F5, null_foo); 181 } 182 183 TEST(CastingTest, dyn_cast_or_null) { 184 const foo *F1 = dyn_cast_or_null<foo>(B2); 185 EXPECT_NE(F1, null_foo); 186 const foo *F2 = dyn_cast_or_null<foo>(B2); 187 EXPECT_NE(F2, null_foo); 188 const foo *F3 = dyn_cast_or_null<foo>(B4); 189 EXPECT_NE(F3, null_foo); 190 foo *F4 = dyn_cast_or_null<foo>(fub()); 191 EXPECT_EQ(F4, null_foo); 192 foo *F5 = B1.naz(); 193 EXPECT_NE(F5, null_foo); 194 } 195 196 std::unique_ptr<derived> newd() { return std::make_unique<derived>(); } 197 std::unique_ptr<base> newb() { return std::make_unique<derived>(); } 198 199 TEST(CastingTest, unique_dyn_cast) { 200 derived *OrigD = nullptr; 201 auto D = std::make_unique<derived>(); 202 OrigD = D.get(); 203 204 // Converting from D to itself is valid, it should return a new unique_ptr 205 // and the old one should become nullptr. 206 auto NewD = unique_dyn_cast<derived>(D); 207 ASSERT_EQ(OrigD, NewD.get()); 208 ASSERT_EQ(nullptr, D); 209 210 // Converting from D to B is valid, B should have a value and D should be 211 // nullptr. 212 auto B = unique_dyn_cast<base>(NewD); 213 ASSERT_EQ(OrigD, B.get()); 214 ASSERT_EQ(nullptr, NewD); 215 216 // Converting from B to itself is valid, it should return a new unique_ptr 217 // and the old one should become nullptr. 218 auto NewB = unique_dyn_cast<base>(B); 219 ASSERT_EQ(OrigD, NewB.get()); 220 ASSERT_EQ(nullptr, B); 221 222 // Converting from B to D is valid, D should have a value and B should be 223 // nullptr; 224 D = unique_dyn_cast<derived>(NewB); 225 ASSERT_EQ(OrigD, D.get()); 226 ASSERT_EQ(nullptr, NewB); 227 228 // Converting between unrelated types should fail. The original value should 229 // remain unchanged and it should return nullptr. 230 auto F = unique_dyn_cast<foo>(D); 231 ASSERT_EQ(nullptr, F); 232 ASSERT_EQ(OrigD, D.get()); 233 234 // All of the above should also hold for temporaries. 235 auto D2 = unique_dyn_cast<derived>(newd()); 236 EXPECT_NE(nullptr, D2); 237 238 auto B2 = unique_dyn_cast<derived>(newb()); 239 EXPECT_NE(nullptr, B2); 240 241 auto B3 = unique_dyn_cast<base>(newb()); 242 EXPECT_NE(nullptr, B3); 243 244 auto F2 = unique_dyn_cast<foo>(newb()); 245 EXPECT_EQ(nullptr, F2); 246 } 247 248 // These lines are errors... 249 //foo *F20 = cast<foo>(B2); // Yields const foo* 250 //foo &F21 = cast<foo>(B3); // Yields const foo& 251 //foo *F22 = cast<foo>(B4); // Yields const foo* 252 //foo &F23 = cast_or_null<foo>(B1); 253 //const foo &F24 = cast_or_null<foo>(B3); 254 255 const bar *B2 = &B; 256 } // anonymous namespace 257 258 bar *llvm::fub() { return nullptr; } 259 260 namespace { 261 namespace inferred_upcasting { 262 // This test case verifies correct behavior of inferred upcasts when the 263 // types are statically known to be OK to upcast. This is the case when, 264 // for example, Derived inherits from Base, and we do `isa<Base>(Derived)`. 265 266 // Note: This test will actually fail to compile without inferred 267 // upcasting. 268 269 class Base { 270 public: 271 // No classof. We are testing that the upcast is inferred. 272 Base() {} 273 }; 274 275 class Derived : public Base { 276 public: 277 Derived() {} 278 }; 279 280 // Even with no explicit classof() in Base, we should still be able to cast 281 // Derived to its base class. 282 TEST(CastingTest, UpcastIsInferred) { 283 Derived D; 284 EXPECT_TRUE(isa<Base>(D)); 285 Base *BP = dyn_cast<Base>(&D); 286 EXPECT_TRUE(BP != nullptr); 287 } 288 289 290 // This test verifies that the inferred upcast takes precedence over an 291 // explicitly written one. This is important because it verifies that the 292 // dynamic check gets optimized away. 293 class UseInferredUpcast { 294 public: 295 int Dummy; 296 static bool classof(const UseInferredUpcast *) { 297 return false; 298 } 299 }; 300 301 TEST(CastingTest, InferredUpcastTakesPrecedence) { 302 UseInferredUpcast UIU; 303 // Since the explicit classof() returns false, this will fail if the 304 // explicit one is used. 305 EXPECT_TRUE(isa<UseInferredUpcast>(&UIU)); 306 } 307 308 } // end namespace inferred_upcasting 309 } // end anonymous namespace 310 // Test that we reject casts of temporaries (and so the illegal cast gets used). 311 namespace TemporaryCast { 312 struct pod {}; 313 IllegalCast *testIllegalCast() { return cast<foo>(pod()); } 314 } 315 316 namespace { 317 namespace pointer_wrappers { 318 319 struct Base { 320 bool IsDerived; 321 Base(bool IsDerived = false) : IsDerived(IsDerived) {} 322 }; 323 324 struct Derived : Base { 325 Derived() : Base(true) {} 326 static bool classof(const Base *B) { return B->IsDerived; } 327 }; 328 329 class PTy { 330 Base *B; 331 public: 332 PTy(Base *B) : B(B) {} 333 explicit operator bool() const { return get(); } 334 Base *get() const { return B; } 335 }; 336 337 } // end namespace pointer_wrappers 338 } // end namespace 339 340 namespace llvm { 341 342 template <> struct simplify_type<pointer_wrappers::PTy> { 343 typedef pointer_wrappers::Base *SimpleType; 344 static SimpleType getSimplifiedValue(pointer_wrappers::PTy &P) { 345 return P.get(); 346 } 347 }; 348 template <> struct simplify_type<const pointer_wrappers::PTy> { 349 typedef pointer_wrappers::Base *SimpleType; 350 static SimpleType getSimplifiedValue(const pointer_wrappers::PTy &P) { 351 return P.get(); 352 } 353 }; 354 355 } // end namespace llvm 356 357 namespace { 358 namespace pointer_wrappers { 359 360 // Some objects. 361 pointer_wrappers::Base B; 362 pointer_wrappers::Derived D; 363 364 // Mutable "smart" pointers. 365 pointer_wrappers::PTy MN(nullptr); 366 pointer_wrappers::PTy MB(&B); 367 pointer_wrappers::PTy MD(&D); 368 369 // Const "smart" pointers. 370 const pointer_wrappers::PTy CN(nullptr); 371 const pointer_wrappers::PTy CB(&B); 372 const pointer_wrappers::PTy CD(&D); 373 374 TEST(CastingTest, smart_isa) { 375 EXPECT_TRUE(!isa<pointer_wrappers::Derived>(MB)); 376 EXPECT_TRUE(!isa<pointer_wrappers::Derived>(CB)); 377 EXPECT_TRUE(isa<pointer_wrappers::Derived>(MD)); 378 EXPECT_TRUE(isa<pointer_wrappers::Derived>(CD)); 379 } 380 381 TEST(CastingTest, smart_cast) { 382 EXPECT_TRUE(cast<pointer_wrappers::Derived>(MD) == &D); 383 EXPECT_TRUE(cast<pointer_wrappers::Derived>(CD) == &D); 384 } 385 386 TEST(CastingTest, smart_cast_or_null) { 387 EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MN) == nullptr); 388 EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CN) == nullptr); 389 EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MD) == &D); 390 EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CD) == &D); 391 } 392 393 TEST(CastingTest, smart_dyn_cast) { 394 EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MB) == nullptr); 395 EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CB) == nullptr); 396 EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MD) == &D); 397 EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CD) == &D); 398 } 399 400 TEST(CastingTest, smart_dyn_cast_or_null) { 401 EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MN) == nullptr); 402 EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CN) == nullptr); 403 EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MB) == nullptr); 404 EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CB) == nullptr); 405 EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MD) == &D); 406 EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CD) == &D); 407 } 408 409 } // end namespace pointer_wrappers 410 } // end namespace 411