Static Value-Flow Analysis
Loading...
Searching...
No Matches
Casting.h
Go to the documentation of this file.
1/*
2 * Casting.h
3 *
4 * Created on: 19Sep.,2018
5 * Author: yulei
6 */
7
8#ifndef INCLUDE_UTIL_CASTING_H_
9#define INCLUDE_UTIL_CASTING_H_
10
11
12//===- llvm/Support/Casting.h - Allow flexible, checked, casts --*- C++ -*-===//
13//
14// The LLVM Compiler Infrastructure
15//
16// This file is distributed under the University of Illinois Open Source
17// License. See LICENSE.TXT for details.
18//
19//===----------------------------------------------------------------------===//
20//
21// This file defines the SVFUtil::isa<X>(), cast<X>(), dyn_cast<X>(), cast_or_null<X>(),
22// and dyn_cast_or_null<X>() templates.
23//
24//===----------------------------------------------------------------------===//
25
26#include <cassert>
27#include <memory>
28#include <type_traits>
29
30//===-- Part of llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===//
31
32// Only use __has_cpp_attribute in C++ mode. GCC defines __has_cpp_attribute in
33// C mode, but the :: in __has_cpp_attribute(scoped::attribute) is invalid.
34#ifndef LLVM_HAS_CPP_ATTRIBUTE
35#if defined(__cplusplus) && defined(__has_cpp_attribute)
36# define LLVM_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
37#else
38# define LLVM_HAS_CPP_ATTRIBUTE(x) 0
39#endif
40#endif
41
43
44// Use the 'nodiscard' attribute in C++17 or newer mode.
45#if defined(__cplusplus) && __cplusplus > 201402L && LLVM_HAS_CPP_ATTRIBUTE(nodiscard)
46#define LLVM_NODISCARD [[nodiscard]]
47#elif LLVM_HAS_CPP_ATTRIBUTE(clang::warn_unused_result)
48#define LLVM_NODISCARD [[clang::warn_unused_result]]
49// Clang in C++14 mode claims that it has the 'nodiscard' attribute, but also
50// warns in the pedantic mode that 'nodiscard' is a C++17 extension (PR33518).
51// Use the 'nodiscard' attribute in C++14 mode only with GCC.
52// TODO: remove this workaround when PR33518 is resolved.
53#elif defined(__GNUC__) && LLVM_HAS_CPP_ATTRIBUTE(nodiscard)
54#define LLVM_NODISCARD [[nodiscard]]
55#else
56#define LLVM_NODISCARD
57#endif
58
59namespace SVF
60{
61
62namespace SVFUtil
63{
64
65//===- Part of llvm/Support/type_traits.h - Simplified type traits -------*- C++ -*-===//
66
69template<typename T, typename Enable = void>
71{
72 using type = const T;
73};
74
75template <typename T>
76struct add_const_past_pointer<T, std::enable_if_t<std::is_pointer<T>::value>>
77{
78 using type = const std::remove_pointer_t<T> *;
79};
80
82template<typename T, typename Enable = void>
87
88template <typename T>
90 T, std::enable_if_t<std::is_pointer<T>::value>>
91{
92 using type = T;
93};
94
95//===----------------------------------------------------------------------===//
96// SVFUtil::isa<x> Support Templates
97//===----------------------------------------------------------------------===//
98
99// Define a template that can be specialized by smart pointers to reflect the
100// fact that they are automatically dereferenced, and are not involved with the
101// template selection process... the default implementation is a noop.
102//
103template<typename From> struct simplify_type
104{
105 using SimpleType = From; // The real type this represents...
106
107 // An accessor to get the real value...
109 {
110 return Val;
111 }
112};
113
127
128// The core of the implementation of SVFUtil::isa<X> is here; To and From should be
129// the names of classes. This template can be specialized to customize the
130// implementation of SVFUtil::isa<> without rewriting it from scratch.
131template <typename To, typename From, typename Enabler = void>
133{
134 static inline bool doit(const From &Val)
135 {
136 return To::classof(&Val);
137 }
138};
139
141template <typename To, typename From>
142struct isa_impl<To, From, std::enable_if_t<std::is_base_of<To, From>::value>>
143{
144 static inline bool doit(const From &)
145 {
146 return true;
147 }
148};
149
150template <typename To, typename From> struct isa_impl_cl
151{
152 static inline bool doit(const From &Val)
153 {
155 }
156};
157
158template <typename To, typename From> struct isa_impl_cl<To, const From>
159{
160 static inline bool doit(const From &Val)
161 {
163 }
164};
165
166template <typename To, typename From>
167struct isa_impl_cl<To, const std::unique_ptr<From>>
168{
169 static inline bool doit(const std::unique_ptr<From> &Val)
170 {
171 assert(Val && "SVFUtil::isa<> used on a null pointer");
173 }
174};
175
176template <typename To, typename From> struct isa_impl_cl<To, From*>
177{
178 static inline bool doit(const From *Val)
179 {
180 assert(Val && "SVFUtil::isa<> used on a null pointer");
182 }
183};
184
185template <typename To, typename From> struct isa_impl_cl<To, From*const>
186{
187 static inline bool doit(const From *Val)
188 {
189 assert(Val && "SVFUtil::isa<> used on a null pointer");
191 }
192};
193
194template <typename To, typename From> struct isa_impl_cl<To, const From*>
195{
196 static inline bool doit(const From *Val)
197 {
198 assert(Val && "SVFUtil::isa<> used on a null pointer");
200 }
201};
202
203template <typename To, typename From> struct isa_impl_cl<To, const From*const>
204{
205 static inline bool doit(const From *Val)
206 {
207 assert(Val && "SVFUtil::isa<> used on a null pointer");
209 }
210};
211
212template<typename To, typename From, typename SimpleFrom>
214{
215 // When From != SimplifiedType, we can simplify the type some more by using
216 // the simplify_type template.
223};
224
225template<typename To, typename FromTy>
227{
228 // When From == SimpleType, we are as simple as we are going to get.
229 static bool doit(const FromTy &Val)
230 {
232 }
233};
234
235// SVFUtil::isa<X> - Return true if the parameter to the template is an instance of the
236// template type argument. Used like this:
237//
238// if (SVFUtil::isa<Type>(myVal)) { ... }
239// if (SVFUtil::isa<Type0, Type1, Type2>(myVal)) { ... }
240//
241template <class X, class Y> LLVM_NODISCARD inline bool isa(const Y &Val)
242{
243 return isa_impl_wrap<X, const Y,
245}
246
247template <typename First, typename Second, typename... Rest, typename Y>
248LLVM_NODISCARD inline bool isa(const Y &Val)
249{
250 return SVFUtil::isa<First>(Val) || SVFUtil::isa<Second, Rest...>(Val);
251}
252
253//===----------------------------------------------------------------------===//
254// cast<x> Support Templates
255//===----------------------------------------------------------------------===//
256
257template<class To, class From> struct cast_retty;
258
259// Calculate what type the 'cast' function should return, based on a requested
260// type of To and a source type of From.
261template<class To, class From> struct cast_retty_impl
262{
263 using ret_type = To &; // Normal case, return Ty&
264};
265template<class To, class From> struct cast_retty_impl<To, const From>
266{
267 using ret_type = const To &; // Normal case, return Ty&
268};
269
270template<class To, class From> struct cast_retty_impl<To, From*>
271{
272 using ret_type = To *; // Pointer arg case, return Ty*
273};
274
275template<class To, class From> struct cast_retty_impl<To, const From*>
276{
277 using ret_type = const To *; // Constant pointer arg case, return const Ty*
278};
279
280template<class To, class From> struct cast_retty_impl<To, const From*const>
281{
282 using ret_type = const To *; // Constant pointer arg case, return const Ty*
283};
284
285template <class To, class From>
286struct cast_retty_impl<To, std::unique_ptr<From>>
287{
288private:
290 using ResultType = typename std::remove_pointer<PointerType>::type;
291
292public:
293 using ret_type = std::unique_ptr<ResultType>;
294};
295
296template<class To, class From, class SimpleFrom>
298{
299 // When the simplified type and the from type are not the same, use the type
300 // simplifier to reduce the type, then reuse cast_retty_impl to get the
301 // resultant type.
303};
304
305template<class To, class FromTy>
307{
308 // When the simplified type is equal to the from type, use it directly.
310};
311
312template<class To, class From>
314{
315 using ret_type = typename cast_retty_wrap<
317};
318
319// Ensure the non-simple values are converted using the simplify_type template
320// that may be specialized by smart pointers...
321//
322template<class To, class From, class SimpleFrom> struct cast_convert_val
323{
324 // This is not a simple type, use the template to simplify it...
331};
332
333template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy>
334{
335 // This _is_ a simple type, just cast it.
337 {
339 = (typename cast_retty<To, FromTy>::ret_type)const_cast<FromTy&>(Val);
340 return Res2;
341 }
342};
343
344template <class X> struct is_simple_type
345{
346 static const bool value =
347 std::is_same<X, typename simplify_type<X>::SimpleType>::value;
348};
349
350// cast<X> - Return the argument parameter cast to the specified type. This
351// casting operator asserts that the type is correct, so it does not return null
352// on failure. It does not allow a null argument (use cast_or_null for that).
353// It is typically used like this:
354//
355// cast<Instruction>(myVal)->getParent()
356//
357template <class X, class Y>
358inline std::enable_if_t<!is_simple_type<Y>::value,
360 cast(const Y &Val)
361{
362 assert(SVFUtil::isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
363 return cast_convert_val<
364 X, const Y, typename simplify_type<const Y>::SimpleType>::doit(Val);
365}
366
367template <class X, class Y>
369{
370 assert(SVFUtil::isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
371 return cast_convert_val<X, Y,
372 typename simplify_type<Y>::SimpleType>::doit(Val);
373}
374
375template <class X, class Y>
377{
378 assert(SVFUtil::isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
379 return cast_convert_val<X, Y*,
380 typename simplify_type<Y*>::SimpleType>::doit(Val);
381}
382
383template <class X, class Y>
384inline typename cast_retty<X, std::unique_ptr<Y>>::ret_type
385 cast(std::unique_ptr<Y> &&Val)
386{
387 assert(SVFUtil::isa<X>(Val.get()) && "cast<Ty>() argument of incompatible type!");
388 using ret_type = typename cast_retty<X, std::unique_ptr<Y>>::ret_type;
389 return ret_type(
391 Val.release()));
392}
393
394// dyn_cast<X> - Return the argument parameter cast to the specified type. This
395// casting operator returns null if the argument is of the wrong type, so it can
396// be used to test for a type as well as cast if successful. This should be
397// used in the context of an if statement like this:
398//
399// if (const Instruction* I = dyn_cast<Instruction>(myVal)) { ... }
400//
401
402template <class X, class Y>
403LLVM_NODISCARD inline std::enable_if_t<
406{
407 return SVFUtil::isa<X>(Val) ? SVFUtil::cast<X>(Val) : nullptr;
408}
409
410template <class X, class Y>
412{
413 return SVFUtil::isa<X>(Val) ? SVFUtil::cast<X>(Val) : nullptr;
414}
415
416template <class X, class Y>
418{
419 return SVFUtil::isa<X>(Val) ? SVFUtil::cast<X>(Val) : nullptr;
420}
421
422} // End namespace SVFUtil
423
424} // End namespace SVF
425
426#endif /* INCLUDE_UTIL_CASTING_H_ */
#define LLVM_NODISCARD
LLVM_NODISCARD - Warn if a type or return value is discarded.
Definition Casting.h:56
std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > cast(const Y &Val)
Definition Casting.h:360
LLVM_NODISCARD bool isa(const Y &Val)
Definition Casting.h:241
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
Definition Casting.h:405
for isBitcode
Definition BasicTypes.h:68
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
If T is a pointer, just return it. If it is not, return T&.
Definition Casting.h:84
static cast_retty< To, FromTy >::ret_type doit(const FromTy &Val)
Definition Casting.h:336
static cast_retty< To, From >::ret_type doit(From &Val)
Definition Casting.h:325
typename std::remove_pointer< PointerType >::type ResultType
Definition Casting.h:290
typename cast_retty_impl< To, From * >::ret_type PointerType
Definition Casting.h:289
typename cast_retty_impl< To, FromTy >::ret_type ret_type
Definition Casting.h:309
typename cast_retty< To, SimpleFrom >::ret_type ret_type
Definition Casting.h:302
typename cast_retty_wrap< To, From, typename simplify_type< From >::SimpleType >::ret_type ret_type
Definition Casting.h:316
static const bool value
Definition Casting.h:346
static bool doit(const From *Val)
Definition Casting.h:178
static bool doit(const From *Val)
Definition Casting.h:187
static bool doit(const From &Val)
Definition Casting.h:160
static bool doit(const From *Val)
Definition Casting.h:196
static bool doit(const std::unique_ptr< From > &Val)
Definition Casting.h:169
static bool doit(const From &Val)
Definition Casting.h:152
static bool doit(const FromTy &Val)
Definition Casting.h:229
static bool doit(const From &Val)
Definition Casting.h:217
static bool doit(const From &Val)
Definition Casting.h:134
typename SVFUtil::add_const_past_pointer< NonConstSimpleType >::type SimpleType
Definition Casting.h:118
typename simplify_type< From >::SimpleType NonConstSimpleType
Definition Casting.h:116
typename SVFUtil::add_lvalue_reference_if_not_pointer< SimpleType >::type RetType
Definition Casting.h:120
static RetType getSimplifiedValue(const From &Val)
Definition Casting.h:122
static SimpleType & getSimplifiedValue(From &Val)
Definition Casting.h:108