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
16namespace llvm {
17// Used to test illegal cast. If a cast doesn't match any of the "real" ones,
18// it will match this one.
19struct IllegalCast;
20template <typename T> IllegalCast *cast(...) { return nullptr; }
21
22// set up two example classes
23// with conversion facility
24//
25struct bar {
26 bar() {}
27 struct foo *baz();
28 struct foo *caz();
29 struct foo *daz();
30 struct foo *naz();
31
32private:
33 bar(const bar &);
34};
35struct foo {
36 foo(const bar &) {}
37 void ext() const;
38};
39
40struct base {
41 virtual ~base() {}
42};
43
44struct derived : public base {
45 static bool classof(const base *B) { return true; }
46};
47
48struct derived_nocast : public base {
49 static bool classof(const base *B) { return false; }
50};
51
52template <> struct isa_impl<foo, bar> {
53 static inline bool doit(const bar &Val) {
54 dbgs() << "Classof: " << &Val << "\n";
55 return true;
56 }
57};
58
59// Note for the future - please don't do this. isa_impl is an internal template
60// for the implementation of `isa` and should not be exposed this way.
61// Completely unrelated types *should* result in compiler errors if you try to
62// cast between them.
63template <typename T> struct isa_impl<foo, T> {
64 static inline bool doit(const T &Val) { return false; }
65};
66
67foo *bar::baz() { return cast<foo>(Val: this); }
68
69foo *bar::caz() { return cast_or_null<foo>(Val: this); }
70
71foo *bar::daz() { return dyn_cast<foo>(Val: this); }
72
73foo *bar::naz() { return dyn_cast_or_null<foo>(Val: this); }
74
75bar *fub();
76
77template <> struct simplify_type<foo> {
78 typedef int SimpleType;
79 static SimpleType getSimplifiedValue(foo &Val) { return 0; }
80};
81
82struct T1 {};
83
84struct T2 {
85 T2(const T1 &x) {}
86 static bool classof(const T1 *x) { return true; }
87};
88
89template <> struct CastInfo<T2, T1> : public OptionalValueCast<T2, T1> {};
90
91struct T3 {
92 T3(const T1 *x) : hasValue(x != nullptr) {}
93
94 static bool classof(const T1 *x) { return true; }
95 bool hasValue = false;
96};
97
98// T3 is convertible from a pointer to T1.
99template <> struct CastInfo<T3, T1 *> : public ValueFromPointerCast<T3, T1> {};
100
101struct T4 {
102 T4() : hasValue(false) {}
103 T4(const T3 &x) : hasValue(true) {}
104
105 static bool classof(const T3 *x) { return true; }
106 bool hasValue = false;
107};
108
109template <> struct ValueIsPresent<T3> {
110 using UnwrappedType = T3;
111 static inline bool isPresent(const T3 &t) { return t.hasValue; }
112 static inline const T3 &unwrapValue(const T3 &t) { return t; }
113};
114
115template <> struct CastInfo<T4, T3> {
116 using CastResultType = T4;
117 static inline CastResultType doCast(const T3 &t) { return T4(t); }
118 static inline CastResultType castFailed() { return CastResultType(); }
119 static inline CastResultType doCastIfPossible(const T3 &f) {
120 return doCast(t: f);
121 }
122};
123
124} // namespace llvm
125
126using namespace llvm;
127
128// Test the peculiar behavior of Use in simplify_type.
129static_assert(std::is_same_v<simplify_type<Use>::SimpleType, Value *>,
130 "Use doesn't simplify correctly!");
131static_assert(std::is_same_v<simplify_type<Use *>::SimpleType, Value *>,
132 "Use doesn't simplify correctly!");
133
134// Test that a regular class behaves as expected.
135static_assert(std::is_same_v<simplify_type<foo>::SimpleType, int>,
136 "Unexpected simplify_type result!");
137static_assert(std::is_same_v<simplify_type<foo *>::SimpleType, foo *>,
138 "Unexpected simplify_type result!");
139
140namespace {
141
142const foo *null_foo = nullptr;
143
144bar B;
145extern bar &B1;
146bar &B1 = B;
147extern const bar *B2;
148// test various configurations of const
149const bar &B3 = B1;
150const bar *const B4 = B2;
151
152TEST(CastingTest, isa) {
153 EXPECT_TRUE(isa<foo>(B1));
154 EXPECT_TRUE(isa<foo>(B2));
155 EXPECT_TRUE(isa<foo>(B3));
156 EXPECT_TRUE(isa<foo>(B4));
157}
158
159TEST(CastingTest, isa_and_nonnull) {
160 EXPECT_TRUE(isa_and_nonnull<foo>(B2));
161 EXPECT_TRUE(isa_and_nonnull<foo>(B4));
162 EXPECT_FALSE(isa_and_nonnull<foo>(fub()));
163}
164
165TEST(CastingTest, cast) {
166 foo &F1 = cast<foo>(Val&: B1);
167 EXPECT_NE(&F1, null_foo);
168 const foo *F3 = cast<foo>(Val: B2);
169 EXPECT_NE(F3, null_foo);
170 const foo *F4 = cast<foo>(Val: B2);
171 EXPECT_NE(F4, null_foo);
172 const foo &F5 = cast<foo>(Val: B3);
173 EXPECT_NE(&F5, null_foo);
174 const foo *F6 = cast<foo>(Val: B4);
175 EXPECT_NE(F6, null_foo);
176 // Can't pass null pointer to cast<>.
177 // foo *F7 = cast<foo>(fub());
178 // EXPECT_EQ(F7, null_foo);
179 foo *F8 = B1.baz();
180 EXPECT_NE(F8, null_foo);
181
182 std::unique_ptr<const bar> BP(B2);
183 auto FP = cast<foo>(Val: std::move(BP));
184 static_assert(std::is_same_v<std::unique_ptr<const foo>, decltype(FP)>,
185 "Incorrect deduced return type!");
186 EXPECT_NE(FP.get(), null_foo);
187 FP.release();
188}
189
190TEST(CastingTest, cast_or_null) {
191 const foo *F11 = cast_or_null<foo>(Val: B2);
192 EXPECT_NE(F11, null_foo);
193 const foo *F12 = cast_or_null<foo>(Val: B2);
194 EXPECT_NE(F12, null_foo);
195 const foo *F13 = cast_or_null<foo>(Val: B4);
196 EXPECT_NE(F13, null_foo);
197 const foo *F14 = cast_or_null<foo>(Val: fub()); // Shouldn't print.
198 EXPECT_EQ(F14, null_foo);
199 foo *F15 = B1.caz();
200 EXPECT_NE(F15, null_foo);
201
202 std::unique_ptr<const bar> BP(fub());
203 auto FP = cast_or_null<foo>(Val: std::move(BP));
204 EXPECT_EQ(FP.get(), null_foo);
205}
206
207TEST(CastingTest, dyn_cast) {
208 const foo *F1 = dyn_cast<foo>(Val: B2);
209 EXPECT_NE(F1, null_foo);
210 const foo *F2 = dyn_cast<foo>(Val: B2);
211 EXPECT_NE(F2, null_foo);
212 const foo *F3 = dyn_cast<foo>(Val: B4);
213 EXPECT_NE(F3, null_foo);
214 // Can't pass null pointer to dyn_cast<>.
215 // foo *F4 = dyn_cast<foo>(fub());
216 // EXPECT_EQ(F4, null_foo);
217 foo *F5 = B1.daz();
218 EXPECT_NE(F5, null_foo);
219
220 auto BP = std::make_unique<const bar>();
221 auto FP = dyn_cast<foo>(Val&: BP);
222 static_assert(std::is_same_v<std::unique_ptr<const foo>, decltype(FP)>,
223 "Incorrect deduced return type!");
224 EXPECT_NE(FP.get(), nullptr);
225 EXPECT_EQ(BP.get(), nullptr);
226
227 auto BP2 = std::make_unique<base>();
228 auto DP = dyn_cast<derived_nocast>(Val&: BP2);
229 EXPECT_EQ(DP.get(), nullptr);
230 EXPECT_NE(BP2.get(), nullptr);
231}
232
233// All these tests forward to dyn_cast_if_present, so they also provde an
234// effective test for its use cases.
235TEST(CastingTest, dyn_cast_or_null) {
236 const foo *F1 = dyn_cast_or_null<foo>(Val: B2);
237 EXPECT_NE(F1, null_foo);
238 const foo *F2 = dyn_cast_or_null<foo>(Val: B2);
239 EXPECT_NE(F2, null_foo);
240 const foo *F3 = dyn_cast_or_null<foo>(Val: B4);
241 EXPECT_NE(F3, null_foo);
242 foo *F4 = dyn_cast_or_null<foo>(Val: fub());
243 EXPECT_EQ(F4, null_foo);
244 foo *F5 = B1.naz();
245 EXPECT_NE(F5, null_foo);
246 // dyn_cast_if_present should have exactly the same behavior as
247 // dyn_cast_or_null.
248 const foo *F6 = dyn_cast_if_present<foo>(Val: B2);
249 EXPECT_EQ(F6, F2);
250}
251
252TEST(CastingTest, dyn_cast_value_types) {
253 T1 t1;
254 std::optional<T2> t2 = dyn_cast<T2>(Val&: t1);
255 EXPECT_TRUE(t2);
256
257 T2 *t2ptr = dyn_cast<T2>(Val: &t1);
258 EXPECT_TRUE(t2ptr != nullptr);
259
260 T3 t3 = dyn_cast<T3>(Val: &t1);
261 EXPECT_TRUE(t3.hasValue);
262}
263
264TEST(CastingTest, dyn_cast_if_present) {
265 std::optional<T1> empty{};
266 std::optional<T2> F1 = dyn_cast_if_present<T2>(Val&: empty);
267 EXPECT_FALSE(F1.has_value());
268
269 T1 t1;
270 std::optional<T2> F2 = dyn_cast_if_present<T2>(Val&: t1);
271 EXPECT_TRUE(F2.has_value());
272
273 T1 *t1Null = nullptr;
274
275 // T3 should have hasValue == false because t1Null is nullptr.
276 T3 t3 = dyn_cast_if_present<T3>(Val: t1Null);
277 EXPECT_FALSE(t3.hasValue);
278
279 // Now because of that, T4 should receive the castFailed implementation of its
280 // FallibleCastTraits, which default-constructs a T4, which has no value.
281 T4 t4 = dyn_cast_if_present<T4>(Val&: t3);
282 EXPECT_FALSE(t4.hasValue);
283}
284
285TEST(CastingTest, isa_check_predicates) {
286 auto IsaFoo = IsaPred<foo>;
287 EXPECT_TRUE(IsaFoo(B1));
288 EXPECT_TRUE(IsaFoo(B2));
289 EXPECT_TRUE(IsaFoo(B3));
290 EXPECT_TRUE(IsaPred<foo>(B4));
291 EXPECT_TRUE((IsaPred<foo, bar>(B4)));
292
293 auto IsaAndPresentFoo = IsaAndPresentPred<foo>;
294 EXPECT_TRUE(IsaAndPresentFoo(B2));
295 EXPECT_TRUE(IsaAndPresentFoo(B4));
296 EXPECT_FALSE(IsaAndPresentPred<foo>(fub()));
297 EXPECT_FALSE((IsaAndPresentPred<foo, bar>(fub())));
298}
299
300std::unique_ptr<derived> newd() { return std::make_unique<derived>(); }
301std::unique_ptr<base> newb() { return std::make_unique<derived>(); }
302
303TEST(CastingTest, unique_dyn_cast) {
304 derived *OrigD = nullptr;
305 auto D = std::make_unique<derived>();
306 OrigD = D.get();
307
308 // Converting from D to itself is valid, it should return a new unique_ptr
309 // and the old one should become nullptr.
310 auto NewD = unique_dyn_cast<derived>(Val&: D);
311 ASSERT_EQ(OrigD, NewD.get());
312 ASSERT_EQ(nullptr, D);
313
314 // Converting from D to B is valid, B should have a value and D should be
315 // nullptr.
316 auto B = unique_dyn_cast<base>(Val&: NewD);
317 ASSERT_EQ(OrigD, B.get());
318 ASSERT_EQ(nullptr, NewD);
319
320 // Converting from B to itself is valid, it should return a new unique_ptr
321 // and the old one should become nullptr.
322 auto NewB = unique_dyn_cast<base>(Val&: B);
323 ASSERT_EQ(OrigD, NewB.get());
324 ASSERT_EQ(nullptr, B);
325
326 // Converting from B to D is valid, D should have a value and B should be
327 // nullptr;
328 D = unique_dyn_cast<derived>(Val&: NewB);
329 ASSERT_EQ(OrigD, D.get());
330 ASSERT_EQ(nullptr, NewB);
331
332 // This is a very contrived test, casting between completely unrelated types
333 // should generally fail to compile. See the classof shenanigans we have in
334 // the definition of `foo` above.
335 auto F = unique_dyn_cast<foo>(Val&: D);
336 ASSERT_EQ(nullptr, F);
337 ASSERT_EQ(OrigD, D.get());
338
339 // All of the above should also hold for temporaries.
340 auto D2 = unique_dyn_cast<derived>(Val: newd());
341 EXPECT_NE(nullptr, D2);
342
343 auto B2 = unique_dyn_cast<derived>(Val: newb());
344 EXPECT_NE(nullptr, B2);
345
346 auto B3 = unique_dyn_cast<base>(Val: newb());
347 EXPECT_NE(nullptr, B3);
348
349 // This is a very contrived test, casting between completely unrelated types
350 // should generally fail to compile. See the classof shenanigans we have in
351 // the definition of `foo` above.
352 auto F2 = unique_dyn_cast<foo>(Val: newb());
353 EXPECT_EQ(nullptr, F2);
354}
355
356// These lines are errors...
357// foo *F20 = cast<foo>(B2); // Yields const foo*
358// foo &F21 = cast<foo>(B3); // Yields const foo&
359// foo *F22 = cast<foo>(B4); // Yields const foo*
360// foo &F23 = cast_or_null<foo>(B1);
361// const foo &F24 = cast_or_null<foo>(B3);
362
363const bar *B2 = &B;
364} // anonymous namespace
365
366bar *llvm::fub() { return nullptr; }
367
368namespace {
369namespace inferred_upcasting {
370// This test case verifies correct behavior of inferred upcasts when the
371// types are statically known to be OK to upcast. This is the case when,
372// for example, Derived inherits from Base, and we do `isa<Base>(Derived)`.
373
374// Note: This test will actually fail to compile without inferred
375// upcasting.
376
377class Base {
378public:
379 // No classof. We are testing that the upcast is inferred.
380 Base() {}
381};
382
383class Derived : public Base {
384public:
385 Derived() {}
386};
387
388// Even with no explicit classof() in Base, we should still be able to cast
389// Derived to its base class.
390TEST(CastingTest, UpcastIsInferred) {
391 Derived D;
392 EXPECT_TRUE(isa<Base>(D));
393 Base *BP = dyn_cast<Base>(Val: &D);
394 EXPECT_NE(BP, nullptr);
395}
396
397// This test verifies that the inferred upcast takes precedence over an
398// explicitly written one. This is important because it verifies that the
399// dynamic check gets optimized away.
400class UseInferredUpcast {
401public:
402 int Dummy;
403 static bool classof(const UseInferredUpcast *) { return false; }
404};
405
406TEST(CastingTest, InferredUpcastTakesPrecedence) {
407 UseInferredUpcast UIU;
408 // Since the explicit classof() returns false, this will fail if the
409 // explicit one is used.
410 EXPECT_TRUE(isa<UseInferredUpcast>(&UIU));
411}
412
413} // end namespace inferred_upcasting
414} // end anonymous namespace
415
416namespace {
417namespace pointer_wrappers {
418
419struct Base {
420 bool IsDerived;
421 Base(bool IsDerived = false) : IsDerived(IsDerived) {}
422};
423
424struct Derived : Base {
425 Derived() : Base(true) {}
426 static bool classof(const Base *B) { return B->IsDerived; }
427};
428
429class PTy {
430 Base *B;
431
432public:
433 PTy(Base *B) : B(B) {}
434 explicit operator bool() const { return get(); }
435 Base *get() const { return B; }
436};
437
438} // end namespace pointer_wrappers
439} // end namespace
440
441namespace llvm {
442
443template <> struct ValueIsPresent<pointer_wrappers::PTy> {
444 using UnwrappedType = pointer_wrappers::PTy;
445 static inline bool isPresent(const pointer_wrappers::PTy &P) {
446 return P.get() != nullptr;
447 }
448 static UnwrappedType &unwrapValue(pointer_wrappers::PTy &P) { return P; }
449};
450
451template <> struct ValueIsPresent<const pointer_wrappers::PTy> {
452 using UnwrappedType = pointer_wrappers::PTy;
453 static inline bool isPresent(const pointer_wrappers::PTy &P) {
454 return P.get() != nullptr;
455 }
456
457 static UnwrappedType &unwrapValue(const pointer_wrappers::PTy &P) {
458 return const_cast<UnwrappedType &>(P);
459 }
460};
461
462template <> struct simplify_type<pointer_wrappers::PTy> {
463 typedef pointer_wrappers::Base *SimpleType;
464 static SimpleType getSimplifiedValue(pointer_wrappers::PTy &P) {
465 return P.get();
466 }
467};
468template <> struct simplify_type<const pointer_wrappers::PTy> {
469 typedef pointer_wrappers::Base *SimpleType;
470 static SimpleType getSimplifiedValue(const pointer_wrappers::PTy &P) {
471 return P.get();
472 }
473};
474
475} // end namespace llvm
476
477namespace {
478namespace pointer_wrappers {
479
480// Some objects.
481pointer_wrappers::Base B;
482pointer_wrappers::Derived D;
483
484// Mutable "smart" pointers.
485pointer_wrappers::PTy MN(nullptr);
486pointer_wrappers::PTy MB(&B);
487pointer_wrappers::PTy MD(&D);
488
489// Const "smart" pointers.
490const pointer_wrappers::PTy CN(nullptr);
491const pointer_wrappers::PTy CB(&B);
492const pointer_wrappers::PTy CD(&D);
493
494TEST(CastingTest, smart_isa) {
495 EXPECT_TRUE(!isa<pointer_wrappers::Derived>(MB));
496 EXPECT_TRUE(!isa<pointer_wrappers::Derived>(CB));
497 EXPECT_TRUE(isa<pointer_wrappers::Derived>(MD));
498 EXPECT_TRUE(isa<pointer_wrappers::Derived>(CD));
499}
500
501TEST(CastingTest, smart_cast) {
502 EXPECT_EQ(cast<pointer_wrappers::Derived>(MD), &D);
503 EXPECT_EQ(cast<pointer_wrappers::Derived>(CD), &D);
504}
505
506TEST(CastingTest, smart_cast_or_null) {
507 EXPECT_EQ(cast_or_null<pointer_wrappers::Derived>(MN), nullptr);
508 EXPECT_EQ(cast_or_null<pointer_wrappers::Derived>(CN), nullptr);
509 EXPECT_EQ(cast_or_null<pointer_wrappers::Derived>(MD), &D);
510 EXPECT_EQ(cast_or_null<pointer_wrappers::Derived>(CD), &D);
511}
512
513TEST(CastingTest, smart_dyn_cast) {
514 EXPECT_EQ(dyn_cast<pointer_wrappers::Derived>(MB), nullptr);
515 EXPECT_EQ(dyn_cast<pointer_wrappers::Derived>(CB), nullptr);
516 EXPECT_EQ(dyn_cast<pointer_wrappers::Derived>(MD), &D);
517 EXPECT_EQ(dyn_cast<pointer_wrappers::Derived>(CD), &D);
518}
519
520TEST(CastingTest, smart_dyn_cast_or_null) {
521 EXPECT_EQ(dyn_cast_or_null<pointer_wrappers::Derived>(MN), nullptr);
522 EXPECT_EQ(dyn_cast_or_null<pointer_wrappers::Derived>(CN), nullptr);
523 EXPECT_EQ(dyn_cast_or_null<pointer_wrappers::Derived>(MB), nullptr);
524 EXPECT_EQ(dyn_cast_or_null<pointer_wrappers::Derived>(CB), nullptr);
525 EXPECT_EQ(dyn_cast_or_null<pointer_wrappers::Derived>(MD), &D);
526 EXPECT_EQ(dyn_cast_or_null<pointer_wrappers::Derived>(CD), &D);
527}
528
529} // end namespace pointer_wrappers
530
531#ifndef NDEBUG
532namespace assertion_checks {
533struct Base {
534 virtual ~Base() {}
535};
536
537struct Derived : public Base {
538 static bool classof(const Base *B) { return false; }
539};
540
541TEST(CastingTest, assertion_check_const_ref) {
542 const Base B;
543 EXPECT_DEATH((void)cast<Derived>(B), "argument of incompatible type")
544 << "Invalid cast of const ref did not cause an abort()";
545}
546
547TEST(CastingTest, assertion_check_ref) {
548 Base B;
549 EXPECT_DEATH((void)cast<Derived>(B), "argument of incompatible type")
550 << "Invalid cast of const ref did not cause an abort()";
551}
552
553TEST(CastingTest, assertion_check_ptr) {
554 Base B;
555 EXPECT_DEATH((void)cast<Derived>(&B), "argument of incompatible type")
556 << "Invalid cast of const ref did not cause an abort()";
557}
558
559TEST(CastingTest, assertion_check_unique_ptr) {
560 auto B = std::make_unique<Base>();
561 EXPECT_DEATH((void)cast<Derived>(std::move(B)),
562 "argument of incompatible type")
563 << "Invalid cast of const ref did not cause an abort()";
564}
565
566} // end namespace assertion_checks
567#endif
568} // end namespace
569

source code of llvm/unittests/Support/Casting.cpp