cprover
expr_cast.h
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Nathan Phillips <Nathan.Phillips@diffblue.com>
6 
7 \*******************************************************************/
8 
9 #ifndef CPROVER_UTIL_EXPR_CAST_H
10 #define CPROVER_UTIL_EXPR_CAST_H
11 
14 
15 #include <typeinfo>
16 #include <type_traits>
17 #include <functional>
18 
19 #include "invariant.h"
20 #include "expr.h"
21 
30 template<typename T> inline bool can_cast_expr(const exprt &base);
31 
40 template <typename T>
41 inline bool can_cast_type(const typet &base);
42 
49 inline void validate_expr(const exprt &) {}
50 
57 inline void validate_type(const typet &)
58 {
59 }
60 
61 namespace detail // NOLINT
62 {
63 
64 template<typename Ret, typename T>
66 {
67  static_assert(
68  !std::is_reference<Ret>::value,
69  "Ret must not be a reference, i.e. expr_try_dynamic_cast<const thingt> "
70  "rather than expr_try_dynamic_cast<const thing &>");
71 
72  typedef
73  typename std::conditional<
74  std::is_const<T>::value,
75  typename std::add_const<Ret>::type,
76  Ret>::type *
77  type;
78 };
79 
80 } // namespace detail
81 
90 template <typename T, typename TExpr>
91 auto expr_try_dynamic_cast(TExpr &base)
93 {
94  typedef
96  returnt;
97  static_assert(
98  std::is_base_of<exprt, typename std::decay<TExpr>::type>::value,
99  "Tried to expr_try_dynamic_cast from something that wasn't an exprt");
100  static_assert(
101  std::is_base_of<exprt, T>::value,
102  "The template argument T must be derived from exprt.");
103  if(!can_cast_expr<typename std::remove_const<T>::type>(base))
104  return nullptr;
105  const auto ret=static_cast<returnt>(&base);
106  validate_expr(*ret);
107  return ret;
108 }
109 
118 template <typename T, typename TType>
119 auto type_try_dynamic_cast(TType &base) ->
121 {
122  typedef
124  static_assert(
125  std::is_base_of<typet, typename std::decay<TType>::type>::value,
126  "Tried to type_try_dynamic_cast from something that wasn't an typet");
127  static_assert(
128  std::is_base_of<typet, T>::value,
129  "The template argument T must be derived from typet.");
130  if(!can_cast_type<typename std::remove_const<T>::type>(base))
131  return nullptr;
132  const auto ret = static_cast<returnt>(&base);
133  validate_type(*ret);
134  return ret;
135 }
136 
137 namespace detail // NOLINT
138 {
139 
140 template<typename Ret, typename T>
142 {
143  static_assert(
144  !std::is_reference<Ret>::value,
145  "Ret must not be a reference, i.e. expr_dynamic_cast<const thingt> rather "
146  "than expr_dynamic_cast<const thing &>");
147 
148  typedef
149  typename std::conditional<
150  std::is_const<T>::value,
151  typename std::add_const<Ret>::type,
152  Ret>::type &
153  type;
154 };
155 
156 } // namespace detail
157 
164 template<typename T, typename TExpr>
165 auto expr_dynamic_cast(TExpr &base)
167 {
168  const auto ret=expr_try_dynamic_cast<T>(base);
169  if(ret==nullptr)
170  throw std::bad_cast();
171  return *ret;
172 }
173 
183 template<typename T, typename TExpr>
184 auto expr_checked_cast(TExpr &base)
186 {
187  PRECONDITION(can_cast_expr<T>(base));
188  return expr_dynamic_cast<T>(base);
189 }
190 
197 template <typename T, typename TType>
198 auto type_checked_cast(TType &base) ->
200 {
201  auto result = type_try_dynamic_cast<T>(base);
202  CHECK_RETURN(result != nullptr);
203  return *result;
204 }
205 
206 inline void validate_operands(
207  const exprt &value,
209  const char *message,
210  bool allow_more=false)
211 {
213  allow_more
214  ? value.operands().size()>=number
215  : value.operands().size()==number,
216  message);
217 }
218 
219 #endif // CPROVER_UTIL_EXPR_CAST_H
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:438
DATA_INVARIANT
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:485
typet
The type of an expression, extends irept.
Definition: type.h:27
validate_operands
void validate_operands(const exprt &value, exprt::operandst::size_type number, const char *message, bool allow_more=false)
Definition: expr_cast.h:206
exprt
Base class for all expressions.
Definition: expr.h:54
can_cast_type
bool can_cast_type(const typet &base)
Check whether a reference to a generic typet is of a specific derived class.
detail
Definition: expr_cast.h:61
invariant.h
expr_dynamic_cast
auto expr_dynamic_cast(TExpr &base) -> typename detail::expr_dynamic_cast_return_typet< T, TExpr >::type
Cast a reference to a generic exprt to a specific derived class.
Definition: expr_cast.h:165
type_checked_cast
auto type_checked_cast(TType &base) -> typename detail::expr_dynamic_cast_return_typet< T, TType >::type
Cast a reference to a generic typet to a specific derived class and checks that the type could be con...
Definition: expr_cast.h:198
expr.h
detail::expr_try_dynamic_cast_return_typet
Definition: expr_cast.h:65
validate_type
void validate_type(const typet &)
Called after casting.
Definition: expr_cast.h:57
detail::expr_dynamic_cast_return_typet::type
std::conditional< std::is_const< T >::value, typename std::add_const< Ret >::type, Ret >::type & type
Definition: expr_cast.h:146
type_try_dynamic_cast
auto type_try_dynamic_cast(TType &base) -> typename detail::expr_try_dynamic_cast_return_typet< T, TType >::type
Try to cast a reference to a generic typet to a specific derived class.
Definition: expr_cast.h:119
expr_checked_cast
auto expr_checked_cast(TExpr &base) -> typename detail::expr_dynamic_cast_return_typet< T, TExpr >::type
Cast a reference to a generic exprt to a specific derived class.
Definition: expr_cast.h:184
detail::expr_dynamic_cast_return_typet
Definition: expr_cast.h:141
can_cast_expr
bool can_cast_expr(const exprt &base)
Check whether a reference to a generic exprt is of a specific derived class.
exprt::operands
operandst & operands()
Definition: expr.h:78
expr_try_dynamic_cast
auto expr_try_dynamic_cast(TExpr &base) -> typename detail::expr_try_dynamic_cast_return_typet< T, TExpr >::type
Try to cast a reference to a generic exprt to a specific derived class.
Definition: expr_cast.h:91
validate_expr
void validate_expr(const exprt &)
Called after casting.
Definition: expr_cast.h:49
size_type
unsignedbv_typet size_type()
Definition: c_types.cpp:58
detail::expr_try_dynamic_cast_return_typet::type
std::conditional< std::is_const< T >::value, typename std::add_const< Ret >::type, Ret >::type * type
Definition: expr_cast.h:70
CHECK_RETURN
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:470