30
30
// / \return true if \a base is of type \a T
31
31
template <typename T> bool can_cast_expr (const exprt &base);
32
32
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
34
34
// / 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.
36
39
inline void validate_expr (const exprt &) {}
37
40
38
41
namespace detail // NOLINT
39
42
{
40
43
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.
43
46
44
47
// / \brief Try to cast a reference to a generic exprt to a specific derived
45
48
// / class
46
49
// / \tparam T The reference or const reference type to \a TUnderlying to cast
47
50
// / to
48
- // / \tparam TUnderlying An exprt-derived class type
49
51
// / \tparam TExpr The original type to cast from, either exprt or const exprt
50
52
// / \param base Reference to a generic \ref exprt
51
53
// / \return Reference to object of type \a TUnderlying
@@ -54,22 +56,39 @@ template <typename T, typename TExpr>
54
56
optionalt<std::reference_wrapper<typename std::remove_reference<T>::type>>
55
57
expr_try_dynamic_cast (TExpr &base)
56
58
{
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 ;
59
61
static_assert (
60
62
std::is_same<typename std::remove_const<TExpr>::type, exprt>::value,
61
63
" Tried to expr_try_dynamic_cast from something that wasn't an exprt" );
62
64
static_assert (
63
65
std::is_reference<T>::value,
64
66
" Tried to convert exprt & to non-reference type" );
65
67
static_assert (
66
- std::is_base_of<exprt, TUnderlying >::value,
68
+ std::is_base_of<exprt, TUnderlyingt >::value,
67
69
" The template argument T must be derived from exprt." );
68
- if (!can_cast_expr<TUnderlying >(base))
70
+ if (!can_cast_expr<TUnderlyingt >(base))
69
71
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);
73
92
}
74
93
75
94
} // namespace detail
@@ -100,40 +119,79 @@ expr_try_dynamic_cast(exprt &base)
100
119
return detail::expr_try_dynamic_cast<T>(base);
101
120
}
102
121
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
+
103
148
namespace detail // NOLINT
104
149
{
105
150
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.
108
153
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.
110
155
// / \tparam T The reference or const reference type to \a TUnderlying to cast to
111
- // / \tparam TUnderlying An exprt-derived class type
112
156
// / \tparam TExpr The original type to cast from, either exprt or const exprt
113
157
// / \param base Reference to a generic \ref exprt
114
158
// / \return Reference to object of type \a T
115
159
// / \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
118
160
template <typename T, typename TExpr>
119
161
T expr_dynamic_cast (TExpr &base)
120
162
{
121
- typedef typename std::decay<T>::type TUnderlying ;
163
+ typedef typename std::decay<T>::type TUnderlyingt ;
122
164
static_assert (
123
165
std::is_same<typename std::remove_const<TExpr>::type, exprt>::value,
124
166
" Tried to expr_dynamic_cast from something that wasn't an exprt" );
125
167
static_assert (
126
168
std::is_reference<T>::value,
127
169
" Tried to convert exprt & to non-reference type" );
128
170
static_assert (
129
- std::is_base_of<exprt, TUnderlying >::value,
171
+ std::is_base_of<exprt, TUnderlyingt >::value,
130
172
" 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))
133
174
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);
137
195
}
138
196
139
197
} // namespace detail
@@ -165,6 +223,34 @@ T expr_dynamic_cast(exprt &base)
165
223
return detail::expr_dynamic_cast<T>(base);
166
224
}
167
225
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
+
168
254
inline void validate_operands (
169
255
const exprt &value,
170
256
exprt::operandst::size_type number,
0 commit comments