CBMC
Loading...
Searching...
No Matches
field_sensitivity.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Field-sensitive SSA
4
5Author: Michael Tautschnig
6
7\*******************************************************************/
8
9#include "field_sensitivity.h"
10
11#include <util/arith_tools.h>
12#include <util/byte_operators.h>
13#include <util/c_types.h>
15
16#include "goto_symex_state.h"
18#include "symex_target.h"
19
20#define ENABLE_ARRAY_FIELD_SENSITIVITY
21
23 const namespacet &ns,
24 goto_symex_statet &state,
26 bool write) const
27{
28 if(write)
29 return std::move(ssa_expr);
30 else
31 return get_fields(ns, state, ssa_expr, true);
32}
33
35 const namespacet &ns,
36 goto_symex_statet &state,
38 bool write) const
39{
40 if(be.op().type().id() != ID_union && be.op().type().id() != ID_union_tag)
41 return be;
42
43 // For non-constant offsets, decompose through the widest union member so
44 // that field sensitivity can process the resulting struct/array expression.
45 // This avoids materialising the full union as a flat bitvector in the SMT
46 // encoding. The operand need not be an SSA expression (e.g., it may be an
47 // index into an array of unions when array field sensitivity is disabled).
48 if(!be.offset().is_constant())
49 {
50 const union_typet &union_type =
51 be.op().type().id() == ID_union_tag
52 ? ns.follow_tag(to_union_tag_type(be.op().type()))
53 : to_union_type(be.op().type());
54
56 const auto widest = union_type.find_widest_union_component(ns);
57 if(
58 widest.has_value() && union_size.has_value() &&
59 widest->second == *union_size)
60 {
62 be.id(),
63 member_exprt{be.op(), widest->first.get_name(), widest->first.type()},
64 be.offset(),
65 be.get_bits_per_byte(),
66 be.type()};
67 return apply(ns, state, std::move(new_be), write);
68 }
69
70 return be;
71 }
72
73 if(!is_ssa_expr(be.op()))
74 return be;
75
76 const union_typet &type = be.op().type().id() == ID_union_tag
77 ? ns.follow_tag(to_union_tag_type(be.op().type()))
78 : to_union_type(be.op().type());
79 for(const auto &comp : type.components())
80 {
82 bool was_l2 = !tmp.get_level_2().empty();
83 tmp.remove_level_2();
84 const member_exprt member{tmp.get_original_expr(), comp};
85 auto recursive_member =
86 get_subexpression_at_offset(member, be.offset(), be.type(), ns);
87 if(!recursive_member.has_value())
88 continue;
89
90 // We need to inspect the access path as the resulting expression may
91 // involve index expressions. When array field sensitivity is disabled
92 // or the size of the array that is indexed into is larger than
93 // max_field_sensitivity_array_size then only the expression up to (but
94 // excluding) said index expression can be turned into an ssa_exprt.
97 exprt *parent = for_ssa;
98 while(parent->id() == ID_typecast)
99 parent = &to_typecast_expr(*parent).op();
100 while(parent->id() == ID_member || parent->id() == ID_index)
101 {
102 if(parent->id() == ID_member)
103 {
104 parent = &to_member_expr(*parent).compound();
105 }
106 else
107 {
108 parent = &to_index_expr(*parent).array();
109#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
110 if(
111 !to_array_type(parent->type()).size().is_constant() ||
113 to_constant_expr(to_array_type(parent->type()).size())) >
115 {
116 for_ssa = parent;
117 }
118#else
119 for_ssa = parent;
120#endif // ENABLE_ARRAY_FIELD_SENSITIVITY
121 }
122 }
123
124 if(for_ssa->id() == ID_index || for_ssa->id() == ID_member)
125 {
126 tmp.type() = for_ssa->type();
127 tmp.set_expression(*for_ssa);
128 if(was_l2)
129 {
130 *for_ssa =
131 apply(ns, state, state.rename(std::move(tmp), ns).get(), write);
132 }
133 else
134 *for_ssa = apply(ns, state, std::move(tmp), write);
135
136 return full_exprt;
137 }
138 else if(for_ssa->id() == ID_typecast)
139 {
140 if(was_l2)
141 {
142 *for_ssa = apply(ns, state, state.rename(*for_ssa, ns).get(), write);
143 }
144 else
145 *for_ssa = apply(ns, state, std::move(*for_ssa), write);
146
147 return full_exprt;
148 }
149 }
150
151 return be;
152}
153
155 const namespacet &ns,
156 goto_symex_statet &state,
157 exprt expr,
158 bool write) const
159{
160 if(expr.id() != ID_address_of)
161 {
162 Forall_operands(it, expr)
163 *it = apply(ns, state, std::move(*it), write);
164 }
165
166 if(!write && is_ssa_expr(expr))
167 {
168 return get_fields(ns, state, to_ssa_expr(expr), true);
169 }
170 else if(
171 !write && expr.id() == ID_member &&
172 to_member_expr(expr).struct_op().id() == ID_struct)
173 {
174 return simplify_opt(std::move(expr), state.value_set, ns);
175 }
176#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
177 else if(
178 !write && expr.id() == ID_index &&
179 to_index_expr(expr).array().id() == ID_array)
180 {
181 return simplify_opt(std::move(expr), state.value_set, ns);
182 }
183#endif // ENABLE_ARRAY_FIELD_SENSITIVITY
184 else if(expr.id() == ID_member)
185 {
186 // turn a member-of-an-SSA-expression into a single SSA expression, thus
187 // encoding the member as an individual symbol rather than only the full
188 // struct
189 member_exprt &member = to_member_expr(expr);
190
191 if(
192 is_ssa_expr(member.struct_op()) &&
193 (member.struct_op().type().id() == ID_struct ||
194 member.struct_op().type().id() == ID_struct_tag ||
195 member.struct_op().type().id() == ID_union ||
196 member.struct_op().type().id() == ID_union_tag))
197 {
198 // place the entire member expression, not just the struct operand, in an
199 // SSA expression
201 bool was_l2 = !tmp.get_level_2().empty();
202
203 tmp.remove_level_2();
204 member.struct_op() = tmp.get_original_expr();
205 tmp.set_expression(member);
206 if(was_l2)
207 return apply(ns, state, state.rename(std::move(tmp), ns).get(), write);
208 else
209 return apply(ns, state, std::move(tmp), write);
210 }
211 }
212 else if(
213 !write && (expr.id() == ID_byte_extract_little_endian ||
215 {
216 return apply_byte_extract(ns, state, to_byte_extract_expr(expr), write);
217 }
218#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
219 else if(expr.id() == ID_index)
220 {
221 // turn a index-of-an-SSA-expression into a single SSA expression, thus
222 // encoding the index access into an array as an individual symbol rather
223 // than only the full array
224 index_exprt &index = to_index_expr(expr);
226 {
228 .simplify(index.index());
229 }
230
231 if(
232 is_ssa_expr(index.array()) && index.array().type().id() == ID_array &&
233 index.index().is_constant())
234 {
235 // place the entire index expression, not just the array operand, in an
236 // SSA expression
237 ssa_exprt tmp = to_ssa_expr(index.array());
238 auto l2_index = state.rename(index.index(), ns).get();
240 {
242 .simplify(l2_index);
243 }
244 bool was_l2 = !tmp.get_level_2().empty();
245 exprt l2_size =
246 state.rename(to_array_type(index.array().type()).size(), ns).get();
247 if(l2_size.is_nil() && index.array().id() == ID_symbol)
248 {
249 // In case the array type was incomplete, attempt to retrieve it from
250 // the symbol table.
252 to_symbol_expr(index.array()).identifier());
253 if(array_from_symbol_table != nullptr)
255 }
256
257 if(
258 l2_size.is_constant() &&
261 {
262 if(l2_index.is_constant())
263 {
264 // place the entire index expression, not just the array operand,
265 // in an SSA expression
267 ssa_array.remove_level_2();
268 index.array() = ssa_array.get_original_expr();
269 index.index() = l2_index;
270 tmp.set_expression(index);
271 if(was_l2)
272 {
273 return apply(
274 ns, state, state.rename(std::move(tmp), ns).get(), write);
275 }
276 else
277 return apply(ns, state, std::move(tmp), write);
278 }
279 else if(!write)
280 {
281 // Expand the array and return `{array[0]; array[1]; ...}[index]`
283 get_fields(ns, state, to_ssa_expr(index.array()), true);
284 return index_exprt{std::move(expanded_array), index.index()};
285 }
286 }
287 }
288 }
289#endif // ENABLE_ARRAY_FIELD_SENSITIVITY
290 return expr;
291}
292
294 const namespacet &ns,
295 goto_symex_statet &state,
296 const ssa_exprt &ssa_expr,
297 bool disjoined_fields_only) const
298{
299 if(
300 ssa_expr.type().id() == ID_struct ||
301 ssa_expr.type().id() == ID_struct_tag ||
302 (!disjoined_fields_only && (ssa_expr.type().id() == ID_union ||
303 ssa_expr.type().id() == ID_union_tag)))
304 {
305 const struct_union_typet::componentst &components =
306 (ssa_expr.type().id() == ID_struct_tag ||
307 ssa_expr.type().id() == ID_union_tag)
309 .components()
310 : to_struct_union_type(ssa_expr.type()).components();
311
312 exprt::operandst fields;
313 fields.reserve(components.size());
314
315 const exprt &compound_op = ssa_expr.get_original_expr();
316
317 for(const auto &comp : components)
318 {
320 bool was_l2 = !tmp.get_level_2().empty();
321 tmp.remove_level_2();
322 tmp.set_expression(
323 member_exprt{compound_op, comp.get_name(), comp.type()});
325 if(was_l2)
326 {
327 fields.emplace_back(state.rename(std::move(field), ns).get());
328 }
329 else
330 fields.emplace_back(std::move(field));
331 }
332
333 if(
334 disjoined_fields_only && (ssa_expr.type().id() == ID_struct ||
335 ssa_expr.type().id() == ID_struct_tag))
336 {
337 return struct_exprt{std::move(fields), ssa_expr.type()};
338 }
339 else
340 return field_sensitive_ssa_exprt{ssa_expr, std::move(fields)};
341 }
342#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
343 else if(
344 ssa_expr.type().id() == ID_array &&
345 to_array_type(ssa_expr.type()).size().is_constant())
346 {
348 to_constant_expr(to_array_type(ssa_expr.type()).size()));
350 return ssa_expr;
351
352 const array_typet &type = to_array_type(ssa_expr.type());
354
355 array_exprt::operandst elements;
356 elements.reserve(array_size);
357
358 const exprt &array = ssa_expr.get_original_expr();
359
360 for(std::size_t i = 0; i < array_size; ++i)
361 {
362 const index_exprt index(array, from_integer(i, type.index_type()));
364 bool was_l2 = !tmp.get_level_2().empty();
365 tmp.remove_level_2();
366 tmp.set_expression(index);
367 exprt element = get_fields(ns, state, tmp, disjoined_fields_only);
368 if(was_l2)
369 {
370 elements.emplace_back(state.rename(std::move(element), ns).get());
371 }
372 else
373 elements.emplace_back(std::move(element));
374 }
375
377 return array_exprt(std::move(elements), type);
378 else
379 return field_sensitive_ssa_exprt{ssa_expr, std::move(elements)};
380 }
381#endif // ENABLE_ARRAY_FIELD_SENSITIVITY
382 else
383 return ssa_expr;
384}
385
387 const namespacet &ns,
388 goto_symex_statet &state,
389 const ssa_exprt &lhs,
390 const exprt &rhs,
391 symex_targett &target,
392 bool allow_pointer_unsoundness) const
393{
394 const exprt lhs_fs = get_fields(ns, state, lhs, false);
395
396 if(lhs != lhs_fs)
397 {
399 ns, state, lhs_fs, rhs, target, allow_pointer_unsoundness);
400 // Erase the composite symbol from our working state. Note that we need to
401 // have it in the propagation table and the value set while doing the field
402 // assignments, thus we cannot skip putting it in there above.
403 if(is_divisible(lhs, true))
404 {
405 state.propagation.erase_if_exists(lhs.identifier());
406 state.value_set.erase_symbol(lhs, ns);
407 }
408 }
409}
410
422 const namespacet &ns,
423 goto_symex_statet &state,
424 const exprt &lhs_fs,
425 const exprt &ssa_rhs,
426 symex_targett &target,
427 bool allow_pointer_unsoundness) const
428{
430 {
432 const ssa_exprt ssa_lhs =
433 state
434 .assignment(l1_lhs, ssa_rhs, ns, true, true, allow_pointer_unsoundness)
435 .get();
436
437 // do the assignment
438 target.assignment(
439 state.guard.as_expr(),
440 ssa_lhs,
441 ssa_lhs,
442 ssa_lhs.get_original_expr(),
443 ssa_rhs,
444 state.source,
446 // Erase the composite symbol from our working state. Note that we need to
447 // have it in the propagation table and the value set while doing the field
448 // assignments, thus we cannot skip putting it in there above.
449 if(is_divisible(l1_lhs, true))
450 {
451 state.propagation.erase_if_exists(l1_lhs.identifier());
452 state.value_set.erase_symbol(l1_lhs, ns);
453 }
454 }
455 else if(
456 ssa_rhs.type().id() == ID_struct || ssa_rhs.type().id() == ID_struct_tag)
457 {
458 const struct_typet &type =
459 ssa_rhs.type().id() == ID_struct_tag
460 ? ns.follow_tag(to_struct_tag_type(ssa_rhs.type()))
461 : to_struct_type(ssa_rhs.type());
462 const struct_union_typet::componentst &components = type.components();
463
465 components.empty() ||
466 (lhs_fs.has_operands() && lhs_fs.operands().size() == components.size()));
467
468 exprt::operandst::const_iterator fs_it = lhs_fs.operands().begin();
469 for(const auto &comp : components)
470 {
471 const exprt member_rhs = apply(
472 ns,
473 state,
475 member_exprt{ssa_rhs, comp.get_name(), comp.type()},
476 state.value_set,
477 ns),
478 false);
479
480 const exprt &member_lhs = *fs_it;
481 if(
482 auto fs_ssa =
484 {
486 ns,
487 state,
488 fs_ssa->get_object_ssa(),
490 target,
491 allow_pointer_unsoundness);
492 }
493
495 ns, state, member_lhs, member_rhs, target, allow_pointer_unsoundness);
496 ++fs_it;
497 }
498 }
499 else if(
500 ssa_rhs.type().id() == ID_union || ssa_rhs.type().id() == ID_union_tag)
501 {
502 const union_typet &type =
503 ssa_rhs.type().id() == ID_union_tag
504 ? ns.follow_tag(to_union_tag_type(ssa_rhs.type()))
505 : to_union_type(ssa_rhs.type());
506 const struct_union_typet::componentst &components = type.components();
507
509 components.empty() ||
510 (lhs_fs.has_operands() && lhs_fs.operands().size() == components.size()));
511
512 exprt::operandst::const_iterator fs_it = lhs_fs.operands().begin();
513 for(const auto &comp : components)
514 {
515 const exprt member_rhs = apply(
516 ns,
517 state,
520 ssa_rhs, from_integer(0, c_index_type()), comp.type()),
521 state.value_set,
522 ns),
523 false);
524
525 const exprt &member_lhs = *fs_it;
526 if(
527 auto fs_ssa =
529 {
531 ns,
532 state,
533 fs_ssa->get_object_ssa(),
535 target,
536 allow_pointer_unsoundness);
537 }
538
540 ns, state, member_lhs, member_rhs, target, allow_pointer_unsoundness);
541 ++fs_it;
542 }
543 }
544#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
545 else if(const auto &type = type_try_dynamic_cast<array_typet>(ssa_rhs.type()))
546 {
547 const std::size_t array_size =
549 PRECONDITION(lhs_fs.operands().size() == array_size);
550
552 return;
553
554 exprt::operandst::const_iterator fs_it = lhs_fs.operands().begin();
555 for(std::size_t i = 0; i < array_size; ++i)
556 {
557 const exprt index_rhs = apply(
558 ns,
559 state,
561 index_exprt{ssa_rhs, from_integer(i, type->index_type())},
562 state.value_set,
563 ns),
564 false);
565
566 const exprt &index_lhs = *fs_it;
567 if(
568 auto fs_ssa =
570 {
572 ns,
573 state,
574 fs_ssa->get_object_ssa(),
575 index_rhs,
576 target,
577 allow_pointer_unsoundness);
578 }
579
581 ns, state, index_lhs, index_rhs, target, allow_pointer_unsoundness);
582 ++fs_it;
583 }
584 }
585#endif // ENABLE_ARRAY_FIELD_SENSITIVITY
586 else if(lhs_fs.has_operands())
587 {
589 ssa_rhs.has_operands() &&
590 lhs_fs.operands().size() == ssa_rhs.operands().size());
591
592 exprt::operandst::const_iterator fs_it = lhs_fs.operands().begin();
593 for(const exprt &op : ssa_rhs.operands())
594 {
596 {
598 ns,
599 state,
600 fs_ssa->get_object_ssa(),
601 op,
602 target,
603 allow_pointer_unsoundness);
604 }
605
607 ns, state, *fs_it, op, target, allow_pointer_unsoundness);
608 ++fs_it;
609 }
610 }
611 else
612 {
614 }
615}
616
618 const ssa_exprt &expr,
619 bool disjoined_fields_only) const
620{
621 if(expr.type().id() == ID_struct || expr.type().id() == ID_struct_tag)
622 return true;
623
624#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
625 if(
626 expr.type().id() == ID_array &&
627 to_array_type(expr.type()).size().is_constant() &&
630 {
631 return true;
632 }
633#endif
634
635 if(
637 (expr.type().id() == ID_union || expr.type().id() == ID_union_tag))
638 {
639 return true;
640 }
641
642 return false;
643}
644
646 exprt e,
647 const value_sett &value_set,
648 const namespacet &ns) const
649{
650 if(!should_simplify)
651 return e;
652
653 simplify_expr_with_value_sett{value_set, language_mode, ns}.simplify(e);
654 return e;
655}
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
byte_extract_exprt make_byte_extract(const exprt &_op, const exprt &_offset, const typet &_type)
Construct a byte_extract_exprt with endianness and byte width matching the current configuration.
Expression classes for byte-level operators.
const byte_extract_exprt & to_byte_extract_expr(const exprt &expr)
bitvector_typet c_index_type()
Definition c_types.cpp:16
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition c_types.h:184
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition c_types.h:224
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
Array constructor from list of elements.
Definition std_expr.h:1570
Arrays with given size.
Definition std_types.h:807
typet index_type() const
The type of the index expressions into any instance of this type.
Definition std_types.cpp:34
Expression of type type extracted from some object op starting at position offset (given in number of...
Base class for all expressions.
Definition expr.h:57
std::vector< exprt > operandst
Definition expr.h:59
bool has_operands() const
Return true if there is at least one operand.
Definition expr.h:92
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:213
typet & type()
Return the type of the expression.
Definition expr.h:85
operandst & operands()
Definition expr.h:95
exprt simplify_opt(exprt e, const value_sett &value_set, const namespacet &ns) const
exprt apply_byte_extract(const namespacet &ns, goto_symex_statet &state, const byte_extract_exprt &expr, bool write) const
Turn an expression expr into a field-sensitive SSA expression.
const std::size_t max_field_sensitivity_array_size
exprt get_fields(const namespacet &ns, goto_symex_statet &state, const ssa_exprt &ssa_expr, bool disjoined_fields_only) const
Compute an expression representing the individual components of a field-sensitive SSA representation ...
void field_assignments_rec(const namespacet &ns, goto_symex_statet &state, const exprt &lhs_fs, const exprt &ssa_rhs, symex_targett &target, bool allow_pointer_unsoundness) const
Assign to the individual fields lhs_fs of a non-expanded symbol lhs.
exprt apply(const namespacet &ns, goto_symex_statet &state, exprt expr, bool write) const
Turn an expression expr into a field-sensitive SSA expression.
void field_assignments(const namespacet &ns, goto_symex_statet &state, const ssa_exprt &lhs, const exprt &rhs, symex_targett &target, bool allow_pointer_unsoundness) const
Assign to the individual fields of a non-expanded symbol lhs.
const irep_idt & language_mode
bool is_divisible(const ssa_exprt &expr, bool disjoined_fields_only) const
Determine whether expr would translate to an atomic SSA expression (returns false) or a composite obj...
guardt guard
Definition goto_state.h:58
sharing_mapt< irep_idt, exprt > propagation
Definition goto_state.h:71
value_sett value_set
Uses level 1 names, and is used to do dereferencing.
Definition goto_state.h:51
Central data structure: state.
renamedt< ssa_exprt, L2 > assignment(ssa_exprt lhs, const exprt &rhs, const namespacet &ns, bool rhs_is_simplified, bool record_value, bool allow_pointer_unsoundness=false)
renamedt< exprt, level > rename(exprt expr, const namespacet &ns)
Rewrites symbol expressions in exprt, applying a suffix to each symbol reflecting its most recent ver...
symex_targett::sourcet source
exprt as_expr() const
Definition guard_expr.h:46
Array index operator.
Definition std_expr.h:1431
exprt & index()
Definition std_expr.h:1471
exprt & array()
Definition std_expr.h:1461
const irep_idt & id() const
Definition irep.h:388
Extract member of struct or union.
Definition std_expr.h:2866
const exprt & struct_op() const
Definition std_expr.h:2904
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition namespace.cpp:49
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
const symbol_table_baset & get_symbol_table() const
Return first symbol table registered with the namespace.
Definition namespace.h:123
Expression providing an SSA-renamed symbol of expressions.
Definition ssa_expr.h:17
const exprt & get_original_expr() const
Definition ssa_expr.h:33
Struct constructor from list of elements.
Definition std_expr.h:1820
Structure type, corresponds to C style structs.
Definition std_types.h:231
const componentst & components() const
Definition std_types.h:147
std::vector< componentt > componentst
Definition std_types.h:140
void identifier(const irep_idt &identifier)
Definition std_expr.h:160
Symbol table entry.
Definition symbol.h:28
The interface of the target container for symbolic execution to record its symbolic steps into.
virtual void assignment(const exprt &guard, const ssa_exprt &ssa_lhs, const exprt &ssa_full_lhs, const exprt &original_full_lhs, const exprt &ssa_rhs, const sourcet &source, assignment_typet assignment_type)=0
Write to a local variable.
The union type.
Definition c_types.h:147
State type in value_set_domaint, used in value-set analysis and goto-symex.
Definition value_set.h:43
void erase_symbol(const symbol_exprt &symbol_expr, const namespacet &ns)
#define Forall_operands(it, expr)
Definition expr.h:28
Symbolic Execution.
std::optional< exprt > get_subexpression_at_offset(const exprt &expr, const mp_integer &offset_bytes, const typet &target_type_raw, const namespacet &ns)
std::optional< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
Pointer Logic.
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define PRECONDITION(CONDITION)
Definition invariant.h:463
bool is_ssa_expr(const exprt &expr)
Definition ssa_expr.h:125
const ssa_exprt & to_ssa_expr(const exprt &expr)
Cast a generic exprt to an ssa_exprt.
Definition ssa_expr.h:145
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1494
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2024
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:2953
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3078
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:221
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:308
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition std_types.h:518
const struct_or_union_tag_typet & to_struct_or_union_tag_type(const typet &type)
Cast a typet to a struct_or_union_tag_typet.
Definition std_types.h:478
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition std_types.h:214
Generate Equation using Symbolic Execution.
ssize_t write(int fildes, const void *buf, size_t nbyte)
Definition unistd.c:195