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... 36 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> 132 LLVM_ATTRIBUTE_UNUSED_RESULT inline bool isa(const Y &Val) { 133 return isa_impl_wrap<X, const Y, 134 typename simplify_type<const Y>::SimpleType>::doit(Val); 135 } 136 137 //===----------------------------------------------------------------------===// 138 // cast<x> Support Templates 139 //===----------------------------------------------------------------------===// 140 141 template<class To, class From> struct cast_retty; 142 143 144 // Calculate what type the 'cast' function should return, based on a requested 145 // type of To and a source type of From. 146 template<class To, class From> struct cast_retty_impl { 147 typedef To& ret_type; // Normal case, return Ty& 148 }; 149 template<class To, class From> struct cast_retty_impl<To, const From> { 150 typedef const To &ret_type; // Normal case, return Ty& 151 }; 152 153 template<class To, class From> struct cast_retty_impl<To, From*> { 154 typedef To* ret_type; // Pointer arg case, return Ty* 155 }; 156 157 template<class To, class From> struct cast_retty_impl<To, const From*> { 158 typedef const To* ret_type; // Constant pointer arg case, return const Ty* 159 }; 160 161 template<class To, class From> struct cast_retty_impl<To, const From*const> { 162 typedef const To* ret_type; // Constant pointer arg case, return const Ty* 163 }; 164 165 166 template<class To, class From, class SimpleFrom> 167 struct cast_retty_wrap { 168 // When the simplified type and the from type are not the same, use the type 169 // simplifier to reduce the type, then reuse cast_retty_impl to get the 170 // resultant type. 171 typedef typename cast_retty<To, SimpleFrom>::ret_type ret_type; 172 }; 173 174 template<class To, class FromTy> 175 struct cast_retty_wrap<To, FromTy, FromTy> { 176 // When the simplified type is equal to the from type, use it directly. 177 typedef typename cast_retty_impl<To,FromTy>::ret_type ret_type; 178 }; 179 180 template<class To, class From> 181 struct cast_retty { 182 typedef typename cast_retty_wrap<To, From, 183 typename simplify_type<From>::SimpleType>::ret_type ret_type; 184 }; 185 186 // Ensure the non-simple values are converted using the simplify_type template 187 // that may be specialized by smart pointers... 188 // 189 template<class To, class From, class SimpleFrom> struct cast_convert_val { 190 // This is not a simple type, use the template to simplify it... 191 static typename cast_retty<To, From>::ret_type doit(From &Val) { 192 return cast_convert_val<To, SimpleFrom, 193 typename simplify_type<SimpleFrom>::SimpleType>::doit( 194 simplify_type<From>::getSimplifiedValue(Val)); 195 } 196 }; 197 198 template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { 199 // This _is_ a simple type, just cast it. 200 static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) { 201 typename cast_retty<To, FromTy>::ret_type Res2 202 = (typename cast_retty<To, FromTy>::ret_type)const_cast<FromTy&>(Val); 203 return Res2; 204 } 205 }; 206 207 template <class X> struct is_simple_type { 208 static const bool value = 209 std::is_same<X, typename simplify_type<X>::SimpleType>::value; 210 }; 211 212 // cast<X> - Return the argument parameter cast to the specified type. This 213 // casting operator asserts that the type is correct, so it does not return null 214 // on failure. It does not allow a null argument (use cast_or_null for that). 215 // It is typically used like this: 216 // 217 // cast<Instruction>(myVal)->getParent() 218 // 219 template <class X, class Y> 220 inline typename std::enable_if<!is_simple_type<Y>::value, 221 typename cast_retty<X, const Y>::ret_type>::type 222 cast(const Y &Val) { 223 assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); 224 return cast_convert_val< 225 X, const Y, typename simplify_type<const Y>::SimpleType>::doit(Val); 226 } 227 228 template <class X, class Y> 229 inline typename cast_retty<X, Y>::ret_type cast(Y &Val) { 230 assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); 231 return cast_convert_val<X, Y, 232 typename simplify_type<Y>::SimpleType>::doit(Val); 233 } 234 235 template <class X, class Y> 236 inline typename cast_retty<X, Y *>::ret_type cast(Y *Val) { 237 assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); 238 return cast_convert_val<X, Y*, 239 typename simplify_type<Y*>::SimpleType>::doit(Val); 240 } 241 242 // cast_or_null<X> - Functionally identical to cast, except that a null value is 243 // accepted. 244 // 245 template <class X, class Y> 246 LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< 247 !is_simple_type<Y>::value, 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_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< 257 !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type 258 cast_or_null(Y &Val) { 259 if (!Val) 260 return nullptr; 261 assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); 262 return cast<X>(Val); 263 } 264 265 template <class X, class Y> 266 LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type 267 cast_or_null(Y *Val) { 268 if (!Val) return nullptr; 269 assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); 270 return cast<X>(Val); 271 } 272 273 274 // dyn_cast<X> - Return the argument parameter cast to the specified type. This 275 // casting operator returns null if the argument is of the wrong type, so it can 276 // be used to test for a type as well as cast if successful. This should be 277 // used in the context of an if statement like this: 278 // 279 // if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... } 280 // 281 282 template <class X, class Y> 283 LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< 284 !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type 285 dyn_cast(const Y &Val) { 286 return isa<X>(Val) ? cast<X>(Val) : nullptr; 287 } 288 289 template <class X, class Y> 290 LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y>::ret_type 291 dyn_cast(Y &Val) { 292 return isa<X>(Val) ? cast<X>(Val) : nullptr; 293 } 294 295 template <class X, class Y> 296 LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type 297 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_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< 306 !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type 307 dyn_cast_or_null(const Y &Val) { 308 return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; 309 } 310 311 template <class X, class Y> 312 LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< 313 !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type 314 dyn_cast_or_null(Y &Val) { 315 return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; 316 } 317 318 template <class X, class Y> 319 LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type 320 dyn_cast_or_null(Y *Val) { 321 return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; 322 } 323 324 } // End llvm namespace 325 326 #endif 327