29
29
// / \return true if \a base is of type \a T
30
30
template <typename T> inline bool can_cast_expr (const exprt &base);
31
31
32
+ // / \brief Check whether a reference to a generic \ref typet is of a specific
33
+ // / derived class.
34
+ // /
35
+ // / Implement template specializations of this function to enable casting
36
+ // /
37
+ // / \tparam T The typet-derived class to check for
38
+ // / \param base Reference to a generic \ref typet
39
+ // / \return true if \a base is of type \a T
40
+ template <typename T>
41
+ inline bool can_cast_type (const typet &base);
42
+
32
43
// / Called after casting. Provides a point to assert on the structure of the
33
44
// / expr. By default, this is a no-op, but you can provide an overload to
34
45
// / validate particular types. Should always succeed unless the program has
@@ -37,6 +48,16 @@ template<typename T> inline bool can_cast_expr(const exprt &base);
37
48
// / validate objects in this way at any time.
38
49
inline void validate_expr (const exprt &) {}
39
50
51
+ // / Called after casting. Provides a point to check data invariants on the
52
+ // / structure of the typet. By default, this is a no-op, but you can provide an
53
+ // / overload to validate particular types. Should always succeed unless the
54
+ // / program has entered an invalid state. We validate objects at cast time as
55
+ // / that is when these checks have been used historically, but it would be
56
+ // / reasonable to validate objects in this way at any time.
57
+ inline void validate_type (const typet &)
58
+ {
59
+ }
60
+
40
61
namespace detail // NOLINT
41
62
{
42
63
@@ -86,6 +107,33 @@ auto expr_try_dynamic_cast(TExpr &base)
86
107
return ret;
87
108
}
88
109
110
+ // / \brief Try to cast a reference to a generic typet to a specific derived
111
+ // / class
112
+ // / \tparam T The reference or const reference type to \a TUnderlying to cast
113
+ // / to
114
+ // / \tparam TType The original type to cast from, either typet or const typet
115
+ // / \param base Reference to a generic \ref typet
116
+ // / \return Ptr to object of type \a TUnderlying
117
+ // / or nullptr if \a base is not an instance of \a TUnderlying
118
+ template <typename T, typename TType>
119
+ auto type_try_dynamic_cast (TType &base) ->
120
+ typename detail::expr_try_dynamic_cast_return_typet<T, TType>::type
121
+ {
122
+ typedef
123
+ typename detail::expr_try_dynamic_cast_return_typet<T, TType>::type returnt;
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
+
89
137
namespace detail // NOLINT
90
138
{
91
139
@@ -140,6 +188,21 @@ auto expr_checked_cast(TExpr &base)
140
188
return expr_dynamic_cast<T>(base);
141
189
}
142
190
191
+ // / \brief Cast a reference to a generic typet to a specific derived class and
192
+ // / checks that the type could be converted.
193
+ // / \tparam T The reference or const reference type to \a TUnderlying to cast to
194
+ // / \tparam TType The original type to cast from, either typet or const typet
195
+ // / \param base Reference to a generic \ref typet
196
+ // / \return Reference to object of type \a T
197
+ template <typename T, typename TType>
198
+ auto type_checked_cast (TType &base) ->
199
+ typename detail::expr_dynamic_cast_return_typet<T, TType>::type
200
+ {
201
+ auto result = type_try_dynamic_cast<T>(base);
202
+ CHECK_RETURN (result != nullptr );
203
+ return *result;
204
+ }
205
+
143
206
inline void validate_operands (
144
207
const exprt &value,
145
208
exprt::operandst::size_type number,
0 commit comments