Skip to content

Commit b72bacf

Browse files
Define type_try_dynamic_cast and type_checked_cast
This is similar to expr_cast functions, with some code duplication. Allows to use type_try_dynamic_cast<> and type_checked_cast<> for typet objects in the same way we use expr_try_dynamic_cast<> and expr_checked_cast<> for exprt.
1 parent 933d635 commit b72bacf

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

src/util/expr_cast.h

+63
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@ Author: Nathan Phillips <[email protected]>
2929
/// \return true if \a base is of type \a T
3030
template<typename T> inline bool can_cast_expr(const exprt &base);
3131

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+
3243
/// Called after casting. Provides a point to assert on the structure of the
3344
/// expr. By default, this is a no-op, but you can provide an overload to
3445
/// 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);
3748
/// validate objects in this way at any time.
3849
inline void validate_expr(const exprt &) {}
3950

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+
4061
namespace detail // NOLINT
4162
{
4263

@@ -86,6 +107,33 @@ auto expr_try_dynamic_cast(TExpr &base)
86107
return ret;
87108
}
88109

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+
89137
namespace detail // NOLINT
90138
{
91139

@@ -140,6 +188,21 @@ auto expr_checked_cast(TExpr &base)
140188
return expr_dynamic_cast<T>(base);
141189
}
142190

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+
143206
inline void validate_operands(
144207
const exprt &value,
145208
exprt::operandst::size_type number,

0 commit comments

Comments
 (0)