Static Value-Flow Analysis
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 
59 namespace SVF
60 {
61 
62 namespace SVFUtil
63 {
64 
65 //===- Part of llvm/Support/type_traits.h - Simplified type traits -------*- C++ -*-===//
66 
69 template<typename T, typename Enable = void>
71 {
72  using type = const T;
73 };
74 
75 template <typename T>
76 struct 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 
82 template<typename T, typename Enable = void>
84 {
85  using type = T &;
86 };
87 
88 template <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 //
103 template<typename From> struct simplify_type
104 {
105  using SimpleType = From; // The real type this represents...
106 
107  // An accessor to get the real value...
108  static SimpleType &getSimplifiedValue(From &Val)
109  {
110  return Val;
111  }
112 };
113 
114 template<typename From> struct simplify_type<const From>
115 {
117  using SimpleType =
119  using RetType =
121 
122  static RetType getSimplifiedValue(const From& Val)
123  {
124  return simplify_type<From>::getSimplifiedValue(const_cast<From&>(Val));
125  }
126 };
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.
131 template <typename To, typename From, typename Enabler = void>
132 struct isa_impl
133 {
134  static inline bool doit(const From &Val)
135  {
136  return To::classof(&Val);
137  }
138 };
139 
141 template <typename To, typename From>
142 struct 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 
150 template <typename To, typename From> struct isa_impl_cl
151 {
152  static inline bool doit(const From &Val)
153  {
154  return isa_impl<To, From>::doit(Val);
155  }
156 };
157 
158 template <typename To, typename From> struct isa_impl_cl<To, const From>
159 {
160  static inline bool doit(const From &Val)
161  {
162  return isa_impl<To, From>::doit(Val);
163  }
164 };
165 
166 template <typename To, typename From>
167 struct 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");
172  return isa_impl_cl<To, From>::doit(*Val);
173  }
174 };
175 
176 template <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");
181  return isa_impl<To, From>::doit(*Val);
182  }
183 };
184 
185 template <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");
190  return isa_impl<To, From>::doit(*Val);
191  }
192 };
193 
194 template <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");
199  return isa_impl<To, From>::doit(*Val);
200  }
201 };
202 
203 template <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");
208  return isa_impl<To, From>::doit(*Val);
209  }
210 };
211 
212 template<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.
217  static bool doit(const From &Val)
218  {
219  return isa_impl_wrap<To, SimpleFrom,
222  }
223 };
224 
225 template<typename To, typename FromTy>
226 struct isa_impl_wrap<To, FromTy, FromTy>
227 {
228  // When From == SimpleType, we are as simple as we are going to get.
229  static bool doit(const FromTy &Val)
230  {
231  return isa_impl_cl<To,FromTy>::doit(Val);
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 //
241 template <class X, class Y> LLVM_NODISCARD inline bool isa(const Y &Val)
242 {
243  return isa_impl_wrap<X, const Y,
244  typename simplify_type<const Y>::SimpleType>::doit(Val);
245 }
246 
247 template <typename First, typename Second, typename... Rest, typename Y>
248 LLVM_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 
257 template<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.
261 template<class To, class From> struct cast_retty_impl
262 {
263  using ret_type = To &; // Normal case, return Ty&
264 };
265 template<class To, class From> struct cast_retty_impl<To, const From>
266 {
267  using ret_type = const To &; // Normal case, return Ty&
268 };
269 
270 template<class To, class From> struct cast_retty_impl<To, From*>
271 {
272  using ret_type = To *; // Pointer arg case, return Ty*
273 };
274 
275 template<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 
280 template<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 
285 template <class To, class From>
286 struct cast_retty_impl<To, std::unique_ptr<From>>
287 {
288 private:
291 
292 public:
293  using ret_type = std::unique_ptr<ResultType>;
294 };
295 
296 template<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 
305 template<class To, class FromTy>
306 struct cast_retty_wrap<To, FromTy, FromTy>
307 {
308  // When the simplified type is equal to the from type, use it directly.
310 };
311 
312 template<class To, class From>
314 {
315  using ret_type = typename cast_retty_wrap<
316  To, From, typename simplify_type<From>::SimpleType>::ret_type;
317 };
318 
319 // Ensure the non-simple values are converted using the simplify_type template
320 // that may be specialized by smart pointers...
321 //
322 template<class To, class From, class SimpleFrom> struct cast_convert_val
323 {
324  // This is not a simple type, use the template to simplify it...
325  static typename cast_retty<To, From>::ret_type doit(From &Val)
326  {
327  return cast_convert_val<To, SimpleFrom,
330  }
331 };
332 
333 template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy>
334 {
335  // This _is_ a simple type, just cast it.
336  static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val)
337  {
339  = (typename cast_retty<To, FromTy>::ret_type)const_cast<FromTy&>(Val);
340  return Res2;
341  }
342 };
343 
344 template <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 //
357 template <class X, class Y>
358 inline 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 
367 template <class X, class Y>
368 inline typename cast_retty<X, Y>::ret_type cast(Y &Val)
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 
375 template <class X, class Y>
376 inline typename cast_retty<X, Y *>::ret_type cast(Y *Val)
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 
383 template <class X, class Y>
384 inline 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(
390  cast_convert_val<X, Y *, typename simplify_type<Y *>::SimpleType>::doit(
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 
402 template <class X, class Y>
403 LLVM_NODISCARD inline std::enable_if_t<
405 dyn_cast(const Y &Val)
406 {
407  return SVFUtil::isa<X>(Val) ? SVFUtil::cast<X>(Val) : nullptr;
408 }
409 
410 template <class X, class Y>
412 {
413  return SVFUtil::isa<X>(Val) ? SVFUtil::cast<X>(Val) : nullptr;
414 }
415 
416 template <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
newitem type
Definition: cJSON.cpp:2739
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
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