1 //===- llvm/Support/Casting.h - Allow flexible, checked, casts --*- C++ -*-===// 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 // This file defines the isa<X>(), cast<X>(), dyn_cast<X>(), cast_or_null<X>(), 10 // and dyn_cast_or_null<X>() templates. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_SUPPORT_CASTING_H 15 #define LLVM_SUPPORT_CASTING_H 16 17 #include "llvm/Support/Compiler.h" 18 #include "llvm/Support/type_traits.h" 19 #include <cassert> 20 #include <memory> 21 #include <type_traits> 22 23 namespace llvm { 24 25 //===----------------------------------------------------------------------===// 26 // isa<x> Support Templates 27 //===----------------------------------------------------------------------===// 28 29 // Define a template that can be specialized by smart pointers to reflect the 30 // fact that they are automatically dereferenced, and are not involved with the 31 // template selection process... the default implementation is a noop. 32 // 33 template<typename From> struct simplify_type { 34 using SimpleType = From; // The real type this represents... 35 36 // An accessor to get the real value... getSimplifiedValuesimplify_type37 static SimpleType &getSimplifiedValue(From &Val) { return Val; } 38 }; 39 40 template<typename From> struct simplify_type<const From> { 41 using NonConstSimpleType = typename simplify_type<From>::SimpleType; 42 using SimpleType = 43 typename add_const_past_pointer<NonConstSimpleType>::type; 44 using RetType = 45 typename add_lvalue_reference_if_not_pointer<SimpleType>::type; 46 47 static RetType getSimplifiedValue(const From& Val) { 48 return simplify_type<From>::getSimplifiedValue(const_cast<From&>(Val)); 49 } 50 }; 51 52 // The core of the implementation of isa<X> is here; To and From should be 53 // the names of classes. This template can be specialized to customize the 54 // implementation of isa<> without rewriting it from scratch. 55 template <typename To, typename From, typename Enabler = void> 56 struct isa_impl { 57 static inline bool doit(const From &Val) { 58 return To::classof(&Val); 59 } 60 }; 61 62 /// Always allow upcasts, and perform no dynamic check for them. 63 template <typename To, typename From> 64 struct isa_impl<To, From, std::enable_if_t<std::is_base_of<To, From>::value>> { 65 static inline bool doit(const From &) { return true; } 66 }; 67 68 template <typename To, typename From> struct isa_impl_cl { 69 static inline bool doit(const From &Val) { 70 return isa_impl<To, From>::doit(Val); 71 } 72 }; 73 74 template <typename To, typename From> struct isa_impl_cl<To, const From> { 75 static inline bool doit(const From &Val) { 76 return isa_impl<To, From>::doit(Val); 77 } 78 }; 79 80 template <typename To, typename From> 81 struct isa_impl_cl<To, const std::unique_ptr<From>> { 82 static inline bool doit(const std::unique_ptr<From> &Val) { 83 assert(Val && "isa<> used on a null pointer"); 84 return isa_impl_cl<To, From>::doit(*Val); 85 } 86 }; 87 88 template <typename To, typename From> struct isa_impl_cl<To, From*> { 89 static inline bool doit(const From *Val) { 90 assert(Val && "isa<> used on a null pointer"); 91 return isa_impl<To, From>::doit(*Val); 92 } 93 }; 94 95 template <typename To, typename From> struct isa_impl_cl<To, From*const> { 96 static inline bool doit(const From *Val) { 97 assert(Val && "isa<> used on a null pointer"); 98 return isa_impl<To, From>::doit(*Val); 99 } 100 }; 101 102 template <typename To, typename From> struct isa_impl_cl<To, const From*> { 103 static inline bool doit(const From *Val) { 104 assert(Val && "isa<> used on a null pointer"); 105 return isa_impl<To, From>::doit(*Val); 106 } 107 }; 108 109 template <typename To, typename From> struct isa_impl_cl<To, const From*const> { 110 static inline bool doit(const From *Val) { 111 assert(Val && "isa<> used on a null pointer"); 112 return isa_impl<To, From>::doit(*Val); 113 } 114 }; 115 116 template<typename To, typename From, typename SimpleFrom> 117 struct isa_impl_wrap { 118 // When From != SimplifiedType, we can simplify the type some more by using 119 // the simplify_type template. 120 static bool doit(const From &Val) { 121 return isa_impl_wrap<To, SimpleFrom, 122 typename simplify_type<SimpleFrom>::SimpleType>::doit( 123 simplify_type<const From>::getSimplifiedValue(Val)); 124 } 125 }; 126 127 template<typename To, typename FromTy> 128 struct isa_impl_wrap<To, FromTy, FromTy> { 129 // When From == SimpleType, we are as simple as we are going to get. 130 static bool doit(const FromTy &Val) { 131 return isa_impl_cl<To,FromTy>::doit(Val); 132 } 133 }; 134 135 // isa<X> - Return true if the parameter to the template is an instance of one 136 // of the template type arguments. Used like this: 137 // 138 // if (isa<Type>(myVal)) { ... } 139 // if (isa<Type0, Type1, Type2>(myVal)) { ... } 140 // 141 template <class X, class Y> LLVM_NODISCARD inline bool isa(const Y &Val) { 142 return isa_impl_wrap<X, const Y, 143 typename simplify_type<const Y>::SimpleType>::doit(Val); 144 } 145 146 template <typename First, typename Second, typename... Rest, typename Y> 147 LLVM_NODISCARD inline bool isa(const Y &Val) { 148 return isa<First>(Val) || isa<Second, Rest...>(Val); 149 } 150 151 // isa_and_nonnull<X> - Functionally identical to isa, except that a null value 152 // is accepted. 153 // 154 template <typename... X, class Y> 155 LLVM_NODISCARD inline bool isa_and_nonnull(const Y &Val) { 156 if (!Val) 157 return false; 158 return isa<X...>(Val); 159 } 160 161 //===----------------------------------------------------------------------===// 162 // cast<x> Support Templates 163 //===----------------------------------------------------------------------===// 164 165 template<class To, class From> struct cast_retty; 166 167 // Calculate what type the 'cast' function should return, based on a requested 168 // type of To and a source type of From. 169 template<class To, class From> struct cast_retty_impl { 170 using ret_type = To &; // Normal case, return Ty& 171 }; 172 template<class To, class From> struct cast_retty_impl<To, const From> { 173 using ret_type = const To &; // Normal case, return Ty& 174 }; 175 176 template<class To, class From> struct cast_retty_impl<To, From*> { 177 using ret_type = To *; // Pointer arg case, return Ty* 178 }; 179 180 template<class To, class From> struct cast_retty_impl<To, const From*> { 181 using ret_type = const To *; // Constant pointer arg case, return const Ty* 182 }; 183 184 template<class To, class From> struct cast_retty_impl<To, const From*const> { 185 using ret_type = const To *; // Constant pointer arg case, return const Ty* 186 }; 187 188 template <class To, class From> 189 struct cast_retty_impl<To, std::unique_ptr<From>> { 190 private: 191 using PointerType = typename cast_retty_impl<To, From *>::ret_type; 192 using ResultType = std::remove_pointer_t<PointerType>; 193 194 public: 195 using ret_type = std::unique_ptr<ResultType>; 196 }; 197 198 template<class To, class From, class SimpleFrom> 199 struct cast_retty_wrap { 200 // When the simplified type and the from type are not the same, use the type 201 // simplifier to reduce the type, then reuse cast_retty_impl to get the 202 // resultant type. 203 using ret_type = typename cast_retty<To, SimpleFrom>::ret_type; 204 }; 205 206 template<class To, class FromTy> 207 struct cast_retty_wrap<To, FromTy, FromTy> { 208 // When the simplified type is equal to the from type, use it directly. 209 using ret_type = typename cast_retty_impl<To,FromTy>::ret_type; 210 }; 211 212 template<class To, class From> 213 struct cast_retty { 214 using ret_type = typename cast_retty_wrap< 215 To, From, typename simplify_type<From>::SimpleType>::ret_type; 216 }; 217 218 // Ensure the non-simple values are converted using the simplify_type template 219 // that may be specialized by smart pointers... 220 // 221 template<class To, class From, class SimpleFrom> struct cast_convert_val { 222 // This is not a simple type, use the template to simplify it... 223 static typename cast_retty<To, From>::ret_type doit(From &Val) { 224 return cast_convert_val<To, SimpleFrom, 225 typename simplify_type<SimpleFrom>::SimpleType>::doit( 226 simplify_type<From>::getSimplifiedValue(Val)); 227 } 228 }; 229 230 template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { 231 // This _is_ a simple type, just cast it. 232 static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) { 233 typename cast_retty<To, FromTy>::ret_type Res2 234 = (typename cast_retty<To, FromTy>::ret_type)const_cast<FromTy&>(Val); 235 return Res2; 236 } 237 }; 238 239 template <class X> struct is_simple_type { 240 static const bool value = 241 std::is_same<X, typename simplify_type<X>::SimpleType>::value; 242 }; 243 244 // cast<X> - Return the argument parameter cast to the specified type. This 245 // casting operator asserts that the type is correct, so it does not return null 246 // on failure. It does not allow a null argument (use cast_or_null for that). 247 // It is typically used like this: 248 // 249 // cast<Instruction>(myVal)->getParent() 250 // 251 template <class X, class Y> 252 inline std::enable_if_t<!is_simple_type<Y>::value, 253 typename cast_retty<X, const Y>::ret_type> 254 cast(const Y &Val) { 255 assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); 256 return cast_convert_val< 257 X, const Y, typename simplify_type<const Y>::SimpleType>::doit(Val); 258 } 259 260 template <class X, class Y> 261 inline typename cast_retty<X, Y>::ret_type cast(Y &Val) { 262 assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); 263 return cast_convert_val<X, Y, 264 typename simplify_type<Y>::SimpleType>::doit(Val); 265 } 266 267 template <class X, class Y> 268 inline typename cast_retty<X, Y *>::ret_type cast(Y *Val) { 269 assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); 270 return cast_convert_val<X, Y*, 271 typename simplify_type<Y*>::SimpleType>::doit(Val); 272 } 273 274 template <class X, class Y> 275 inline typename cast_retty<X, std::unique_ptr<Y>>::ret_type 276 cast(std::unique_ptr<Y> &&Val) { 277 assert(isa<X>(Val.get()) && "cast<Ty>() argument of incompatible type!"); 278 using ret_type = typename cast_retty<X, std::unique_ptr<Y>>::ret_type; 279 return ret_type( 280 cast_convert_val<X, Y *, typename simplify_type<Y *>::SimpleType>::doit( 281 Val.release())); 282 } 283 284 // cast_or_null<X> - Functionally identical to cast, except that a null value is 285 // accepted. 286 // 287 template <class X, class Y> 288 LLVM_NODISCARD inline std::enable_if_t< 289 !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type> 290 cast_or_null(const Y &Val) { 291 if (!Val) 292 return nullptr; 293 assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); 294 return cast<X>(Val); 295 } 296 297 template <class X, class Y> 298 LLVM_NODISCARD inline std::enable_if_t<!is_simple_type<Y>::value, 299 typename cast_retty<X, Y>::ret_type> 300 cast_or_null(Y &Val) { 301 if (!Val) 302 return nullptr; 303 assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); 304 return cast<X>(Val); 305 } 306 307 template <class X, class Y> 308 LLVM_NODISCARD inline typename cast_retty<X, Y *>::ret_type 309 cast_or_null(Y *Val) { 310 if (!Val) return nullptr; 311 assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); 312 return cast<X>(Val); 313 } 314 315 template <class X, class Y> 316 inline typename cast_retty<X, std::unique_ptr<Y>>::ret_type 317 cast_or_null(std::unique_ptr<Y> &&Val) { 318 if (!Val) 319 return nullptr; 320 return cast<X>(std::move(Val)); 321 } 322 323 // dyn_cast<X> - Return the argument parameter cast to the specified type. This 324 // casting operator returns null if the argument is of the wrong type, so it can 325 // be used to test for a type as well as cast if successful. This should be 326 // used in the context of an if statement like this: 327 // 328 // if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... } 329 // 330 331 template <class X, class Y> 332 LLVM_NODISCARD inline std::enable_if_t< 333 !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type> 334 dyn_cast(const Y &Val) { 335 return isa<X>(Val) ? cast<X>(Val) : nullptr; 336 } 337 338 template <class X, class Y> 339 LLVM_NODISCARD inline typename cast_retty<X, Y>::ret_type dyn_cast(Y &Val) { 340 return isa<X>(Val) ? cast<X>(Val) : nullptr; 341 } 342 343 template <class X, class Y> 344 LLVM_NODISCARD inline typename cast_retty<X, Y *>::ret_type dyn_cast(Y *Val) { 345 return isa<X>(Val) ? cast<X>(Val) : nullptr; 346 } 347 348 // dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null 349 // value is accepted. 350 // 351 template <class X, class Y> 352 LLVM_NODISCARD inline std::enable_if_t< 353 !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type> 354 dyn_cast_or_null(const Y &Val) { 355 return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; 356 } 357 358 template <class X, class Y> 359 LLVM_NODISCARD inline std::enable_if_t<!is_simple_type<Y>::value, 360 typename cast_retty<X, Y>::ret_type> 361 dyn_cast_or_null(Y &Val) { 362 return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; 363 } 364 365 template <class X, class Y> 366 LLVM_NODISCARD inline typename cast_retty<X, Y *>::ret_type 367 dyn_cast_or_null(Y *Val) { 368 return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; 369 } 370 371 // unique_dyn_cast<X> - Given a unique_ptr<Y>, try to return a unique_ptr<X>, 372 // taking ownership of the input pointer iff isa<X>(Val) is true. If the 373 // cast is successful, From refers to nullptr on exit and the casted value 374 // is returned. If the cast is unsuccessful, the function returns nullptr 375 // and From is unchanged. 376 template <class X, class Y> 377 LLVM_NODISCARD inline auto unique_dyn_cast(std::unique_ptr<Y> &Val) 378 -> decltype(cast<X>(Val)) { 379 if (!isa<X>(Val)) 380 return nullptr; 381 return cast<X>(std::move(Val)); 382 } 383 384 template <class X, class Y> 385 LLVM_NODISCARD inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val) { 386 return unique_dyn_cast<X, Y>(Val); 387 } 388 389 // dyn_cast_or_null<X> - Functionally identical to unique_dyn_cast, except that 390 // a null value is accepted. 391 template <class X, class Y> 392 LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &Val) 393 -> decltype(cast<X>(Val)) { 394 if (!Val) 395 return nullptr; 396 return unique_dyn_cast<X, Y>(Val); 397 } 398 399 template <class X, class Y> 400 LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val) { 401 return unique_dyn_cast_or_null<X, Y>(Val); 402 } 403 404 } // end namespace llvm 405 406 #endif // LLVM_SUPPORT_CASTING_H 407