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