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;
cast(...)20 template <typename T> IllegalCast *cast(...) { return nullptr; }
21
22 // set up two example classes
23 // with conversion facility
24 //
25 struct bar {
barllvm::bar26 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 {
~basellvm::base43 virtual ~base() {}
44 };
45
46 struct derived : public base {
classofllvm::derived47 static bool classof(const base *B) { return true; }
48 };
49
50 template <> struct isa_impl<foo, bar> {
doitllvm::isa_impl51 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> {
doitllvm::isa_impl58 static inline bool doit(const T &Val) { return false; }
59 };
60
baz()61 foo *bar::baz() {
62 return cast<foo>(this);
63 }
64
caz()65 foo *bar::caz() {
66 return cast_or_null<foo>(this);
67 }
68
daz()69 foo *bar::daz() {
70 return dyn_cast<foo>(this);
71 }
72
naz()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;
getSimplifiedValuellvm::simplify_type82 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
TEST(CastingTest,isa)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
TEST(CastingTest,isa_and_nonnull)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
TEST(CastingTest,cast)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
TEST(CastingTest,cast_or_null)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
TEST(CastingTest,dyn_cast)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
TEST(CastingTest,dyn_cast_or_null)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
newd()196 std::unique_ptr<derived> newd() { return std::make_unique<derived>(); }
newb()197 std::unique_ptr<base> newb() { return std::make_unique<derived>(); }
198
TEST(CastingTest,unique_dyn_cast)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
fub()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.
Base()272 Base() {}
273 };
274
275 class Derived : public Base {
276 public:
Derived()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.
TEST(CastingTest,UpcastIsInferred)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;
classof(const UseInferredUpcast *)296 static bool classof(const UseInferredUpcast *) {
297 return false;
298 }
299 };
300
TEST(CastingTest,InferredUpcastTakesPrecedence)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 {};
testIllegalCast()313 IllegalCast *testIllegalCast() { return cast<foo>(pod()); }
314 }
315
316 namespace {
317 namespace pointer_wrappers {
318
319 struct Base {
320 bool IsDerived;
Base__anon7e6d81b80311::pointer_wrappers::Base321 Base(bool IsDerived = false) : IsDerived(IsDerived) {}
322 };
323
324 struct Derived : Base {
Derived__anon7e6d81b80311::pointer_wrappers::Derived325 Derived() : Base(true) {}
classof__anon7e6d81b80311::pointer_wrappers::Derived326 static bool classof(const Base *B) { return B->IsDerived; }
327 };
328
329 class PTy {
330 Base *B;
331 public:
PTy(Base * B)332 PTy(Base *B) : B(B) {}
operator bool() const333 explicit operator bool() const { return get(); }
get() const334 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;
getSimplifiedValuellvm::simplify_type344 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;
getSimplifiedValuellvm::simplify_type350 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
TEST(CastingTest,smart_isa)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
TEST(CastingTest,smart_cast)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
TEST(CastingTest,smart_cast_or_null)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
TEST(CastingTest,smart_dyn_cast)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
TEST(CastingTest,smart_dyn_cast_or_null)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