1 //===- llvm/Support/Casting.h - Allow flexible, checked, casts --*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines the isa<X>(), cast<X>(), dyn_cast<X>(), cast_or_null<X>(),
10 // and dyn_cast_or_null<X>() templates.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_SUPPORT_CASTING_H
15 #define LLVM_SUPPORT_CASTING_H
17 #include "llvm/Support/Compiler.h"
18 #include "llvm/Support/type_traits.h"
21 #include <type_traits>
25 //===----------------------------------------------------------------------===//
26 // isa<x> Support Templates
27 //===----------------------------------------------------------------------===//
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.
33 template<typename From
> struct simplify_type
{
34 using SimpleType
= From
; // The real type this represents...
36 // An accessor to get the real value...
37 static SimpleType
&getSimplifiedValue(From
&Val
) { return Val
; }
40 template<typename From
> struct simplify_type
<const From
> {
41 using NonConstSimpleType
= typename simplify_type
<From
>::SimpleType
;
43 typename add_const_past_pointer
<NonConstSimpleType
>::type
;
45 typename add_lvalue_reference_if_not_pointer
<SimpleType
>::type
;
47 static RetType
getSimplifiedValue(const From
& Val
) {
48 return simplify_type
<From
>::getSimplifiedValue(const_cast<From
&>(Val
));
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.
55 template <typename To
, typename From
, typename Enabler
= void>
57 static inline bool doit(const From
&Val
) {
58 return To::classof(&Val
);
62 /// Always allow upcasts, and perform no dynamic check for them.
63 template <typename To
, typename From
>
65 To
, From
, typename
std::enable_if
<std::is_base_of
<To
, From
>::value
>::type
> {
66 static inline bool doit(const From
&) { return true; }
69 template <typename To
, typename From
> struct isa_impl_cl
{
70 static inline bool doit(const From
&Val
) {
71 return isa_impl
<To
, From
>::doit(Val
);
75 template <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
);
81 template <typename To
, typename From
>
82 struct 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
);
89 template <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
);
96 template <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
);
103 template <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
);
110 template <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
);
117 template<typename To
, typename From
, typename SimpleFrom
>
118 struct 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
));
128 template<typename To
, typename FromTy
>
129 struct 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
);
136 // isa<X> - Return true if the parameter to the template is an instance of the
137 // template type argument. Used like this:
139 // if (isa<Type>(myVal)) { ... }
141 template <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
);
146 //===----------------------------------------------------------------------===//
147 // cast<x> Support Templates
148 //===----------------------------------------------------------------------===//
150 template<class To
, class From
> struct cast_retty
;
152 // Calculate what type the 'cast' function should return, based on a requested
153 // type of To and a source type of From.
154 template<class To
, class From
> struct cast_retty_impl
{
155 using ret_type
= To
&; // Normal case, return Ty&
157 template<class To
, class From
> struct cast_retty_impl
<To
, const From
> {
158 using ret_type
= const To
&; // Normal case, return Ty&
161 template<class To
, class From
> struct cast_retty_impl
<To
, From
*> {
162 using ret_type
= To
*; // Pointer arg case, return Ty*
165 template<class To
, class From
> struct cast_retty_impl
<To
, const From
*> {
166 using ret_type
= const To
*; // Constant pointer arg case, return const Ty*
169 template<class To
, class From
> struct cast_retty_impl
<To
, const From
*const> {
170 using ret_type
= const To
*; // Constant pointer arg case, return const Ty*
173 template <class To
, class From
>
174 struct cast_retty_impl
<To
, std::unique_ptr
<From
>> {
176 using PointerType
= typename cast_retty_impl
<To
, From
*>::ret_type
;
177 using ResultType
= typename
std::remove_pointer
<PointerType
>::type
;
180 using ret_type
= std::unique_ptr
<ResultType
>;
183 template<class To
, class From
, class SimpleFrom
>
184 struct cast_retty_wrap
{
185 // When the simplified type and the from type are not the same, use the type
186 // simplifier to reduce the type, then reuse cast_retty_impl to get the
188 using ret_type
= typename cast_retty
<To
, SimpleFrom
>::ret_type
;
191 template<class To
, class FromTy
>
192 struct cast_retty_wrap
<To
, FromTy
, FromTy
> {
193 // When the simplified type is equal to the from type, use it directly.
194 using ret_type
= typename cast_retty_impl
<To
,FromTy
>::ret_type
;
197 template<class To
, class From
>
199 using ret_type
= typename cast_retty_wrap
<
200 To
, From
, typename simplify_type
<From
>::SimpleType
>::ret_type
;
203 // Ensure the non-simple values are converted using the simplify_type template
204 // that may be specialized by smart pointers...
206 template<class To
, class From
, class SimpleFrom
> struct cast_convert_val
{
207 // This is not a simple type, use the template to simplify it...
208 static typename cast_retty
<To
, From
>::ret_type
doit(From
&Val
) {
209 return cast_convert_val
<To
, SimpleFrom
,
210 typename simplify_type
<SimpleFrom
>::SimpleType
>::doit(
211 simplify_type
<From
>::getSimplifiedValue(Val
));
215 template<class To
, class FromTy
> struct cast_convert_val
<To
,FromTy
,FromTy
> {
216 // This _is_ a simple type, just cast it.
217 static typename cast_retty
<To
, FromTy
>::ret_type
doit(const FromTy
&Val
) {
218 typename cast_retty
<To
, FromTy
>::ret_type Res2
219 = (typename cast_retty
<To
, FromTy
>::ret_type
)const_cast<FromTy
&>(Val
);
224 template <class X
> struct is_simple_type
{
225 static const bool value
=
226 std::is_same
<X
, typename simplify_type
<X
>::SimpleType
>::value
;
229 // cast<X> - Return the argument parameter cast to the specified type. This
230 // casting operator asserts that the type is correct, so it does not return null
231 // on failure. It does not allow a null argument (use cast_or_null for that).
232 // It is typically used like this:
234 // cast<Instruction>(myVal)->getParent()
236 template <class X
, class Y
>
237 inline typename
std::enable_if
<!is_simple_type
<Y
>::value
,
238 typename cast_retty
<X
, const Y
>::ret_type
>::type
240 assert(isa
<X
>(Val
) && "cast<Ty>() argument of incompatible type!");
241 return cast_convert_val
<
242 X
, const Y
, typename simplify_type
<const Y
>::SimpleType
>::doit(Val
);
245 template <class X
, class Y
>
246 inline typename cast_retty
<X
, Y
>::ret_type
cast(Y
&Val
) {
247 assert(isa
<X
>(Val
) && "cast<Ty>() argument of incompatible type!");
248 return cast_convert_val
<X
, Y
,
249 typename simplify_type
<Y
>::SimpleType
>::doit(Val
);
252 template <class X
, class Y
>
253 inline typename cast_retty
<X
, Y
*>::ret_type
cast(Y
*Val
) {
254 assert(isa
<X
>(Val
) && "cast<Ty>() argument of incompatible type!");
255 return cast_convert_val
<X
, Y
*,
256 typename simplify_type
<Y
*>::SimpleType
>::doit(Val
);
259 template <class X
, class Y
>
260 inline typename cast_retty
<X
, std::unique_ptr
<Y
>>::ret_type
261 cast(std::unique_ptr
<Y
> &&Val
) {
262 assert(isa
<X
>(Val
.get()) && "cast<Ty>() argument of incompatible type!");
263 using ret_type
= typename cast_retty
<X
, std::unique_ptr
<Y
>>::ret_type
;
265 cast_convert_val
<X
, Y
*, typename simplify_type
<Y
*>::SimpleType
>::doit(
269 // cast_or_null<X> - Functionally identical to cast, except that a null value is
272 template <class X
, class Y
>
273 LLVM_NODISCARD
inline
274 typename
std::enable_if
<!is_simple_type
<Y
>::value
,
275 typename cast_retty
<X
, const Y
>::ret_type
>::type
276 cast_or_null(const Y
&Val
) {
279 assert(isa
<X
>(Val
) && "cast_or_null<Ty>() argument of incompatible type!");
283 template <class X
, class Y
>
284 LLVM_NODISCARD
inline
285 typename
std::enable_if
<!is_simple_type
<Y
>::value
,
286 typename cast_retty
<X
, Y
>::ret_type
>::type
287 cast_or_null(Y
&Val
) {
290 assert(isa
<X
>(Val
) && "cast_or_null<Ty>() argument of incompatible type!");
294 template <class X
, class Y
>
295 LLVM_NODISCARD
inline typename cast_retty
<X
, Y
*>::ret_type
296 cast_or_null(Y
*Val
) {
297 if (!Val
) return nullptr;
298 assert(isa
<X
>(Val
) && "cast_or_null<Ty>() argument of incompatible type!");
302 template <class X
, class Y
>
303 inline typename cast_retty
<X
, std::unique_ptr
<Y
>>::ret_type
304 cast_or_null(std::unique_ptr
<Y
> &&Val
) {
307 return cast
<X
>(std::move(Val
));
310 // dyn_cast<X> - Return the argument parameter cast to the specified type. This
311 // casting operator returns null if the argument is of the wrong type, so it can
312 // be used to test for a type as well as cast if successful. This should be
313 // used in the context of an if statement like this:
315 // if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... }
318 template <class X
, class Y
>
319 LLVM_NODISCARD
inline
320 typename
std::enable_if
<!is_simple_type
<Y
>::value
,
321 typename cast_retty
<X
, const Y
>::ret_type
>::type
322 dyn_cast(const Y
&Val
) {
323 return isa
<X
>(Val
) ? cast
<X
>(Val
) : nullptr;
326 template <class X
, class Y
>
327 LLVM_NODISCARD
inline typename cast_retty
<X
, Y
>::ret_type
dyn_cast(Y
&Val
) {
328 return isa
<X
>(Val
) ? cast
<X
>(Val
) : nullptr;
331 template <class X
, class Y
>
332 LLVM_NODISCARD
inline typename cast_retty
<X
, Y
*>::ret_type
dyn_cast(Y
*Val
) {
333 return isa
<X
>(Val
) ? cast
<X
>(Val
) : nullptr;
336 // dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null
337 // value is accepted.
339 template <class X
, class Y
>
340 LLVM_NODISCARD
inline
341 typename
std::enable_if
<!is_simple_type
<Y
>::value
,
342 typename cast_retty
<X
, const Y
>::ret_type
>::type
343 dyn_cast_or_null(const Y
&Val
) {
344 return (Val
&& isa
<X
>(Val
)) ? cast
<X
>(Val
) : nullptr;
347 template <class X
, class Y
>
348 LLVM_NODISCARD
inline
349 typename
std::enable_if
<!is_simple_type
<Y
>::value
,
350 typename cast_retty
<X
, Y
>::ret_type
>::type
351 dyn_cast_or_null(Y
&Val
) {
352 return (Val
&& isa
<X
>(Val
)) ? cast
<X
>(Val
) : nullptr;
355 template <class X
, class Y
>
356 LLVM_NODISCARD
inline typename cast_retty
<X
, Y
*>::ret_type
357 dyn_cast_or_null(Y
*Val
) {
358 return (Val
&& isa
<X
>(Val
)) ? cast
<X
>(Val
) : nullptr;
361 // unique_dyn_cast<X> - Given a unique_ptr<Y>, try to return a unique_ptr<X>,
362 // taking ownership of the input pointer iff isa<X>(Val) is true. If the
363 // cast is successful, From refers to nullptr on exit and the casted value
364 // is returned. If the cast is unsuccessful, the function returns nullptr
365 // and From is unchanged.
366 template <class X
, class Y
>
367 LLVM_NODISCARD
inline auto unique_dyn_cast(std::unique_ptr
<Y
> &Val
)
368 -> decltype(cast
<X
>(Val
)) {
371 return cast
<X
>(std::move(Val
));
374 template <class X
, class Y
>
375 LLVM_NODISCARD
inline auto unique_dyn_cast(std::unique_ptr
<Y
> &&Val
)
376 -> decltype(cast
<X
>(Val
)) {
377 return unique_dyn_cast
<X
, Y
>(Val
);
380 // dyn_cast_or_null<X> - Functionally identical to unique_dyn_cast, except that
381 // a null value is accepted.
382 template <class X
, class Y
>
383 LLVM_NODISCARD
inline auto unique_dyn_cast_or_null(std::unique_ptr
<Y
> &Val
)
384 -> decltype(cast
<X
>(Val
)) {
387 return unique_dyn_cast
<X
, Y
>(Val
);
390 template <class X
, class Y
>
391 LLVM_NODISCARD
inline auto unique_dyn_cast_or_null(std::unique_ptr
<Y
> &&Val
)
392 -> decltype(cast
<X
>(Val
)) {
393 return unique_dyn_cast_or_null
<X
, Y
>(Val
);
396 } // end namespace llvm
398 #endif // LLVM_SUPPORT_CASTING_H