3030// / \return true if \a base is of type \a T
3131template <typename T> bool can_cast_expr (const exprt &base);
3232
33- // / Called after casting. Provides a point to assert on the structure of the
33+ // / Called after casting. Provides a point to assert on the structure of the
3434// / expr. By default, this is a no-op, but you can provide an overload to
35- // / validate particular types.
35+ // / validate particular types. Should always succeed unless the program has
36+ // / entered an invalid state. We validate objects at cast time as that is when
37+ // / these checks have been used historically, but it would be reasonable to
38+ // / validate objects in this way at any time.
3639inline void validate_expr (const exprt &) {}
3740
3841namespace detail // NOLINT
3942{
4043
41- // We hide this in a namespace so that only functions that it only
42- // participates in overload resolution when explicitly requested.
44+ // We hide these functions in a namespace so that only functions that they only
45+ // participate in overload resolution when explicitly requested.
4346
4447// / \brief Try to cast a reference to a generic exprt to a specific derived
4548// / class
4649// / \tparam T The reference or const reference type to \a TUnderlying to cast
4750// / to
48- // / \tparam TUnderlying An exprt-derived class type
4951// / \tparam TExpr The original type to cast from, either exprt or const exprt
5052// / \param base Reference to a generic \ref exprt
5153// / \return Reference to object of type \a TUnderlying
@@ -54,22 +56,39 @@ template <typename T, typename TExpr>
5456optionalt<std::reference_wrapper<typename std::remove_reference<T>::type>>
5557expr_try_dynamic_cast (TExpr &base)
5658{
57- typedef typename std::decay<T>::type TUnderlying ;
58- typedef typename std::remove_reference<T>::type TConst ;
59+ typedef typename std::decay<T>::type TUnderlyingt ;
60+ typedef typename std::remove_reference<T>::type TConstt ;
5961 static_assert (
6062 std::is_same<typename std::remove_const<TExpr>::type, exprt>::value,
6163 " Tried to expr_try_dynamic_cast from something that wasn't an exprt" );
6264 static_assert (
6365 std::is_reference<T>::value,
6466 " Tried to convert exprt & to non-reference type" );
6567 static_assert (
66- std::is_base_of<exprt, TUnderlying >::value,
68+ std::is_base_of<exprt, TUnderlyingt >::value,
6769 " The template argument T must be derived from exprt." );
68- if (!can_cast_expr<TUnderlying >(base))
70+ if (!can_cast_expr<TUnderlyingt >(base))
6971 return {};
70- T value=static_cast <T>(base);
71- validate_expr (value);
72- return std::reference_wrapper<TConst>(value);
72+ T ret=static_cast <T>(base);
73+ validate_expr (ret);
74+ return std::reference_wrapper<TConstt>(ret);
75+ }
76+
77+ // / \brief Try to cast a reference to a generic exprt to a specific derived
78+ // / class
79+ // / \tparam T The reference or const reference type to \a TUnderlying to cast
80+ // / to
81+ // / \tparam TExpr The original type to cast from, either exprt or const exprt
82+ // / \param base Reference to a generic \ref exprt
83+ // / \return Reference to object of type \a TUnderlying
84+ // / or valueless optional if \a base is not an instance of \a TUnderlying
85+ template <typename T, typename TExpr>
86+ optionalt<std::reference_wrapper<typename std::remove_reference<T>::type>>
87+ expr_try_checked_cast (TExpr &base)
88+ {
89+ typedef typename std::decay<T>::type TUnderlyingt;
90+ PRECONDITION (can_cast_expr<TUnderlyingt>(base));
91+ return expr_try_checked_cast<T>(base);
7392}
7493
7594} // namespace detail
@@ -100,40 +119,79 @@ expr_try_dynamic_cast(exprt &base)
100119 return detail::expr_try_dynamic_cast<T>(base);
101120}
102121
122+ // / \brief Try to cast a constant reference to a generic exprt to a specific
123+ // / derived class. Also assert that the expr invariants are not violated.
124+ // / \tparam T The exprt-derived class to cast to
125+ // / \param base Reference to a generic \ref exprt
126+ // / \return Reference to object of type \a T or valueless optional if \a base
127+ // / is not an instance of \a T
128+ template <typename T>
129+ optionalt<std::reference_wrapper<typename std::remove_reference<T>::type>>
130+ expr_try_checked_cast (const exprt &base)
131+ {
132+ return detail::expr_try_checked_cast<T>(base);
133+ }
134+
135+ // / \brief Try to cast a reference to a generic exprt to a specific derived
136+ // / class. Also assert that the expr invariants are not violated.
137+ // / \tparam T The exprt-derived class to cast to
138+ // / \param base Reference to a generic \ref exprt
139+ // / \return Reference to object of type \a T or valueless optional if \a base is
140+ // / not an instance of \a T
141+ template <typename T>
142+ optionalt<std::reference_wrapper<typename std::remove_reference<T>::type>>
143+ expr_try_checked_cast (exprt &base)
144+ {
145+ return detail::expr_try_checked_cast<T>(base);
146+ }
147+
103148namespace detail // NOLINT
104149{
105150
106- // We hide this in a namespace so that only functions that it only
107- // participates in overload resolution when explicitly requested.
151+ // We hide these functions in a namespace so that only functions that they only
152+ // participate in overload resolution when explicitly requested.
108153
109- // / \brief Cast a reference to a generic exprt to a specific derived class
154+ // / \brief Cast a reference to a generic exprt to a specific derived class.
110155// / \tparam T The reference or const reference type to \a TUnderlying to cast to
111- // / \tparam TUnderlying An exprt-derived class type
112156// / \tparam TExpr The original type to cast from, either exprt or const exprt
113157// / \param base Reference to a generic \ref exprt
114158// / \return Reference to object of type \a T
115159// / \throw std::bad_cast If \a base is not an instance of \a TUnderlying
116- // / \remark If CBMC assertions (PRECONDITION) are set to abort then this will
117- // / abort rather than throw if \a base is not an instance of \a TUnderlying
118160template <typename T, typename TExpr>
119161T expr_dynamic_cast (TExpr &base)
120162{
121- typedef typename std::decay<T>::type TUnderlying ;
163+ typedef typename std::decay<T>::type TUnderlyingt ;
122164 static_assert (
123165 std::is_same<typename std::remove_const<TExpr>::type, exprt>::value,
124166 " Tried to expr_dynamic_cast from something that wasn't an exprt" );
125167 static_assert (
126168 std::is_reference<T>::value,
127169 " Tried to convert exprt & to non-reference type" );
128170 static_assert (
129- std::is_base_of<exprt, TUnderlying >::value,
171+ std::is_base_of<exprt, TUnderlyingt >::value,
130172 " The template argument T must be derived from exprt." );
131- PRECONDITION (can_cast_expr<TUnderlying>(base));
132- if (!can_cast_expr<TUnderlying>(base))
173+ if (!can_cast_expr<TUnderlyingt>(base))
133174 throw std::bad_cast ();
134- T value=static_cast <T>(base);
135- validate_expr (value);
136- return value;
175+ T ret=static_cast <T>(base);
176+ validate_expr (ret);
177+ return ret;
178+ }
179+
180+ // / \brief Cast a reference to a generic exprt to a specific derived class.
181+ // / Also assert that the expression has the expected type.
182+ // / \tparam T The reference or const reference type to \a TUnderlying to cast to
183+ // / \tparam TExpr The original type to cast from, either exprt or const exprt
184+ // / \param base Reference to a generic \ref exprt
185+ // / \return Reference to object of type \a T
186+ // / \throw std::bad_cast If \a base is not an instance of \a TUnderlying
187+ // / \remark If CBMC assertions (PRECONDITION) are set to abort then this will
188+ // / abort rather than throw if \a base is not an instance of \a TUnderlying
189+ template <typename T, typename TExpr>
190+ T expr_checked_cast (TExpr &base)
191+ {
192+ typedef typename std::decay<T>::type TUnderlyingt;
193+ PRECONDITION (can_cast_expr<TUnderlyingt>(base));
194+ return expr_dynamic_cast<T>(base);
137195}
138196
139197} // namespace detail
@@ -165,6 +223,34 @@ T expr_dynamic_cast(exprt &base)
165223 return detail::expr_dynamic_cast<T>(base);
166224}
167225
226+ // / \brief Cast a constant reference to a generic exprt to a specific derived
227+ // / class. Also assert that the exprt invariants are not violated.
228+ // / \tparam T The exprt-derived class to cast to
229+ // / \param base Reference to a generic \ref exprt
230+ // / \return Reference to object of type \a T
231+ // / \throw std::bad_cast If \a base is not an instance of \a T
232+ // / \remark If CBMC assertions (PRECONDITION) are set to abort then this will
233+ // / abort rather than throw if \a base is not an instance of \a T
234+ template <typename T>
235+ T expr_checked_cast (const exprt &base)
236+ {
237+ return detail::expr_checked_cast<T>(base);
238+ }
239+
240+ // / \brief Cast a reference to a generic exprt to a specific derived class.
241+ // / Also assert that the exprt invariants are not violated.
242+ // / \tparam T The exprt-derived class to cast to
243+ // / \param base Reference to a generic \ref exprt
244+ // / \return Reference to object of type \a T
245+ // / \throw std::bad_cast If \a base is not an instance of \a T
246+ // / \remark If CBMC assertions (PRECONDITION) are set to abort then this will
247+ // / abort rather than throw if \a base is not an instance of \a T
248+ template <typename T>
249+ T expr_checked_cast (exprt &base)
250+ {
251+ return detail::expr_checked_cast<T>(base);
252+ }
253+
168254inline void validate_operands (
169255 const exprt &value,
170256 exprt::operandst::size_type number,
0 commit comments