2929// / \return true if \a base is of type \a T
3030template <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.
3849inline 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+
4061namespace 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+
89137namespace 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+
143206inline void validate_operands (
144207 const exprt &value,
145208 exprt::operandst::size_type number,
0 commit comments