llvm.org GIT mirror llvm / 5deb1bf
Support: Add *cast_or_null<> for pointer wrappers Fill in omission of `cast_or_null<>` and `dyn_cast_or_null<>` for types that wrap pointers (e.g., smart pointers). Type traits need to be slightly stricter than for `cast<>` and `dyn_cast<>` to resolve ambiguities with simple types. There didn't seem to be any unit tests for pointer wrappers, so I tested `isa<>`, `cast<>`, and `dyn_cast<>` while I was in there. This only supports pointer wrappers with a conversion to `bool` to check for null. If in the future it's useful to support wrappers without such a conversion, it should be a straightforward incremental step to use the `simplify_type` machinery for the null check. In that case, the unit tests should be updated to remove the `operator bool()` from the `pointer_wrappers::PTy`. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222644 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 4 years ago
2 changed file(s) with 130 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
242242 // accepted.
243243 //
244244 template
245 LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
246 !is_simple_type::value, typename cast_retty::ret_type>::type
247 cast_or_null(const Y &Val) {
248 if (!Val)
249 return nullptr;
250 assert(isa(Val) && "cast_or_null() argument of incompatible type!");
251 return cast(Val);
252 }
253
254 template
255 LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
256 !is_simple_type::value, typename cast_retty::ret_type>::type
257 cast_or_null(Y &Val) {
258 if (!Val)
259 return nullptr;
260 assert(isa(Val) && "cast_or_null() argument of incompatible type!");
261 return cast(Val);
262 }
263
264 template
245265 LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty::ret_type
246266 cast_or_null(Y *Val) {
247267 if (!Val) return nullptr;
281301 // value is accepted.
282302 //
283303 template
304 LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
305 !is_simple_type::value, typename cast_retty::ret_type>::type
306 dyn_cast_or_null(const Y &Val) {
307 return (Val && isa(Val)) ? cast(Val) : nullptr;
308 }
309
310 template
311 LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
312 !is_simple_type::value, typename cast_retty::ret_type>::type
313 dyn_cast_or_null(Y &Val) {
314 return (Val && isa(Val)) ? cast(Val) : nullptr;
315 }
316
317 template
284318 LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty::ret_type
285319 dyn_cast_or_null(Y *Val) {
286320 return (Val && isa(Val)) ? cast(Val) : nullptr;
231231 struct pod {};
232232 IllegalCast *testIllegalCast() { return cast(pod()); }
233233 }
234
235 namespace {
236 namespace pointer_wrappers {
237
238 struct Base {
239 bool IsDerived;
240 Base(bool IsDerived = false) : IsDerived(IsDerived) {}
241 };
242
243 struct Derived : Base {
244 Derived() : Base(true) {}
245 static bool classof(const Base *B) { return B->IsDerived; }
246 };
247
248 class PTy {
249 Base *B;
250 public:
251 PTy(Base *B) : B(B) {}
252 LLVM_EXPLICIT operator bool() const { return get(); }
253 Base *get() const { return B; }
254 };
255
256 } // end namespace pointer_wrappers
257 } // end namespace
258
259 namespace llvm {
260
261 template <> struct simplify_type {
262 typedef pointer_wrappers::Base *SimpleType;
263 static SimpleType getSimplifiedValue(pointer_wrappers::PTy &P) {
264 return P.get();
265 }
266 };
267 template <> struct simplify_type {
268 typedef pointer_wrappers::Base *SimpleType;
269 static SimpleType getSimplifiedValue(const pointer_wrappers::PTy &P) {
270 return P.get();
271 }
272 };
273
274 } // end namespace llvm
275
276 namespace {
277 namespace pointer_wrappers {
278
279 // Some objects.
280 pointer_wrappers::Base B;
281 pointer_wrappers::Derived D;
282
283 // Mutable "smart" pointers.
284 pointer_wrappers::PTy MN(nullptr);
285 pointer_wrappers::PTy MB(&B);
286 pointer_wrappers::PTy MD(&D);
287
288 // Const "smart" pointers.
289 const pointer_wrappers::PTy CN(nullptr);
290 const pointer_wrappers::PTy CB(&B);
291 const pointer_wrappers::PTy CD(&D);
292
293 TEST(CastingTest, smart_isa) {
294 EXPECT_TRUE(!isa(MB));
295 EXPECT_TRUE(!isa(CB));
296 EXPECT_TRUE(isa(MD));
297 EXPECT_TRUE(isa(CD));
298 }
299
300 TEST(CastingTest, smart_cast) {
301 EXPECT_TRUE(cast(MD) == &D);
302 EXPECT_TRUE(cast(CD) == &D);
303 }
304
305 TEST(CastingTest, smart_cast_or_null) {
306 EXPECT_TRUE(cast_or_null(MN) == nullptr);
307 EXPECT_TRUE(cast_or_null(CN) == nullptr);
308 EXPECT_TRUE(cast_or_null(MD) == &D);
309 EXPECT_TRUE(cast_or_null(CD) == &D);
310 }
311
312 TEST(CastingTest, smart_dyn_cast) {
313 EXPECT_TRUE(dyn_cast(MB) == nullptr);
314 EXPECT_TRUE(dyn_cast(CB) == nullptr);
315 EXPECT_TRUE(dyn_cast(MD) == &D);
316 EXPECT_TRUE(dyn_cast(CD) == &D);
317 }
318
319 TEST(CastingTest, smart_dyn_cast_or_null) {
320 EXPECT_TRUE(dyn_cast_or_null(MN) == nullptr);
321 EXPECT_TRUE(dyn_cast_or_null(CN) == nullptr);
322 EXPECT_TRUE(dyn_cast_or_null(MB) == nullptr);
323 EXPECT_TRUE(dyn_cast_or_null(CB) == nullptr);
324 EXPECT_TRUE(dyn_cast_or_null(MD) == &D);
325 EXPECT_TRUE(dyn_cast_or_null(CD) == &D);
326 }
327
328 } // end namespace pointer_wrappers
329 } // end namespace