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   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   static RetType getSimplifiedValue(const From &Val) {
48     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   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<To, From>::value>> {
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   static inline bool doit(const From &Val) {
81     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   static inline bool doit(const From *Val) {
109     assert(Val && "isa<> used on a null pointer");
110     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   static bool doit(const From &Val) {
127     return isa_impl_wrap<To, SimpleFrom,
128                          typename simplify_type<SimpleFrom>::SimpleType>::
129         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   static bool doit(const FromTy &Val) {
137     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   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         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<X, typename simplify_type<X>::SimpleType>::value;
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   static inline bool isPossible(const From &f) {
255     return isa_impl_wrap<
256         To, const From,
257         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,
279                       std::enable_if_t<std::is_base_of<To, From>::value>> {
280   static inline bool isPossible(const From &f) { return true; }
281 };
282 
283 //===----------------------------------------------------------------------===//
284 // Cast traits
285 //===----------------------------------------------------------------------===//
286 
287 /// All of these cast traits are meant to be implementations for useful casts
288 /// that users may want to use that are outside the standard behavior. An
289 /// example of how to use a special cast called `CastTrait` is:
290 ///
291 /// template<> struct CastInfo<foo, bar> : public CastTrait<foo, bar> {};
292 ///
293 /// Essentially, if your use case falls directly into one of the use cases
294 /// supported by a given cast trait, simply inherit your special CastInfo
295 /// directly from one of these to avoid having to reimplement the boilerplate
296 /// `isPossible/castFailed/doCast/doCastIfPossible`. A cast trait can also
297 /// provide a subset of those functions.
298 
299 /// This cast trait just provides castFailed for the specified `To` type to make
300 /// CastInfo specializations more declarative. In order to use this, the target
301 /// result type must be `To` and `To` must be constructible from `nullptr`.
302 template <typename To> struct NullableValueCastFailed {
303   static To castFailed() { return To(nullptr); }
304 };
305 
306 /// This cast trait just provides the default implementation of doCastIfPossible
307 /// to make CastInfo specializations more declarative. The `Derived` template
308 /// parameter *must* be provided for forwarding castFailed and doCast.
309 template <typename To, typename From, typename Derived>
310 struct DefaultDoCastIfPossible {
311   static To doCastIfPossible(From f) {
312     if (!Derived::isPossible(f))
313       return Derived::castFailed();
314     return Derived::doCast(f);
315   }
316 };
317 
318 namespace detail {
319 /// A helper to derive the type to use with `Self` for cast traits, when the
320 /// provided CRTP derived type is allowed to be void.
321 template <typename OptionalDerived, typename Default>
322 using SelfType = std::conditional_t<std::is_same<OptionalDerived, void>::value,
323                                     Default, OptionalDerived>;
324 } // namespace detail
325 
326 /// This cast trait provides casting for the specific case of casting to a
327 /// value-typed object from a pointer-typed object. Note that `To` must be
328 /// nullable/constructible from a pointer to `From` to use this cast.
329 template <typename To, typename From, typename Derived = void>
330 struct ValueFromPointerCast
331     : public CastIsPossible<To, From *>,
332       public NullableValueCastFailed<To>,
333       public DefaultDoCastIfPossible<
334           To, From *,
335           detail::SelfType<Derived, ValueFromPointerCast<To, From>>> {
336   static inline To doCast(From *f) { return To(f); }
337 };
338 
339 /// This cast trait provides std::unique_ptr casting. It has the semantics of
340 /// moving the contents of the input unique_ptr into the output unique_ptr
341 /// during the cast. It's also a good example of how to implement a move-only
342 /// cast.
343 template <typename To, typename From, typename Derived = void>
344 struct UniquePtrCast : public CastIsPossible<To, From *> {
345   using Self = detail::SelfType<Derived, UniquePtrCast<To, From>>;
346   using CastResultType = std::unique_ptr<
347       std::remove_reference_t<typename cast_retty<To, From>::ret_type>>;
348 
349   static inline CastResultType doCast(std::unique_ptr<From> &&f) {
350     return CastResultType((typename CastResultType::element_type *)f.release());
351   }
352 
353   static inline CastResultType castFailed() { return CastResultType(nullptr); }
354 
355   static inline CastResultType doCastIfPossible(std::unique_ptr<From> &&f) {
356     if (!Self::isPossible(f))
357       return castFailed();
358     return doCast(f);
359   }
360 };
361 
362 /// This cast trait provides std::optional<T> casting. This means that if you
363 /// have a value type, you can cast it to another value type and have dyn_cast
364 /// return an std::optional<T>.
365 template <typename To, typename From, typename Derived = void>
366 struct OptionalValueCast
367     : public CastIsPossible<To, From>,
368       public DefaultDoCastIfPossible<
369           std::optional<To>, From,
370           detail::SelfType<Derived, OptionalValueCast<To, From>>> {
371   static inline std::optional<To> castFailed() { return std::optional<To>{}; }
372 
373   static inline std::optional<To> doCast(const From &f) { return To(f); }
374 };
375 
376 /// Provides a cast trait that strips `const` from types to make it easier to
377 /// implement a const-version of a non-const cast. It just removes boilerplate
378 /// and reduces the amount of code you as the user need to implement. You can
379 /// use it like this:
380 ///
381 /// template<> struct CastInfo<foo, bar> {
382 ///   ...verbose implementation...
383 /// };
384 ///
385 /// template<> struct CastInfo<foo, const bar> : public
386 ///        ConstStrippingForwardingCast<foo, const bar, CastInfo<foo, bar>> {};
387 ///
388 template <typename To, typename From, typename ForwardTo>
389 struct ConstStrippingForwardingCast {
390   // Remove the pointer if it exists, then we can get rid of consts/volatiles.
391   using DecayedFrom = std::remove_cv_t<std::remove_pointer_t<From>>;
392   // Now if it's a pointer, add it back. Otherwise, we want a ref.
393   using NonConstFrom = std::conditional_t<std::is_pointer<From>::value,
394                                           DecayedFrom *, DecayedFrom &>;
395 
396   static inline bool isPossible(const From &f) {
397     return ForwardTo::isPossible(const_cast<NonConstFrom>(f));
398   }
399 
400   static inline decltype(auto) castFailed() { return ForwardTo::castFailed(); }
401 
402   static inline decltype(auto) doCast(const From &f) {
403     return ForwardTo::doCast(const_cast<NonConstFrom>(f));
404   }
405 
406   static inline decltype(auto) doCastIfPossible(const From &f) {
407     return ForwardTo::doCastIfPossible(const_cast<NonConstFrom>(f));
408   }
409 };
410 
411 /// Provides a cast trait that uses a defined pointer to pointer cast as a base
412 /// for reference-to-reference casts. Note that it does not provide castFailed
413 /// and doCastIfPossible because a pointer-to-pointer cast would likely just
414 /// return `nullptr` which could cause nullptr dereference. You can use it like
415 /// this:
416 ///
417 ///   template <> struct CastInfo<foo, bar *> { ... verbose implementation... };
418 ///
419 ///   template <>
420 ///   struct CastInfo<foo, bar>
421 ///       : public ForwardToPointerCast<foo, bar, CastInfo<foo, bar *>> {};
422 ///
423 template <typename To, typename From, typename ForwardTo>
424 struct ForwardToPointerCast {
425   static inline bool isPossible(const From &f) {
426     return ForwardTo::isPossible(&f);
427   }
428 
429   static inline decltype(auto) doCast(const From &f) {
430     return *ForwardTo::doCast(&f);
431   }
432 };
433 
434 //===----------------------------------------------------------------------===//
435 // CastInfo
436 //===----------------------------------------------------------------------===//
437 
438 /// This struct provides a method for customizing the way a cast is performed.
439 /// It inherits from CastIsPossible, to support the case of declaring many
440 /// CastIsPossible specializations without having to specialize the full
441 /// CastInfo.
442 ///
443 /// In order to specialize different behaviors, specify different functions in
444 /// your CastInfo specialization.
445 /// For isa<> customization, provide:
446 ///
447 ///   `static bool isPossible(const From &f)`
448 ///
449 /// For cast<> customization, provide:
450 ///
451 ///  `static To doCast(const From &f)`
452 ///
453 /// For dyn_cast<> and the *_if_present<> variants' customization, provide:
454 ///
455 ///  `static To castFailed()` and `static To doCastIfPossible(const From &f)`
456 ///
457 /// Your specialization might look something like this:
458 ///
459 ///  template<> struct CastInfo<foo, bar> : public CastIsPossible<foo, bar> {
460 ///    static inline foo doCast(const bar &b) {
461 ///      return foo(const_cast<bar &>(b));
462 ///    }
463 ///    static inline foo castFailed() { return foo(); }
464 ///    static inline foo doCastIfPossible(const bar &b) {
465 ///      if (!CastInfo<foo, bar>::isPossible(b))
466 ///        return castFailed();
467 ///      return doCast(b);
468 ///    }
469 ///  };
470 
471 // The default implementations of CastInfo don't use cast traits for now because
472 // we need to specify types all over the place due to the current expected
473 // casting behavior and the way cast_retty works. New use cases can and should
474 // take advantage of the cast traits whenever possible!
475 
476 template <typename To, typename From, typename Enable = void>
477 struct CastInfo : public CastIsPossible<To, From> {
478   using Self = CastInfo<To, From, Enable>;
479 
480   using CastReturnType = typename cast_retty<To, From>::ret_type;
481 
482   static inline CastReturnType doCast(const From &f) {
483     return cast_convert_val<
484         To, From,
485         typename simplify_type<From>::SimpleType>::doit(const_cast<From &>(f));
486   }
487 
488   // This assumes that you can construct the cast return type from `nullptr`.
489   // This is largely to support legacy use cases - if you don't want this
490   // behavior you should specialize CastInfo for your use case.
491   static inline CastReturnType castFailed() { return CastReturnType(nullptr); }
492 
493   static inline CastReturnType doCastIfPossible(const From &f) {
494     if (!Self::isPossible(f))
495       return castFailed();
496     return doCast(f);
497   }
498 };
499 
500 /// This struct provides an overload for CastInfo where From has simplify_type
501 /// defined. This simply forwards to the appropriate CastInfo with the
502 /// simplified type/value, so you don't have to implement both.
503 template <typename To, typename From>
504 struct CastInfo<To, From, std::enable_if_t<!is_simple_type<From>::value>> {
505   using Self = CastInfo<To, From>;
506   using SimpleFrom = typename simplify_type<From>::SimpleType;
507   using SimplifiedSelf = CastInfo<To, SimpleFrom>;
508 
509   static inline bool isPossible(From &f) {
510     return SimplifiedSelf::isPossible(
511         simplify_type<From>::getSimplifiedValue(f));
512   }
513 
514   static inline decltype(auto) doCast(From &f) {
515     return SimplifiedSelf::doCast(simplify_type<From>::getSimplifiedValue(f));
516   }
517 
518   static inline decltype(auto) castFailed() {
519     return SimplifiedSelf::castFailed();
520   }
521 
522   static inline decltype(auto) doCastIfPossible(From &f) {
523     return SimplifiedSelf::doCastIfPossible(
524         simplify_type<From>::getSimplifiedValue(f));
525   }
526 };
527 
528 //===----------------------------------------------------------------------===//
529 // Pre-specialized CastInfo
530 //===----------------------------------------------------------------------===//
531 
532 /// Provide a CastInfo specialized for std::unique_ptr.
533 template <typename To, typename From>
534 struct CastInfo<To, std::unique_ptr<From>> : public UniquePtrCast<To, From> {};
535 
536 /// Provide a CastInfo specialized for std::optional<From>. It's assumed that if
537 /// the input is std::optional<From> that the output can be std::optional<To>.
538 /// If that's not the case, specialize CastInfo for your use case.
539 template <typename To, typename From>
540 struct CastInfo<To, std::optional<From>> : public OptionalValueCast<To, From> {
541 };
542 
543 /// isa<X> - Return true if the parameter to the template is an instance of one
544 /// of the template type arguments.  Used like this:
545 ///
546 ///  if (isa<Type>(myVal)) { ... }
547 ///  if (isa<Type0, Type1, Type2>(myVal)) { ... }
548 template <typename To, typename From>
549 [[nodiscard]] inline bool isa(const From &Val) {
550   return CastInfo<To, const From>::isPossible(Val);
551 }
552 
553 template <typename First, typename Second, typename... Rest, typename From>
554 [[nodiscard]] inline bool isa(const From &Val) {
555   return isa<First>(Val) || isa<Second, Rest...>(Val);
556 }
557 
558 /// cast<X> - Return the argument parameter cast to the specified type.  This
559 /// casting operator asserts that the type is correct, so it does not return
560 /// null on failure.  It does not allow a null argument (use cast_if_present for
561 /// that). It is typically used like this:
562 ///
563 ///  cast<Instruction>(myVal)->getParent()
564 
565 template <typename To, typename From>
566 [[nodiscard]] inline decltype(auto) cast(const From &Val) {
567   assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
568   return CastInfo<To, const From>::doCast(Val);
569 }
570 
571 template <typename To, typename From>
572 [[nodiscard]] inline decltype(auto) cast(From &Val) {
573   assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
574   return CastInfo<To, From>::doCast(Val);
575 }
576 
577 template <typename To, typename From>
578 [[nodiscard]] inline decltype(auto) cast(From *Val) {
579   assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
580   return CastInfo<To, From *>::doCast(Val);
581 }
582 
583 template <typename To, typename From>
584 [[nodiscard]] inline decltype(auto) cast(std::unique_ptr<From> &&Val) {
585   assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
586   return CastInfo<To, std::unique_ptr<From>>::doCast(std::move(Val));
587 }
588 
589 //===----------------------------------------------------------------------===//
590 // ValueIsPresent
591 //===----------------------------------------------------------------------===//
592 
593 template <typename T>
594 constexpr bool IsNullable =
595     std::is_pointer_v<T> || std::is_constructible_v<T, std::nullptr_t>;
596 
597 /// ValueIsPresent provides a way to check if a value is, well, present. For
598 /// pointers, this is the equivalent of checking against nullptr, for Optionals
599 /// this is the equivalent of checking hasValue(). It also provides a method for
600 /// unwrapping a value (think calling .value() on an optional).
601 
602 // Generic values can't *not* be present.
603 template <typename T, typename Enable = void> struct ValueIsPresent {
604   using UnwrappedType = T;
605   static inline bool isPresent(const T &t) { return true; }
606   static inline decltype(auto) unwrapValue(T &t) { return t; }
607 };
608 
609 // Optional provides its own way to check if something is present.
610 template <typename T> struct ValueIsPresent<std::optional<T>> {
611   using UnwrappedType = T;
612   static inline bool isPresent(const std::optional<T> &t) {
613     return t.has_value();
614   }
615   static inline decltype(auto) unwrapValue(std::optional<T> &t) { return *t; }
616 };
617 
618 // If something is "nullable" then we just compare it to nullptr to see if it
619 // exists.
620 template <typename T>
621 struct ValueIsPresent<T, std::enable_if_t<IsNullable<T>>> {
622   using UnwrappedType = T;
623   static inline bool isPresent(const T &t) { return t != T(nullptr); }
624   static inline decltype(auto) unwrapValue(T &t) { return t; }
625 };
626 
627 namespace detail {
628 // Convenience function we can use to check if a value is present. Because of
629 // simplify_type, we have to call it on the simplified type for now.
630 template <typename T> inline bool isPresent(const T &t) {
631   return ValueIsPresent<typename simplify_type<T>::SimpleType>::isPresent(
632       simplify_type<T>::getSimplifiedValue(const_cast<T &>(t)));
633 }
634 
635 // Convenience function we can use to unwrap a value.
636 template <typename T> inline decltype(auto) unwrapValue(T &t) {
637   return ValueIsPresent<T>::unwrapValue(t);
638 }
639 } // namespace detail
640 
641 /// dyn_cast<X> - Return the argument parameter cast to the specified type. This
642 /// casting operator returns null if the argument is of the wrong type, so it
643 /// can be used to test for a type as well as cast if successful. The value
644 /// passed in must be present, if not, use dyn_cast_if_present. This should be
645 /// used in the context of an if statement like this:
646 ///
647 ///  if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... }
648 
649 template <typename To, typename From>
650 [[nodiscard]] inline decltype(auto) dyn_cast(const From &Val) {
651   assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
652   return CastInfo<To, const From>::doCastIfPossible(Val);
653 }
654 
655 template <typename To, typename From>
656 [[nodiscard]] inline decltype(auto) dyn_cast(From &Val) {
657   assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
658   return CastInfo<To, From>::doCastIfPossible(Val);
659 }
660 
661 template <typename To, typename From>
662 [[nodiscard]] inline decltype(auto) dyn_cast(From *Val) {
663   assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
664   return CastInfo<To, From *>::doCastIfPossible(Val);
665 }
666 
667 template <typename To, typename From>
668 [[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &&Val) {
669   assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
670   return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible(
671       std::forward<std::unique_ptr<From> &&>(Val));
672 }
673 
674 /// isa_and_present<X> - Functionally identical to isa, except that a null value
675 /// is accepted.
676 template <typename... X, class Y>
677 [[nodiscard]] inline bool isa_and_present(const Y &Val) {
678   if (!detail::isPresent(Val))
679     return false;
680   return isa<X...>(Val);
681 }
682 
683 template <typename... X, class Y>
684 [[nodiscard]] inline bool isa_and_nonnull(const Y &Val) {
685   return isa_and_present<X...>(Val);
686 }
687 
688 /// cast_if_present<X> - Functionally identical to cast, except that a null
689 /// value is accepted.
690 template <class X, class Y>
691 [[nodiscard]] inline auto cast_if_present(const Y &Val) {
692   if (!detail::isPresent(Val))
693     return CastInfo<X, const Y>::castFailed();
694   assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!");
695   return cast<X>(detail::unwrapValue(Val));
696 }
697 
698 template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y &Val) {
699   if (!detail::isPresent(Val))
700     return CastInfo<X, Y>::castFailed();
701   assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!");
702   return cast<X>(detail::unwrapValue(Val));
703 }
704 
705 template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y *Val) {
706   if (!detail::isPresent(Val))
707     return CastInfo<X, Y *>::castFailed();
708   assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!");
709   return cast<X>(detail::unwrapValue(Val));
710 }
711 
712 template <class X, class Y>
713 [[nodiscard]] inline auto cast_if_present(std::unique_ptr<Y> &&Val) {
714   if (!detail::isPresent(Val))
715     return UniquePtrCast<X, Y>::castFailed();
716   return UniquePtrCast<X, Y>::doCast(std::move(Val));
717 }
718 
719 // Provide a forwarding from cast_or_null to cast_if_present for current
720 // users. This is deprecated and will be removed in a future patch, use
721 // cast_if_present instead.
722 template <class X, class Y> auto cast_or_null(const Y &Val) {
723   return cast_if_present<X>(Val);
724 }
725 
726 template <class X, class Y> auto cast_or_null(Y &Val) {
727   return cast_if_present<X>(Val);
728 }
729 
730 template <class X, class Y> auto cast_or_null(Y *Val) {
731   return cast_if_present<X>(Val);
732 }
733 
734 template <class X, class Y> auto cast_or_null(std::unique_ptr<Y> &&Val) {
735   return cast_if_present<X>(std::move(Val));
736 }
737 
738 /// dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a
739 /// null (or none in the case of optionals) value is accepted.
740 template <class X, class Y> auto dyn_cast_if_present(const Y &Val) {
741   if (!detail::isPresent(Val))
742     return CastInfo<X, const Y>::castFailed();
743   return CastInfo<X, const Y>::doCastIfPossible(detail::unwrapValue(Val));
744 }
745 
746 template <class X, class Y> auto dyn_cast_if_present(Y &Val) {
747   if (!detail::isPresent(Val))
748     return CastInfo<X, Y>::castFailed();
749   return CastInfo<X, Y>::doCastIfPossible(detail::unwrapValue(Val));
750 }
751 
752 template <class X, class Y> auto dyn_cast_if_present(Y *Val) {
753   if (!detail::isPresent(Val))
754     return CastInfo<X, Y *>::castFailed();
755   return CastInfo<X, Y *>::doCastIfPossible(detail::unwrapValue(Val));
756 }
757 
758 // Forwards to dyn_cast_if_present to avoid breaking current users. This is
759 // deprecated and will be removed in a future patch, use
760 // cast_if_present instead.
761 template <class X, class Y> auto dyn_cast_or_null(const Y &Val) {
762   return dyn_cast_if_present<X>(Val);
763 }
764 
765 template <class X, class Y> auto dyn_cast_or_null(Y &Val) {
766   return dyn_cast_if_present<X>(Val);
767 }
768 
769 template <class X, class Y> auto dyn_cast_or_null(Y *Val) {
770   return dyn_cast_if_present<X>(Val);
771 }
772 
773 /// unique_dyn_cast<X> - Given a unique_ptr<Y>, try to return a unique_ptr<X>,
774 /// taking ownership of the input pointer iff isa<X>(Val) is true.  If the
775 /// cast is successful, From refers to nullptr on exit and the casted value
776 /// is returned.  If the cast is unsuccessful, the function returns nullptr
777 /// and From is unchanged.
778 template <class X, class Y>
779 [[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType
780 unique_dyn_cast(std::unique_ptr<Y> &Val) {
781   if (!isa<X>(Val))
782     return nullptr;
783   return cast<X>(std::move(Val));
784 }
785 
786 template <class X, class Y>
787 [[nodiscard]] inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val) {
788   return unique_dyn_cast<X, Y>(Val);
789 }
790 
791 // unique_dyn_cast_or_null<X> - Functionally identical to unique_dyn_cast,
792 // except that a null value is accepted.
793 template <class X, class Y>
794 [[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType
795 unique_dyn_cast_or_null(std::unique_ptr<Y> &Val) {
796   if (!Val)
797     return nullptr;
798   return unique_dyn_cast<X, Y>(Val);
799 }
800 
801 template <class X, class Y>
802 [[nodiscard]] inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val) {
803   return unique_dyn_cast_or_null<X, Y>(Val);
804 }
805 
806 } // end namespace llvm
807 
808 #endif // LLVM_SUPPORT_CASTING_H
809