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