1 //===-- llvm/Support/Casting.h - Allow flexible, checked, casts -*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the isa<X>(), cast<X>(), dyn_cast<X>(), cast_or_null<X>(), 11 // and dyn_cast_or_null<X>() templates. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_SUPPORT_CASTING_H 16 #define LLVM_SUPPORT_CASTING_H 17 18 #include "llvm/Support/Compiler.h" 19 #include "llvm/Support/type_traits.h" 20 #include <cassert> 21 22 namespace llvm { 23 24 //===----------------------------------------------------------------------===// 25 // isa<x> Support Templates 26 //===----------------------------------------------------------------------===// 27 28 // Define a template that can be specialized by smart pointers to reflect the 29 // fact that they are automatically dereferenced, and are not involved with the 30 // template selection process... the default implementation is a noop. 31 // 32 template<typename From> struct simplify_type { 33 typedef From SimpleType; // The real type this represents... 34 35 // An accessor to get the real value... getSimplifiedValuesimplify_type36 static SimpleType &getSimplifiedValue(From &Val) { return Val; } 37 }; 38 39 template<typename From> struct simplify_type<const From> { 40 typedef typename simplify_type<From>::SimpleType NonConstSimpleType; 41 typedef typename add_const_past_pointer<NonConstSimpleType>::type 42 SimpleType; 43 typedef typename add_lvalue_reference_if_not_pointer<SimpleType>::type 44 RetType; 45 static RetType getSimplifiedValue(const From& Val) { 46 return simplify_type<From>::getSimplifiedValue(const_cast<From&>(Val)); 47 } 48 }; 49 50 // The core of the implementation of isa<X> is here; To and From should be 51 // the names of classes. This template can be specialized to customize the 52 // implementation of isa<> without rewriting it from scratch. 53 template <typename To, typename From, typename Enabler = void> 54 struct isa_impl { 55 static inline bool doit(const From &Val) { 56 return To::classof(&Val); 57 } 58 }; 59 60 /// \brief Always allow upcasts, and perform no dynamic check for them. 61 template <typename To, typename From> 62 struct isa_impl< 63 To, From, typename std::enable_if<std::is_base_of<To, From>::value>::type> { 64 static inline bool doit(const From &) { return true; } 65 }; 66 67 template <typename To, typename From> struct isa_impl_cl { 68 static inline bool doit(const From &Val) { 69 return isa_impl<To, From>::doit(Val); 70 } 71 }; 72 73 template <typename To, typename From> struct isa_impl_cl<To, const From> { 74 static inline bool doit(const From &Val) { 75 return isa_impl<To, From>::doit(Val); 76 } 77 }; 78 79 template <typename To, typename From> struct isa_impl_cl<To, From*> { 80 static inline bool doit(const From *Val) { 81 assert(Val && "isa<> used on a null pointer"); 82 return isa_impl<To, From>::doit(*Val); 83 } 84 }; 85 86 template <typename To, typename From> struct isa_impl_cl<To, From*const> { 87 static inline bool doit(const From *Val) { 88 assert(Val && "isa<> used on a null pointer"); 89 return isa_impl<To, From>::doit(*Val); 90 } 91 }; 92 93 template <typename To, typename From> struct isa_impl_cl<To, const From*> { 94 static inline bool doit(const From *Val) { 95 assert(Val && "isa<> used on a null pointer"); 96 return isa_impl<To, From>::doit(*Val); 97 } 98 }; 99 100 template <typename To, typename From> struct isa_impl_cl<To, const From*const> { 101 static inline bool doit(const From *Val) { 102 assert(Val && "isa<> used on a null pointer"); 103 return isa_impl<To, From>::doit(*Val); 104 } 105 }; 106 107 template<typename To, typename From, typename SimpleFrom> 108 struct isa_impl_wrap { 109 // When From != SimplifiedType, we can simplify the type some more by using 110 // the simplify_type template. 111 static bool doit(const From &Val) { 112 return isa_impl_wrap<To, SimpleFrom, 113 typename simplify_type<SimpleFrom>::SimpleType>::doit( 114 simplify_type<const From>::getSimplifiedValue(Val)); 115 } 116 }; 117 118 template<typename To, typename FromTy> 119 struct isa_impl_wrap<To, FromTy, FromTy> { 120 // When From == SimpleType, we are as simple as we are going to get. 121 static bool doit(const FromTy &Val) { 122 return isa_impl_cl<To,FromTy>::doit(Val); 123 } 124 }; 125 126 // isa<X> - Return true if the parameter to the template is an instance of the 127 // template type argument. Used like this: 128 // 129 // if (isa<Type>(myVal)) { ... } 130 // 131 template <class X, class Y> LLVM_NODISCARD inline bool isa(const Y &Val) { 132 return isa_impl_wrap<X, const Y, 133 typename simplify_type<const Y>::SimpleType>::doit(Val); 134 } 135 136 //===----------------------------------------------------------------------===// 137 // cast<x> Support Templates 138 //===----------------------------------------------------------------------===// 139 140 template<class To, class From> struct cast_retty; 141 142 143 // Calculate what type the 'cast' function should return, based on a requested 144 // type of To and a source type of From. 145 template<class To, class From> struct cast_retty_impl { 146 typedef To& ret_type; // Normal case, return Ty& 147 }; 148 template<class To, class From> struct cast_retty_impl<To, const From> { 149 typedef const To &ret_type; // Normal case, return Ty& 150 }; 151 152 template<class To, class From> struct cast_retty_impl<To, From*> { 153 typedef To* ret_type; // Pointer arg case, return Ty* 154 }; 155 156 template<class To, class From> struct cast_retty_impl<To, const From*> { 157 typedef const To* ret_type; // Constant pointer arg case, return const Ty* 158 }; 159 160 template<class To, class From> struct cast_retty_impl<To, const From*const> { 161 typedef const To* ret_type; // Constant pointer arg case, return const Ty* 162 }; 163 164 165 template<class To, class From, class SimpleFrom> 166 struct cast_retty_wrap { 167 // When the simplified type and the from type are not the same, use the type 168 // simplifier to reduce the type, then reuse cast_retty_impl to get the 169 // resultant type. 170 typedef typename cast_retty<To, SimpleFrom>::ret_type ret_type; 171 }; 172 173 template<class To, class FromTy> 174 struct cast_retty_wrap<To, FromTy, FromTy> { 175 // When the simplified type is equal to the from type, use it directly. 176 typedef typename cast_retty_impl<To,FromTy>::ret_type ret_type; 177 }; 178 179 template<class To, class From> 180 struct cast_retty { 181 typedef typename cast_retty_wrap<To, From, 182 typename simplify_type<From>::SimpleType>::ret_type ret_type; 183 }; 184 185 // Ensure the non-simple values are converted using the simplify_type template 186 // that may be specialized by smart pointers... 187 // 188 template<class To, class From, class SimpleFrom> struct cast_convert_val { 189 // This is not a simple type, use the template to simplify it... 190 static typename cast_retty<To, From>::ret_type doit(From &Val) { 191 return cast_convert_val<To, SimpleFrom, 192 typename simplify_type<SimpleFrom>::SimpleType>::doit( 193 simplify_type<From>::getSimplifiedValue(Val)); 194 } 195 }; 196 197 template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { 198 // This _is_ a simple type, just cast it. 199 static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) { 200 typename cast_retty<To, FromTy>::ret_type Res2 201 = (typename cast_retty<To, FromTy>::ret_type)const_cast<FromTy&>(Val); 202 return Res2; 203 } 204 }; 205 206 template <class X> struct is_simple_type { 207 static const bool value = 208 std::is_same<X, typename simplify_type<X>::SimpleType>::value; 209 }; 210 211 // cast<X> - Return the argument parameter cast to the specified type. This 212 // casting operator asserts that the type is correct, so it does not return null 213 // on failure. It does not allow a null argument (use cast_or_null for that). 214 // It is typically used like this: 215 // 216 // cast<Instruction>(myVal)->getParent() 217 // 218 template <class X, class Y> 219 inline typename std::enable_if<!is_simple_type<Y>::value, 220 typename cast_retty<X, const Y>::ret_type>::type 221 cast(const Y &Val) { 222 assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); 223 return cast_convert_val< 224 X, const Y, typename simplify_type<const Y>::SimpleType>::doit(Val); 225 } 226 227 template <class X, class Y> 228 inline typename cast_retty<X, Y>::ret_type cast(Y &Val) { 229 assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); 230 return cast_convert_val<X, Y, 231 typename simplify_type<Y>::SimpleType>::doit(Val); 232 } 233 234 template <class X, class Y> 235 inline typename cast_retty<X, Y *>::ret_type cast(Y *Val) { 236 assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); 237 return cast_convert_val<X, Y*, 238 typename simplify_type<Y*>::SimpleType>::doit(Val); 239 } 240 241 // cast_or_null<X> - Functionally identical to cast, except that a null value is 242 // accepted. 243 // 244 template <class X, class Y> 245 LLVM_NODISCARD inline 246 typename std::enable_if<!is_simple_type<Y>::value, 247 typename cast_retty<X, const Y>::ret_type>::type 248 cast_or_null(const Y &Val) { 249 if (!Val) 250 return nullptr; 251 assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); 252 return cast<X>(Val); 253 } 254 255 template <class X, class Y> 256 LLVM_NODISCARD inline 257 typename std::enable_if<!is_simple_type<Y>::value, 258 typename cast_retty<X, Y>::ret_type>::type 259 cast_or_null(Y &Val) { 260 if (!Val) 261 return nullptr; 262 assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); 263 return cast<X>(Val); 264 } 265 266 template <class X, class Y> 267 LLVM_NODISCARD inline typename cast_retty<X, Y *>::ret_type 268 cast_or_null(Y *Val) { 269 if (!Val) return nullptr; 270 assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); 271 return cast<X>(Val); 272 } 273 274 275 // dyn_cast<X> - Return the argument parameter cast to the specified type. This 276 // casting operator returns null if the argument is of the wrong type, so it can 277 // be used to test for a type as well as cast if successful. This should be 278 // used in the context of an if statement like this: 279 // 280 // if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... } 281 // 282 283 template <class X, class Y> 284 LLVM_NODISCARD inline 285 typename std::enable_if<!is_simple_type<Y>::value, 286 typename cast_retty<X, const Y>::ret_type>::type 287 dyn_cast(const Y &Val) { 288 return isa<X>(Val) ? cast<X>(Val) : nullptr; 289 } 290 291 template <class X, class Y> 292 LLVM_NODISCARD inline typename cast_retty<X, Y>::ret_type dyn_cast(Y &Val) { 293 return isa<X>(Val) ? cast<X>(Val) : nullptr; 294 } 295 296 template <class X, class Y> 297 LLVM_NODISCARD inline typename cast_retty<X, Y *>::ret_type dyn_cast(Y *Val) { 298 return isa<X>(Val) ? cast<X>(Val) : nullptr; 299 } 300 301 // dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null 302 // value is accepted. 303 // 304 template <class X, class Y> 305 LLVM_NODISCARD inline 306 typename std::enable_if<!is_simple_type<Y>::value, 307 typename cast_retty<X, const Y>::ret_type>::type 308 dyn_cast_or_null(const Y &Val) { 309 return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; 310 } 311 312 template <class X, class Y> 313 LLVM_NODISCARD inline 314 typename std::enable_if<!is_simple_type<Y>::value, 315 typename cast_retty<X, Y>::ret_type>::type 316 dyn_cast_or_null(Y &Val) { 317 return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; 318 } 319 320 template <class X, class Y> 321 LLVM_NODISCARD inline typename cast_retty<X, Y *>::ret_type 322 dyn_cast_or_null(Y *Val) { 323 return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; 324 } 325 326 } // End llvm namespace 327 328 #endif 329