LCOV - code coverage report
Current view: top level - include/llvm/Support - Casting.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 43 44 97.7 %
Date: 2017-09-14 15:23:50 Functions: 79 94 84.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 12520094846 :     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 10474445744 :     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          86 :     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   245974665 :     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         163 :     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   556621089 :     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 10160554891 :     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    27069662 :   static bool doit(const From &Val) {
     123             :     return isa_impl_wrap<To, SimpleFrom,
     124             :       typename simplify_type<SimpleFrom>::SimpleType>::doit(
     125 13078667430 :                           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 24003115903 :     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       57876 : template <class X, class Y> LLVM_NODISCARD inline bool isa(const Y &Val) {
     143             :   return isa_impl_wrap<X, const Y,
     144 12949194448 :                        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  1570566462 :                           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  4250109184 :     typename cast_retty<To, FromTy>::ret_type Res2
     220        1516 :      = (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   584555683 :       X, const Y, typename simplify_type<const Y>::SimpleType>::doit(Val);
     244             : }
     245             : 
     246             : template <class X, class Y>
     247       51911 : 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   104476684 :                           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  5340916963 :                           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          85 :       cast_convert_val<X, Y *, typename simplify_type<Y *>::SimpleType>::doit(
     267         170 :           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     5134472 :   if (!Val)
     279             :     return nullptr;
     280             :   assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
     281     4890689 :   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         169 :   if (!Val)
     290             :     return nullptr;
     291             :   assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
     292         164 :   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   426256410 :   if (!Val) return nullptr;
     299             :   assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
     300   401599764 :   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           1 :   if (!Val)
     307             :     return nullptr;
     308           0 :   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       17818 :     dyn_cast(const Y &Val) {
     324  1121855810 :   return isa<X>(Val) ? cast<X>(Val) : nullptr;
     325             : }
     326             : 
     327             : template <class X, class Y>
     328     3108224 : LLVM_NODISCARD inline typename cast_retty<X, Y>::ret_type dyn_cast(Y &Val) {
     329   135944339 :   return isa<X>(Val) ? cast<X>(Val) : nullptr;
     330             : }
     331             : 
     332             : template <class X, class Y>
     333     1720564 : LLVM_NODISCARD inline typename cast_retty<X, Y *>::ret_type dyn_cast(Y *Val) {
     334 12245608291 :   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    10457665 :   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       98010 :   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        1516 : dyn_cast_or_null(Y *Val) {
     359   205788196 :   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          86 :   if (!isa<X>(Val))
     371             :     return nullptr;
     372          84 :   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           4 :   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          89 :   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          89 :   return unique_dyn_cast_or_null<X, Y>(Val);
     395             : }
     396             : 
     397             : } // end namespace llvm
     398             : 
     399             : #endif // LLVM_SUPPORT_CASTING_H

Generated by: LCOV version 1.13