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