0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1 //===---------- llvm/unittest/Support/Casting.cpp - Casting tests ---------===//
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
2 //
|
147
|
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
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
6 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
7 //===----------------------------------------------------------------------===//
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
8
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
9 #include "llvm/Support/Casting.h"
|
77
|
10 #include "llvm/IR/User.h"
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
11 #include "llvm/Support/Debug.h"
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
12 #include "llvm/Support/raw_ostream.h"
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
13 #include "gtest/gtest.h"
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
14 #include <cstdlib>
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
15
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
16 namespace llvm {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
17 // Used to test illegal cast. If a cast doesn't match any of the "real" ones,
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
18 // it will match this one.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
19 struct IllegalCast;
|
77
|
20 template <typename T> IllegalCast *cast(...) { return nullptr; }
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
21
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
22 // set up two example classes
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
23 // with conversion facility
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
24 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
25 struct bar {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
26 bar() {}
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
27 struct foo *baz();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
28 struct foo *caz();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
29 struct foo *daz();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
30 struct foo *naz();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
31 private:
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
32 bar(const bar &);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
33 };
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
34 struct foo {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
35 void ext() const;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
36 /* static bool classof(const bar *X) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
37 cerr << "Classof: " << X << "\n";
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
38 return true;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
39 }*/
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
40 };
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
41
|
121
|
42 struct base {
|
|
43 virtual ~base() {}
|
|
44 };
|
|
45
|
|
46 struct derived : public base {
|
|
47 static bool classof(const base *B) { return true; }
|
|
48 };
|
|
49
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
50 template <> struct isa_impl<foo, bar> {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
51 static inline bool doit(const bar &Val) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
52 dbgs() << "Classof: " << &Val << "\n";
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
53 return true;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
54 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
55 };
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
56
|
121
|
57 template <typename T> struct isa_impl<foo, T> {
|
|
58 static inline bool doit(const T &Val) { return false; }
|
|
59 };
|
|
60
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
61 foo *bar::baz() {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
62 return cast<foo>(this);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
63 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
64
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
65 foo *bar::caz() {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
66 return cast_or_null<foo>(this);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
67 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
68
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
69 foo *bar::daz() {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
70 return dyn_cast<foo>(this);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
71 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
72
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
73 foo *bar::naz() {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
74 return dyn_cast_or_null<foo>(this);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
75 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
76
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
77
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
78 bar *fub();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
79
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
80 template <> struct simplify_type<foo> {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
81 typedef int SimpleType;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
82 static SimpleType getSimplifiedValue(foo &Val) { return 0; }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
83 };
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
84
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
85 } // End llvm namespace
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
86
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
87 using namespace llvm;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
88
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
89
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
90 // Test the peculiar behavior of Use in simplify_type.
|
77
|
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!");
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
95
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
96 // Test that a regular class behaves as expected.
|
77
|
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!");
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
101
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
102 namespace {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
103
|
77
|
104 const foo *null_foo = nullptr;
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
105
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
106 bar B;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
107 extern bar &B1;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
108 bar &B1 = B;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
109 extern const bar *B2;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
110 // test various configurations of const
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
111 const bar &B3 = B1;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
112 const bar *const B4 = B2;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
113
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
114 TEST(CastingTest, isa) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
115 EXPECT_TRUE(isa<foo>(B1));
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
116 EXPECT_TRUE(isa<foo>(B2));
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
117 EXPECT_TRUE(isa<foo>(B3));
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
118 EXPECT_TRUE(isa<foo>(B4));
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
119 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
120
|
147
|
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
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
127 TEST(CastingTest, cast) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
128 foo &F1 = cast<foo>(B1);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
129 EXPECT_NE(&F1, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
130 const foo *F3 = cast<foo>(B2);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
131 EXPECT_NE(F3, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
132 const foo *F4 = cast<foo>(B2);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
133 EXPECT_NE(F4, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
134 const foo &F5 = cast<foo>(B3);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
135 EXPECT_NE(&F5, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
136 const foo *F6 = cast<foo>(B4);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
137 EXPECT_NE(F6, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
138 // Can't pass null pointer to cast<>.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
139 // foo *F7 = cast<foo>(fub());
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
140 // EXPECT_EQ(F7, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
141 foo *F8 = B1.baz();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
142 EXPECT_NE(F8, null_foo);
|
121
|
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();
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
150 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
151
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
152 TEST(CastingTest, cast_or_null) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
153 const foo *F11 = cast_or_null<foo>(B2);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
154 EXPECT_NE(F11, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
155 const foo *F12 = cast_or_null<foo>(B2);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
156 EXPECT_NE(F12, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
157 const foo *F13 = cast_or_null<foo>(B4);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
158 EXPECT_NE(F13, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
159 const foo *F14 = cast_or_null<foo>(fub()); // Shouldn't print.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
160 EXPECT_EQ(F14, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
161 foo *F15 = B1.caz();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
162 EXPECT_NE(F15, null_foo);
|
121
|
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);
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
167 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
168
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
169 TEST(CastingTest, dyn_cast) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
170 const foo *F1 = dyn_cast<foo>(B2);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
171 EXPECT_NE(F1, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
172 const foo *F2 = dyn_cast<foo>(B2);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
173 EXPECT_NE(F2, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
174 const foo *F3 = dyn_cast<foo>(B4);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
175 EXPECT_NE(F3, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
176 // Can't pass null pointer to dyn_cast<>.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
177 // foo *F4 = dyn_cast<foo>(fub());
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
178 // EXPECT_EQ(F4, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
179 foo *F5 = B1.daz();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
180 EXPECT_NE(F5, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
181 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
182
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
183 TEST(CastingTest, dyn_cast_or_null) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
184 const foo *F1 = dyn_cast_or_null<foo>(B2);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
185 EXPECT_NE(F1, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
186 const foo *F2 = dyn_cast_or_null<foo>(B2);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
187 EXPECT_NE(F2, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
188 const foo *F3 = dyn_cast_or_null<foo>(B4);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
189 EXPECT_NE(F3, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
190 foo *F4 = dyn_cast_or_null<foo>(fub());
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
191 EXPECT_EQ(F4, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
192 foo *F5 = B1.naz();
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
193 EXPECT_NE(F5, null_foo);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
194 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
195
|
121
|
196 std::unique_ptr<derived> newd() { return llvm::make_unique<derived>(); }
|
|
197 std::unique_ptr<base> newb() { return llvm::make_unique<derived>(); }
|
|
198
|
|
199 TEST(CastingTest, unique_dyn_cast) {
|
|
200 derived *OrigD = nullptr;
|
|
201 auto D = llvm::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
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
248 // These lines are errors...
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
249 //foo *F20 = cast<foo>(B2); // Yields const foo*
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
250 //foo &F21 = cast<foo>(B3); // Yields const foo&
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
251 //foo *F22 = cast<foo>(B4); // Yields const foo*
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
252 //foo &F23 = cast_or_null<foo>(B1);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
253 //const foo &F24 = cast_or_null<foo>(B3);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
254
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
255 const bar *B2 = &B;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
256 } // anonymous namespace
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
257
|
77
|
258 bar *llvm::fub() { return nullptr; }
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
259
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
260 namespace {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
261 namespace inferred_upcasting {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
262 // This test case verifies correct behavior of inferred upcasts when the
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
263 // types are statically known to be OK to upcast. This is the case when,
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
264 // for example, Derived inherits from Base, and we do `isa<Base>(Derived)`.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
265
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
266 // Note: This test will actually fail to compile without inferred
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
267 // upcasting.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
268
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
269 class Base {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
270 public:
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
271 // No classof. We are testing that the upcast is inferred.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
272 Base() {}
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
273 };
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
274
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
275 class Derived : public Base {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
276 public:
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
277 Derived() {}
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
278 };
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
279
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
280 // Even with no explicit classof() in Base, we should still be able to cast
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
281 // Derived to its base class.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
282 TEST(CastingTest, UpcastIsInferred) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
283 Derived D;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
284 EXPECT_TRUE(isa<Base>(D));
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
285 Base *BP = dyn_cast<Base>(&D);
|
77
|
286 EXPECT_TRUE(BP != nullptr);
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
287 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
288
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
289
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
290 // This test verifies that the inferred upcast takes precedence over an
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
291 // explicitly written one. This is important because it verifies that the
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
292 // dynamic check gets optimized away.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
293 class UseInferredUpcast {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
294 public:
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
295 int Dummy;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
296 static bool classof(const UseInferredUpcast *) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
297 return false;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
298 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
299 };
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
300
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
301 TEST(CastingTest, InferredUpcastTakesPrecedence) {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
302 UseInferredUpcast UIU;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
303 // Since the explicit classof() returns false, this will fail if the
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
304 // explicit one is used.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
305 EXPECT_TRUE(isa<UseInferredUpcast>(&UIU));
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
306 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
307
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
308 } // end namespace inferred_upcasting
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
309 } // end anonymous namespace
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
310 // Test that we reject casts of temporaries (and so the illegal cast gets used).
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
311 namespace TemporaryCast {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
312 struct pod {};
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
313 IllegalCast *testIllegalCast() { return cast<foo>(pod()); }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
314 }
|
83
|
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
|