LCOV - code coverage report
Current view: top level - /usr/lib/llvm-19/include/llvm/Support - Casting.h (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 0.0 % 61 0
Test Date: 2026-07-03 19:57:34 Functions: 0.0 % 195 0
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 0.0 % 24 0

             Branch data     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                 :           0 :   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                 :           0 :   static RetType getSimplifiedValue(const From &Val) {
      48                 :           0 :     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                 :           0 :   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                 :           0 :   static inline bool doit(const From &Val) {
      81                 :           0 :     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                 :           0 :   static inline bool doit(const From *Val) {
     109         [ #  # ]:           0 :     assert(Val && "isa<> used on a null pointer");
     110                 :           0 :     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                 :           0 :   static bool doit(const From &Val) {
     127                 :             :     return isa_impl_wrap<To, SimpleFrom,
     128                 :             :                          typename simplify_type<SimpleFrom>::SimpleType>::
     129   [ #  #  #  # ]:           0 :         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                 :           0 :   static bool doit(const FromTy &Val) {
     137                 :           0 :     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                 :           0 :   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                 :           0 :         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                 :           0 :   static inline bool isPossible(const From &f) {
     255                 :             :     return isa_impl_wrap<
     256                 :             :         To, const From,
     257                 :           0 :         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                 :           0 :   static inline CastReturnType doCast(const From &f) {
     482                 :             :     return cast_convert_val<
     483                 :             :         To, From,
     484                 :           0 :         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                 :           0 :   static inline CastReturnType castFailed() { return CastReturnType(nullptr); }
     491                 :             : 
     492                 :           0 :   static inline CastReturnType doCastIfPossible(const From &f) {
     493         [ #  # ]:           0 :     if (!Self::isPossible(f))
     494                 :           0 :       return castFailed();
     495                 :           0 :     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                 :           0 :   static inline bool isPossible(From &f) {
     509                 :           0 :     return SimplifiedSelf::isPossible(
     510   [ #  #  #  # ]:           0 :         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                 :           0 :   static inline decltype(auto) doCastIfPossible(From &f) {
     522                 :           0 :     return SimplifiedSelf::doCastIfPossible(
     523         [ #  # ]:           0 :         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                 :           0 : [[nodiscard]] inline bool isa(const From &Val) {
     549                 :           0 :   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                 :           0 : [[nodiscard]] inline decltype(auto) cast(From *Val) {
     578         [ #  # ]:           0 :   assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
     579                 :           0 :   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                 :           0 :   static inline bool isPresent(const T &t) { return t != T(nullptr); }
     623                 :           0 :   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                 :           0 : template <typename T> inline bool isPresent(const T &t) {
     630                 :           0 :   return ValueIsPresent<typename simplify_type<T>::SimpleType>::isPresent(
     631                 :           0 :       simplify_type<T>::getSimplifiedValue(const_cast<T &>(t)));
     632                 :             : }
     633                 :             : 
     634                 :             : // Convenience function we can use to unwrap a value.
     635                 :           0 : template <typename T> inline decltype(auto) unwrapValue(T &t) {
     636                 :           0 :   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                 :           0 : [[nodiscard]] inline decltype(auto) dyn_cast(From &Val) {
     656         [ #  # ]:           0 :   assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
     657                 :           0 :   return CastInfo<To, From>::doCastIfPossible(Val);
     658                 :             : }
     659                 :             : 
     660                 :             : template <typename To, typename From>
     661                 :           0 : [[nodiscard]] inline decltype(auto) dyn_cast(From *Val) {
     662         [ #  # ]:           0 :   assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
     663                 :           0 :   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                 :           0 : template <class X, class Y> auto dyn_cast_if_present(Y *Val) {
     751         [ #  # ]:           0 :   if (!detail::isPresent(Val))
     752                 :           0 :     return CastInfo<X, Y *>::castFailed();
     753                 :           0 :   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                 :           0 : template <class X, class Y> auto dyn_cast_or_null(Y *Val) {
     768                 :           0 :   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