LCOV - code coverage report
Current view: top level - /usr/lib/llvm-19/include/llvm/Support - Casting.h (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 86.9 % 61 53
Test Date: 2026-02-27 04:14:43 Functions: 79.5 % 195 155
Legend: Lines:     hit not hit

            Line data    Source code
       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>(),
      10              : // cast_if_present<X>(), and dyn_cast_if_present<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 <optional>
      22              : #include <type_traits>
      23              : 
      24              : namespace llvm {
      25              : 
      26              : //===----------------------------------------------------------------------===//
      27              : // simplify_type
      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              : // TODO: rename this and/or replace it with other cast traits.
      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      8052227 :   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 = typename add_const_past_pointer<NonConstSimpleType>::type;
      44              :   using RetType =
      45              :       typename add_lvalue_reference_if_not_pointer<SimpleType>::type;
      46              : 
      47      7082503 :   static RetType getSimplifiedValue(const From &Val) {
      48      7082503 :     return simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val));
      49              :   }
      50              : };
      51              : 
      52              : // TODO: add this namespace once everyone is switched to using the new
      53              : //       interface.
      54              : // namespace detail {
      55              : 
      56              : //===----------------------------------------------------------------------===//
      57              : // isa_impl
      58              : //===----------------------------------------------------------------------===//
      59              : 
      60              : // The core of the implementation of isa<X> is here; To and From should be
      61              : // the names of classes.  This template can be specialized to customize the
      62              : // implementation of isa<> without rewriting it from scratch.
      63              : template <typename To, typename From, typename Enabler = void> struct isa_impl {
      64      2916087 :   static inline bool doit(const From &Val) { return To::classof(&Val); }
      65              : };
      66              : 
      67              : // Always allow upcasts, and perform no dynamic check for them.
      68              : template <typename To, typename From>
      69              : struct isa_impl<To, From, std::enable_if_t<std::is_base_of_v<To, From>>> {
      70              :   static inline bool doit(const From &) { return true; }
      71              : };
      72              : 
      73              : template <typename To, typename From> struct isa_impl_cl {
      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, const From> {
      80       284157 :   static inline bool doit(const From &Val) {
      81       284157 :     return isa_impl<To, From>::doit(Val);
      82              :   }
      83              : };
      84              : 
      85              : template <typename To, typename From>
      86              : struct isa_impl_cl<To, const std::unique_ptr<From>> {
      87              :   static inline bool doit(const std::unique_ptr<From> &Val) {
      88              :     assert(Val && "isa<> used on a null pointer");
      89              :     return isa_impl_cl<To, From>::doit(*Val);
      90              :   }
      91              : };
      92              : 
      93              : template <typename To, typename From> struct isa_impl_cl<To, 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, 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> struct isa_impl_cl<To, const From *> {
     108      4319798 :   static inline bool doit(const From *Val) {
     109      4319798 :     assert(Val && "isa<> used on a null pointer");
     110      4319798 :     return isa_impl<To, From>::doit(*Val);
     111              :   }
     112              : };
     113              : 
     114              : template <typename To, typename From>
     115              : struct isa_impl_cl<To, const From *const> {
     116              :   static inline bool doit(const From *Val) {
     117              :     assert(Val && "isa<> used on a null pointer");
     118              :     return isa_impl<To, From>::doit(*Val);
     119              :   }
     120              : };
     121              : 
     122              : template <typename To, typename From, typename SimpleFrom>
     123              : struct isa_impl_wrap {
     124              :   // When From != SimplifiedType, we can simplify the type some more by using
     125              :   // the simplify_type template.
     126      4319798 :   static bool doit(const From &Val) {
     127              :     return isa_impl_wrap<To, SimpleFrom,
     128              :                          typename simplify_type<SimpleFrom>::SimpleType>::
     129      4319798 :         doit(simplify_type<const From>::getSimplifiedValue(Val));
     130              :   }
     131              : };
     132              : 
     133              : template <typename To, typename FromTy>
     134              : struct isa_impl_wrap<To, FromTy, FromTy> {
     135              :   // When From == SimpleType, we are as simple as we are going to get.
     136      4603955 :   static bool doit(const FromTy &Val) {
     137      4603955 :     return isa_impl_cl<To, FromTy>::doit(Val);
     138              :   }
     139              : };
     140              : 
     141              : //===----------------------------------------------------------------------===//
     142              : // cast_retty + cast_retty_impl
     143              : //===----------------------------------------------------------------------===//
     144              : 
     145              : template <class To, class From> struct cast_retty;
     146              : 
     147              : // Calculate what type the 'cast' function should return, based on a requested
     148              : // type of To and a source type of From.
     149              : template <class To, class From> struct cast_retty_impl {
     150              :   using ret_type = To &; // Normal case, return Ty&
     151              : };
     152              : template <class To, class From> struct cast_retty_impl<To, const From> {
     153              :   using ret_type = const To &; // Normal case, return Ty&
     154              : };
     155              : 
     156              : template <class To, class From> struct cast_retty_impl<To, From *> {
     157              :   using ret_type = To *; // Pointer arg case, return Ty*
     158              : };
     159              : 
     160              : template <class To, class From> struct cast_retty_impl<To, const From *> {
     161              :   using ret_type = const To *; // Constant pointer arg case, return const Ty*
     162              : };
     163              : 
     164              : template <class To, class From> struct cast_retty_impl<To, const From *const> {
     165              :   using ret_type = const To *; // Constant pointer arg case, return const Ty*
     166              : };
     167              : 
     168              : template <class To, class From>
     169              : struct cast_retty_impl<To, std::unique_ptr<From>> {
     170              : private:
     171              :   using PointerType = typename cast_retty_impl<To, From *>::ret_type;
     172              :   using ResultType = std::remove_pointer_t<PointerType>;
     173              : 
     174              : public:
     175              :   using ret_type = std::unique_ptr<ResultType>;
     176              : };
     177              : 
     178              : template <class To, class From, class SimpleFrom> struct cast_retty_wrap {
     179              :   // When the simplified type and the from type are not the same, use the type
     180              :   // simplifier to reduce the type, then reuse cast_retty_impl to get the
     181              :   // resultant type.
     182              :   using ret_type = typename cast_retty<To, SimpleFrom>::ret_type;
     183              : };
     184              : 
     185              : template <class To, class FromTy> struct cast_retty_wrap<To, FromTy, FromTy> {
     186              :   // When the simplified type is equal to the from type, use it directly.
     187              :   using ret_type = typename cast_retty_impl<To, FromTy>::ret_type;
     188              : };
     189              : 
     190              : template <class To, class From> struct cast_retty {
     191              :   using ret_type = typename cast_retty_wrap<
     192              :       To, From, typename simplify_type<From>::SimpleType>::ret_type;
     193              : };
     194              : 
     195              : //===----------------------------------------------------------------------===//
     196              : // cast_convert_val
     197              : //===----------------------------------------------------------------------===//
     198              : 
     199              : // Ensure the non-simple values are converted using the simplify_type template
     200              : // that may be specialized by smart pointers...
     201              : //
     202              : template <class To, class From, class SimpleFrom> struct cast_convert_val {
     203              :   // This is not a simple type, use the template to simplify it...
     204              :   static typename cast_retty<To, From>::ret_type doit(const From &Val) {
     205              :     return cast_convert_val<To, SimpleFrom,
     206              :                             typename simplify_type<SimpleFrom>::SimpleType>::
     207              :         doit(simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val)));
     208              :   }
     209              : };
     210              : 
     211              : template <class To, class FromTy> struct cast_convert_val<To, FromTy, FromTy> {
     212              :   // If it's a reference, switch to a pointer to do the cast and then deref it.
     213              :   static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) {
     214              :     return *(std::remove_reference_t<typename cast_retty<To, FromTy>::ret_type>
     215              :                  *)&const_cast<FromTy &>(Val);
     216              :   }
     217              : };
     218              : 
     219              : template <class To, class FromTy>
     220              : struct cast_convert_val<To, FromTy *, FromTy *> {
     221              :   // If it's a pointer, we can use c-style casting directly.
     222      1066347 :   static typename cast_retty<To, FromTy *>::ret_type doit(const FromTy *Val) {
     223              :     return (typename cast_retty<To, FromTy *>::ret_type) const_cast<FromTy *>(
     224      1066347 :         Val);
     225              :   }
     226              : };
     227              : 
     228              : //===----------------------------------------------------------------------===//
     229              : // is_simple_type
     230              : //===----------------------------------------------------------------------===//
     231              : 
     232              : template <class X> struct is_simple_type {
     233              :   static const bool value =
     234              :       std::is_same_v<X, typename simplify_type<X>::SimpleType>;
     235              : };
     236              : 
     237              : // } // namespace detail
     238              : 
     239              : //===----------------------------------------------------------------------===//
     240              : // CastIsPossible
     241              : //===----------------------------------------------------------------------===//
     242              : 
     243              : /// This struct provides a way to check if a given cast is possible. It provides
     244              : /// a static function called isPossible that is used to check if a cast can be
     245              : /// performed. It should be overridden like this:
     246              : ///
     247              : /// template<> struct CastIsPossible<foo, bar> {
     248              : ///   static inline bool isPossible(const bar &b) {
     249              : ///     return bar.isFoo();
     250              : ///   }
     251              : /// };
     252              : template <typename To, typename From, typename Enable = void>
     253              : struct CastIsPossible {
     254      4603955 :   static inline bool isPossible(const From &f) {
     255              :     return isa_impl_wrap<
     256              :         To, const From,
     257      4603955 :         typename simplify_type<const From>::SimpleType>::doit(f);
     258              :   }
     259              : };
     260              : 
     261              : // Needed for optional unwrapping. This could be implemented with isa_impl, but
     262              : // we want to implement things in the new method and move old implementations
     263              : // over. In fact, some of the isa_impl templates should be moved over to
     264              : // CastIsPossible.
     265              : template <typename To, typename From>
     266              : struct CastIsPossible<To, std::optional<From>> {
     267              :   static inline bool isPossible(const std::optional<From> &f) {
     268              :     assert(f && "CastIsPossible::isPossible called on a nullopt!");
     269              :     return isa_impl_wrap<
     270              :         To, const From,
     271              :         typename simplify_type<const From>::SimpleType>::doit(*f);
     272              :   }
     273              : };
     274              : 
     275              : /// Upcasting (from derived to base) and casting from a type to itself should
     276              : /// always be possible.
     277              : template <typename To, typename From>
     278              : struct CastIsPossible<To, From, std::enable_if_t<std::is_base_of_v<To, From>>> {
     279              :   static inline bool isPossible(const From &f) { return true; }
     280              : };
     281              : 
     282              : //===----------------------------------------------------------------------===//
     283              : // Cast traits
     284              : //===----------------------------------------------------------------------===//
     285              : 
     286              : /// All of these cast traits are meant to be implementations for useful casts
     287              : /// that users may want to use that are outside the standard behavior. An
     288              : /// example of how to use a special cast called `CastTrait` is:
     289              : ///
     290              : /// template<> struct CastInfo<foo, bar> : public CastTrait<foo, bar> {};
     291              : ///
     292              : /// Essentially, if your use case falls directly into one of the use cases
     293              : /// supported by a given cast trait, simply inherit your special CastInfo
     294              : /// directly from one of these to avoid having to reimplement the boilerplate
     295              : /// `isPossible/castFailed/doCast/doCastIfPossible`. A cast trait can also
     296              : /// provide a subset of those functions.
     297              : 
     298              : /// This cast trait just provides castFailed for the specified `To` type to make
     299              : /// CastInfo specializations more declarative. In order to use this, the target
     300              : /// result type must be `To` and `To` must be constructible from `nullptr`.
     301              : template <typename To> struct NullableValueCastFailed {
     302              :   static To castFailed() { return To(nullptr); }
     303              : };
     304              : 
     305              : /// This cast trait just provides the default implementation of doCastIfPossible
     306              : /// to make CastInfo specializations more declarative. The `Derived` template
     307              : /// parameter *must* be provided for forwarding castFailed and doCast.
     308              : template <typename To, typename From, typename Derived>
     309              : struct DefaultDoCastIfPossible {
     310              :   static To doCastIfPossible(From f) {
     311              :     if (!Derived::isPossible(f))
     312              :       return Derived::castFailed();
     313              :     return Derived::doCast(f);
     314              :   }
     315              : };
     316              : 
     317              : namespace detail {
     318              : /// A helper to derive the type to use with `Self` for cast traits, when the
     319              : /// provided CRTP derived type is allowed to be void.
     320              : template <typename OptionalDerived, typename Default>
     321              : using SelfType = std::conditional_t<std::is_same_v<OptionalDerived, void>,
     322              :                                     Default, OptionalDerived>;
     323              : } // namespace detail
     324              : 
     325              : /// This cast trait provides casting for the specific case of casting to a
     326              : /// value-typed object from a pointer-typed object. Note that `To` must be
     327              : /// nullable/constructible from a pointer to `From` to use this cast.
     328              : template <typename To, typename From, typename Derived = void>
     329              : struct ValueFromPointerCast
     330              :     : public CastIsPossible<To, From *>,
     331              :       public NullableValueCastFailed<To>,
     332              :       public DefaultDoCastIfPossible<
     333              :           To, From *,
     334              :           detail::SelfType<Derived, ValueFromPointerCast<To, From>>> {
     335              :   static inline To doCast(From *f) { return To(f); }
     336              : };
     337              : 
     338              : /// This cast trait provides std::unique_ptr casting. It has the semantics of
     339              : /// moving the contents of the input unique_ptr into the output unique_ptr
     340              : /// during the cast. It's also a good example of how to implement a move-only
     341              : /// cast.
     342              : template <typename To, typename From, typename Derived = void>
     343              : struct UniquePtrCast : public CastIsPossible<To, From *> {
     344              :   using Self = detail::SelfType<Derived, UniquePtrCast<To, From>>;
     345              :   using CastResultType = std::unique_ptr<
     346              :       std::remove_reference_t<typename cast_retty<To, From>::ret_type>>;
     347              : 
     348              :   static inline CastResultType doCast(std::unique_ptr<From> &&f) {
     349              :     return CastResultType((typename CastResultType::element_type *)f.release());
     350              :   }
     351              : 
     352              :   static inline CastResultType castFailed() { return CastResultType(nullptr); }
     353              : 
     354              :   static inline CastResultType doCastIfPossible(std::unique_ptr<From> &f) {
     355              :     if (!Self::isPossible(f.get()))
     356              :       return castFailed();
     357              :     return doCast(std::move(f));
     358              :   }
     359              : };
     360              : 
     361              : /// This cast trait provides std::optional<T> casting. This means that if you
     362              : /// have a value type, you can cast it to another value type and have dyn_cast
     363              : /// return an std::optional<T>.
     364              : template <typename To, typename From, typename Derived = void>
     365              : struct OptionalValueCast
     366              :     : public CastIsPossible<To, From>,
     367              :       public DefaultDoCastIfPossible<
     368              :           std::optional<To>, From,
     369              :           detail::SelfType<Derived, OptionalValueCast<To, From>>> {
     370              :   static inline std::optional<To> castFailed() { return std::optional<To>{}; }
     371              : 
     372              :   static inline std::optional<To> doCast(const From &f) { return To(f); }
     373              : };
     374              : 
     375              : /// Provides a cast trait that strips `const` from types to make it easier to
     376              : /// implement a const-version of a non-const cast. It just removes boilerplate
     377              : /// and reduces the amount of code you as the user need to implement. You can
     378              : /// use it like this:
     379              : ///
     380              : /// template<> struct CastInfo<foo, bar> {
     381              : ///   ...verbose implementation...
     382              : /// };
     383              : ///
     384              : /// template<> struct CastInfo<foo, const bar> : public
     385              : ///        ConstStrippingForwardingCast<foo, const bar, CastInfo<foo, bar>> {};
     386              : ///
     387              : template <typename To, typename From, typename ForwardTo>
     388              : struct ConstStrippingForwardingCast {
     389              :   // Remove the pointer if it exists, then we can get rid of consts/volatiles.
     390              :   using DecayedFrom = std::remove_cv_t<std::remove_pointer_t<From>>;
     391              :   // Now if it's a pointer, add it back. Otherwise, we want a ref.
     392              :   using NonConstFrom =
     393              :       std::conditional_t<std::is_pointer_v<From>, DecayedFrom *, DecayedFrom &>;
     394              : 
     395            0 :   static inline bool isPossible(const From &f) {
     396            0 :     return ForwardTo::isPossible(const_cast<NonConstFrom>(f));
     397              :   }
     398              : 
     399              :   static inline decltype(auto) castFailed() { return ForwardTo::castFailed(); }
     400              : 
     401            0 :   static inline decltype(auto) doCast(const From &f) {
     402            0 :     return ForwardTo::doCast(const_cast<NonConstFrom>(f));
     403              :   }
     404              : 
     405              :   static inline decltype(auto) doCastIfPossible(const From &f) {
     406              :     return ForwardTo::doCastIfPossible(const_cast<NonConstFrom>(f));
     407              :   }
     408              : };
     409              : 
     410              : /// Provides a cast trait that uses a defined pointer to pointer cast as a base
     411              : /// for reference-to-reference casts. Note that it does not provide castFailed
     412              : /// and doCastIfPossible because a pointer-to-pointer cast would likely just
     413              : /// return `nullptr` which could cause nullptr dereference. You can use it like
     414              : /// this:
     415              : ///
     416              : ///   template <> struct CastInfo<foo, bar *> { ... verbose implementation... };
     417              : ///
     418              : ///   template <>
     419              : ///   struct CastInfo<foo, bar>
     420              : ///       : public ForwardToPointerCast<foo, bar, CastInfo<foo, bar *>> {};
     421              : ///
     422              : template <typename To, typename From, typename ForwardTo>
     423              : struct ForwardToPointerCast {
     424              :   static inline bool isPossible(const From &f) {
     425              :     return ForwardTo::isPossible(&f);
     426              :   }
     427              : 
     428              :   static inline decltype(auto) doCast(const From &f) {
     429              :     return *ForwardTo::doCast(&f);
     430              :   }
     431              : };
     432              : 
     433              : //===----------------------------------------------------------------------===//
     434              : // CastInfo
     435              : //===----------------------------------------------------------------------===//
     436              : 
     437              : /// This struct provides a method for customizing the way a cast is performed.
     438              : /// It inherits from CastIsPossible, to support the case of declaring many
     439              : /// CastIsPossible specializations without having to specialize the full
     440              : /// CastInfo.
     441              : ///
     442              : /// In order to specialize different behaviors, specify different functions in
     443              : /// your CastInfo specialization.
     444              : /// For isa<> customization, provide:
     445              : ///
     446              : ///   `static bool isPossible(const From &f)`
     447              : ///
     448              : /// For cast<> customization, provide:
     449              : ///
     450              : ///  `static To doCast(const From &f)`
     451              : ///
     452              : /// For dyn_cast<> and the *_if_present<> variants' customization, provide:
     453              : ///
     454              : ///  `static To castFailed()` and `static To doCastIfPossible(const From &f)`
     455              : ///
     456              : /// Your specialization might look something like this:
     457              : ///
     458              : ///  template<> struct CastInfo<foo, bar> : public CastIsPossible<foo, bar> {
     459              : ///    static inline foo doCast(const bar &b) {
     460              : ///      return foo(const_cast<bar &>(b));
     461              : ///    }
     462              : ///    static inline foo castFailed() { return foo(); }
     463              : ///    static inline foo doCastIfPossible(const bar &b) {
     464              : ///      if (!CastInfo<foo, bar>::isPossible(b))
     465              : ///        return castFailed();
     466              : ///      return doCast(b);
     467              : ///    }
     468              : ///  };
     469              : 
     470              : // The default implementations of CastInfo don't use cast traits for now because
     471              : // we need to specify types all over the place due to the current expected
     472              : // casting behavior and the way cast_retty works. New use cases can and should
     473              : // take advantage of the cast traits whenever possible!
     474              : 
     475              : template <typename To, typename From, typename Enable = void>
     476              : struct CastInfo : public CastIsPossible<To, From> {
     477              :   using Self = CastInfo<To, From, Enable>;
     478              : 
     479              :   using CastReturnType = typename cast_retty<To, From>::ret_type;
     480              : 
     481      1066347 :   static inline CastReturnType doCast(const From &f) {
     482              :     return cast_convert_val<
     483              :         To, From,
     484      1066347 :         typename simplify_type<From>::SimpleType>::doit(const_cast<From &>(f));
     485              :   }
     486              : 
     487              :   // This assumes that you can construct the cast return type from `nullptr`.
     488              :   // This is largely to support legacy use cases - if you don't want this
     489              :   // behavior you should specialize CastInfo for your use case.
     490       959274 :   static inline CastReturnType castFailed() { return CastReturnType(nullptr); }
     491              : 
     492      1557093 :   static inline CastReturnType doCastIfPossible(const From &f) {
     493      1557093 :     if (!Self::isPossible(f))
     494       959274 :       return castFailed();
     495       597819 :     return doCast(f);
     496              :   }
     497              : };
     498              : 
     499              : /// This struct provides an overload for CastInfo where From has simplify_type
     500              : /// defined. This simply forwards to the appropriate CastInfo with the
     501              : /// simplified type/value, so you don't have to implement both.
     502              : template <typename To, typename From>
     503              : struct CastInfo<To, From, std::enable_if_t<!is_simple_type<From>::value>> {
     504              :   using Self = CastInfo<To, From>;
     505              :   using SimpleFrom = typename simplify_type<From>::SimpleType;
     506              :   using SimplifiedSelf = CastInfo<To, SimpleFrom>;
     507              : 
     508      2762705 :   static inline bool isPossible(From &f) {
     509      5525410 :     return SimplifiedSelf::isPossible(
     510      2762705 :         simplify_type<From>::getSimplifiedValue(f));
     511              :   }
     512              : 
     513              :   static inline decltype(auto) doCast(From &f) {
     514              :     return SimplifiedSelf::doCast(simplify_type<From>::getSimplifiedValue(f));
     515              :   }
     516              : 
     517              :   static inline decltype(auto) castFailed() {
     518              :     return SimplifiedSelf::castFailed();
     519              :   }
     520              : 
     521       587369 :   static inline decltype(auto) doCastIfPossible(From &f) {
     522      1174738 :     return SimplifiedSelf::doCastIfPossible(
     523       587369 :         simplify_type<From>::getSimplifiedValue(f));
     524              :   }
     525              : };
     526              : 
     527              : //===----------------------------------------------------------------------===//
     528              : // Pre-specialized CastInfo
     529              : //===----------------------------------------------------------------------===//
     530              : 
     531              : /// Provide a CastInfo specialized for std::unique_ptr.
     532              : template <typename To, typename From>
     533              : struct CastInfo<To, std::unique_ptr<From>> : public UniquePtrCast<To, From> {};
     534              : 
     535              : /// Provide a CastInfo specialized for std::optional<From>. It's assumed that if
     536              : /// the input is std::optional<From> that the output can be std::optional<To>.
     537              : /// If that's not the case, specialize CastInfo for your use case.
     538              : template <typename To, typename From>
     539              : struct CastInfo<To, std::optional<From>> : public OptionalValueCast<To, From> {
     540              : };
     541              : 
     542              : /// isa<X> - Return true if the parameter to the template is an instance of one
     543              : /// of the template type arguments.  Used like this:
     544              : ///
     545              : ///  if (isa<Type>(myVal)) { ... }
     546              : ///  if (isa<Type0, Type1, Type2>(myVal)) { ... }
     547              : template <typename To, typename From>
     548      3046862 : [[nodiscard]] inline bool isa(const From &Val) {
     549      3046862 :   return CastInfo<To, const From>::isPossible(Val);
     550              : }
     551              : 
     552              : template <typename First, typename Second, typename... Rest, typename From>
     553              : [[nodiscard]] inline bool isa(const From &Val) {
     554              :   return isa<First>(Val) || isa<Second, Rest...>(Val);
     555              : }
     556              : 
     557              : /// cast<X> - Return the argument parameter cast to the specified type.  This
     558              : /// casting operator asserts that the type is correct, so it does not return
     559              : /// null on failure.  It does not allow a null argument (use cast_if_present for
     560              : /// that). It is typically used like this:
     561              : ///
     562              : ///  cast<Instruction>(myVal)->getParent()
     563              : 
     564              : template <typename To, typename From>
     565            0 : [[nodiscard]] inline decltype(auto) cast(const From &Val) {
     566            0 :   assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
     567            0 :   return CastInfo<To, const From>::doCast(Val);
     568              : }
     569              : 
     570              : template <typename To, typename From>
     571              : [[nodiscard]] inline decltype(auto) cast(From &Val) {
     572              :   assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
     573              :   return CastInfo<To, From>::doCast(Val);
     574              : }
     575              : 
     576              : template <typename To, typename From>
     577       468528 : [[nodiscard]] inline decltype(auto) cast(From *Val) {
     578       468528 :   assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
     579       468528 :   return CastInfo<To, From *>::doCast(Val);
     580              : }
     581              : 
     582              : template <typename To, typename From>
     583              : [[nodiscard]] inline decltype(auto) cast(std::unique_ptr<From> &&Val) {
     584              :   assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
     585              :   return CastInfo<To, std::unique_ptr<From>>::doCast(std::move(Val));
     586              : }
     587              : 
     588              : //===----------------------------------------------------------------------===//
     589              : // ValueIsPresent
     590              : //===----------------------------------------------------------------------===//
     591              : 
     592              : template <typename T>
     593              : constexpr bool IsNullable =
     594              :     std::is_pointer_v<T> || std::is_constructible_v<T, std::nullptr_t>;
     595              : 
     596              : /// ValueIsPresent provides a way to check if a value is, well, present. For
     597              : /// pointers, this is the equivalent of checking against nullptr, for Optionals
     598              : /// this is the equivalent of checking hasValue(). It also provides a method for
     599              : /// unwrapping a value (think calling .value() on an optional).
     600              : 
     601              : // Generic values can't *not* be present.
     602              : template <typename T, typename Enable = void> struct ValueIsPresent {
     603              :   using UnwrappedType = T;
     604              :   static inline bool isPresent(const T &t) { return true; }
     605              :   static inline decltype(auto) unwrapValue(T &t) { return t; }
     606              : };
     607              : 
     608              : // Optional provides its own way to check if something is present.
     609              : template <typename T> struct ValueIsPresent<std::optional<T>> {
     610              :   using UnwrappedType = T;
     611              :   static inline bool isPresent(const std::optional<T> &t) {
     612              :     return t.has_value();
     613              :   }
     614              :   static inline decltype(auto) unwrapValue(std::optional<T> &t) { return *t; }
     615              : };
     616              : 
     617              : // If something is "nullable" then we just compare it to nullptr to see if it
     618              : // exists.
     619              : template <typename T>
     620              : struct ValueIsPresent<T, std::enable_if_t<IsNullable<T>>> {
     621              :   using UnwrappedType = T;
     622      1557093 :   static inline bool isPresent(const T &t) { return t != T(nullptr); }
     623        60997 :   static inline decltype(auto) unwrapValue(T &t) { return t; }
     624              : };
     625              : 
     626              : namespace detail {
     627              : // Convenience function we can use to check if a value is present. Because of
     628              : // simplify_type, we have to call it on the simplified type for now.
     629      1557093 : template <typename T> inline bool isPresent(const T &t) {
     630      1557093 :   return ValueIsPresent<typename simplify_type<T>::SimpleType>::isPresent(
     631      2526817 :       simplify_type<T>::getSimplifiedValue(const_cast<T &>(t)));
     632              : }
     633              : 
     634              : // Convenience function we can use to unwrap a value.
     635        60997 : template <typename T> inline decltype(auto) unwrapValue(T &t) {
     636        60997 :   return ValueIsPresent<T>::unwrapValue(t);
     637              : }
     638              : } // namespace detail
     639              : 
     640              : /// dyn_cast<X> - Return the argument parameter cast to the specified type. This
     641              : /// casting operator returns null if the argument is of the wrong type, so it
     642              : /// can be used to test for a type as well as cast if successful. The value
     643              : /// passed in must be present, if not, use dyn_cast_if_present. This should be
     644              : /// used in the context of an if statement like this:
     645              : ///
     646              : ///  if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... }
     647              : 
     648              : template <typename To, typename From>
     649              : [[nodiscard]] inline decltype(auto) dyn_cast(const From &Val) {
     650              :   assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
     651              :   return CastInfo<To, const From>::doCastIfPossible(Val);
     652              : }
     653              : 
     654              : template <typename To, typename From>
     655       587369 : [[nodiscard]] inline decltype(auto) dyn_cast(From &Val) {
     656       587369 :   assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
     657       587369 :   return CastInfo<To, From>::doCastIfPossible(Val);
     658              : }
     659              : 
     660              : template <typename To, typename From>
     661       908727 : [[nodiscard]] inline decltype(auto) dyn_cast(From *Val) {
     662       908727 :   assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
     663       908727 :   return CastInfo<To, From *>::doCastIfPossible(Val);
     664              : }
     665              : 
     666              : template <typename To, typename From>
     667              : [[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &Val) {
     668              :   assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
     669              :   return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible(Val);
     670              : }
     671              : 
     672              : /// isa_and_present<X> - Functionally identical to isa, except that a null value
     673              : /// is accepted.
     674              : template <typename... X, class Y>
     675              : [[nodiscard]] inline bool isa_and_present(const Y &Val) {
     676              :   if (!detail::isPresent(Val))
     677              :     return false;
     678              :   return isa<X...>(Val);
     679              : }
     680              : 
     681              : template <typename... X, class Y>
     682              : [[nodiscard]] inline bool isa_and_nonnull(const Y &Val) {
     683              :   return isa_and_present<X...>(Val);
     684              : }
     685              : 
     686              : /// cast_if_present<X> - Functionally identical to cast, except that a null
     687              : /// value is accepted.
     688              : template <class X, class Y>
     689              : [[nodiscard]] inline auto cast_if_present(const Y &Val) {
     690              :   if (!detail::isPresent(Val))
     691              :     return CastInfo<X, const Y>::castFailed();
     692              :   assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!");
     693              :   return cast<X>(detail::unwrapValue(Val));
     694              : }
     695              : 
     696              : template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y &Val) {
     697              :   if (!detail::isPresent(Val))
     698              :     return CastInfo<X, Y>::castFailed();
     699              :   assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!");
     700              :   return cast<X>(detail::unwrapValue(Val));
     701              : }
     702              : 
     703              : template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y *Val) {
     704              :   if (!detail::isPresent(Val))
     705              :     return CastInfo<X, Y *>::castFailed();
     706              :   assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!");
     707              :   return cast<X>(detail::unwrapValue(Val));
     708              : }
     709              : 
     710              : template <class X, class Y>
     711              : [[nodiscard]] inline auto cast_if_present(std::unique_ptr<Y> &&Val) {
     712              :   if (!detail::isPresent(Val))
     713              :     return UniquePtrCast<X, Y>::castFailed();
     714              :   return UniquePtrCast<X, Y>::doCast(std::move(Val));
     715              : }
     716              : 
     717              : // Provide a forwarding from cast_or_null to cast_if_present for current
     718              : // users. This is deprecated and will be removed in a future patch, use
     719              : // cast_if_present instead.
     720              : template <class X, class Y> auto cast_or_null(const Y &Val) {
     721              :   return cast_if_present<X>(Val);
     722              : }
     723              : 
     724              : template <class X, class Y> auto cast_or_null(Y &Val) {
     725              :   return cast_if_present<X>(Val);
     726              : }
     727              : 
     728              : template <class X, class Y> auto cast_or_null(Y *Val) {
     729              :   return cast_if_present<X>(Val);
     730              : }
     731              : 
     732              : template <class X, class Y> auto cast_or_null(std::unique_ptr<Y> &&Val) {
     733              :   return cast_if_present<X>(std::move(Val));
     734              : }
     735              : 
     736              : /// dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a
     737              : /// null (or none in the case of optionals) value is accepted.
     738              : template <class X, class Y> auto dyn_cast_if_present(const Y &Val) {
     739              :   if (!detail::isPresent(Val))
     740              :     return CastInfo<X, const Y>::castFailed();
     741              :   return CastInfo<X, const Y>::doCastIfPossible(detail::unwrapValue(Val));
     742              : }
     743              : 
     744              : template <class X, class Y> auto dyn_cast_if_present(Y &Val) {
     745              :   if (!detail::isPresent(Val))
     746              :     return CastInfo<X, Y>::castFailed();
     747              :   return CastInfo<X, Y>::doCastIfPossible(detail::unwrapValue(Val));
     748              : }
     749              : 
     750        60997 : template <class X, class Y> auto dyn_cast_if_present(Y *Val) {
     751        60997 :   if (!detail::isPresent(Val))
     752            0 :     return CastInfo<X, Y *>::castFailed();
     753        60997 :   return CastInfo<X, Y *>::doCastIfPossible(detail::unwrapValue(Val));
     754              : }
     755              : 
     756              : // Forwards to dyn_cast_if_present to avoid breaking current users. This is
     757              : // deprecated and will be removed in a future patch, use
     758              : // cast_if_present instead.
     759              : template <class X, class Y> auto dyn_cast_or_null(const Y &Val) {
     760              :   return dyn_cast_if_present<X>(Val);
     761              : }
     762              : 
     763              : template <class X, class Y> auto dyn_cast_or_null(Y &Val) {
     764              :   return dyn_cast_if_present<X>(Val);
     765              : }
     766              : 
     767        60997 : template <class X, class Y> auto dyn_cast_or_null(Y *Val) {
     768        60997 :   return dyn_cast_if_present<X>(Val);
     769              : }
     770              : 
     771              : /// unique_dyn_cast<X> - Given a unique_ptr<Y>, try to return a unique_ptr<X>,
     772              : /// taking ownership of the input pointer iff isa<X>(Val) is true.  If the
     773              : /// cast is successful, From refers to nullptr on exit and the casted value
     774              : /// is returned.  If the cast is unsuccessful, the function returns nullptr
     775              : /// and From is unchanged.
     776              : template <class X, class Y>
     777              : [[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType
     778              : unique_dyn_cast(std::unique_ptr<Y> &Val) {
     779              :   if (!isa<X>(Val))
     780              :     return nullptr;
     781              :   return cast<X>(std::move(Val));
     782              : }
     783              : 
     784              : template <class X, class Y>
     785              : [[nodiscard]] inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val) {
     786              :   return unique_dyn_cast<X, Y>(Val);
     787              : }
     788              : 
     789              : // unique_dyn_cast_or_null<X> - Functionally identical to unique_dyn_cast,
     790              : // except that a null value is accepted.
     791              : template <class X, class Y>
     792              : [[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType
     793              : unique_dyn_cast_or_null(std::unique_ptr<Y> &Val) {
     794              :   if (!Val)
     795              :     return nullptr;
     796              :   return unique_dyn_cast<X, Y>(Val);
     797              : }
     798              : 
     799              : template <class X, class Y>
     800              : [[nodiscard]] inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val) {
     801              :   return unique_dyn_cast_or_null<X, Y>(Val);
     802              : }
     803              : 
     804              : //===----------------------------------------------------------------------===//
     805              : // Isa Predicates
     806              : //===----------------------------------------------------------------------===//
     807              : 
     808              : /// These are wrappers over isa* function that allow them to be used in generic
     809              : /// algorithms such as `llvm:all_of`, `llvm::none_of`, etc. This is accomplished
     810              : /// by exposing the isa* functions through function objects with a generic
     811              : /// function call operator.
     812              : 
     813              : namespace detail {
     814              : template <typename... Types> struct IsaCheckPredicate {
     815              :   template <typename T> [[nodiscard]] bool operator()(const T &Val) const {
     816              :     return isa<Types...>(Val);
     817              :   }
     818              : };
     819              : 
     820              : template <typename... Types> struct IsaAndPresentCheckPredicate {
     821              :   template <typename T> [[nodiscard]] bool operator()(const T &Val) const {
     822              :     return isa_and_present<Types...>(Val);
     823              :   }
     824              : };
     825              : } // namespace detail
     826              : 
     827              : /// Function object wrapper for the `llvm::isa` type check. The function call
     828              : /// operator returns true when the value can be cast to any type in `Types`.
     829              : /// Example:
     830              : /// ```
     831              : /// SmallVector<Type> myTypes = ...;
     832              : /// if (llvm::all_of(myTypes, llvm::IsaPred<VectorType>))
     833              : ///   ...
     834              : /// ```
     835              : template <typename... Types>
     836              : inline constexpr detail::IsaCheckPredicate<Types...> IsaPred{};
     837              : 
     838              : /// Function object wrapper for the `llvm::isa_and_present` type check. The
     839              : /// function call operator returns true when the value can be cast to any type
     840              : /// in `Types`, or if the value is not present (e.g., nullptr). Example:
     841              : /// ```
     842              : /// SmallVector<Type> myTypes = ...;
     843              : /// if (llvm::all_of(myTypes, llvm::IsaAndPresentPred<VectorType>))
     844              : ///   ...
     845              : /// ```
     846              : template <typename... Types>
     847              : inline constexpr detail::IsaAndPresentCheckPredicate<Types...>
     848              :     IsaAndPresentPred{};
     849              : 
     850              : } // end namespace llvm
     851              : 
     852              : #endif // LLVM_SUPPORT_CASTING_H
        

Generated by: LCOV version 2.0-1