CBMC
symex_dereference.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Symbolic Execution of ANSI-C
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "goto_symex.h"
13 
14 #include <util/arith_tools.h>
15 #include <util/byte_operators.h>
16 #include <util/c_types.h>
17 #include <util/exception_utils.h>
18 #include <util/expr_util.h>
19 #include <util/fresh_symbol.h>
20 #include <util/invariant.h>
22 
24 
25 #include "expr_skeleton.h"
26 #include "path_storage.h"
27 #include "symex_assign.h"
29 
44  const exprt &expr,
45  statet &state,
46  bool keep_array)
47 {
48  exprt result;
49 
50  if(expr.id()==ID_byte_extract_little_endian ||
51  expr.id()==ID_byte_extract_big_endian)
52  {
53  // address_of(byte_extract(op, offset, t)) is
54  // address_of(op) + offset with adjustments for arrays
55 
57 
58  // recursive call
59  result = address_arithmetic(be.op(), state, keep_array);
60 
61  if(be.op().type().id() == ID_array && result.id() == ID_address_of)
62  {
64 
65  // turn &a of type T[i][j] into &(a[0][0])
66  for(const typet *t = &(to_type_with_subtype(a.type()).subtype());
67  t->id() == ID_array && expr.type() != *t;
68  t = &(to_array_type(*t).element_type()))
70  }
71 
72  // do (expr.type() *)(((char *)op)+offset)
73  result=typecast_exprt(result, pointer_type(char_type()));
74 
75  // there could be further dereferencing in the offset
76  exprt offset=be.offset();
77  dereference_rec(offset, state, false, false);
78 
79  result=plus_exprt(result, offset);
80 
81  // treat &array as &array[0]
82  const typet &expr_type = expr.type();
83  typet dest_type_subtype;
84 
85  if(expr_type.id()==ID_array && !keep_array)
86  dest_type_subtype = to_array_type(expr_type).element_type();
87  else
88  dest_type_subtype=expr_type;
89 
90  result=typecast_exprt(result, pointer_type(dest_type_subtype));
91  }
92  else if(expr.id()==ID_index ||
93  expr.id()==ID_member)
94  {
96  ode.build(expr, ns);
97 
98  const byte_extract_exprt be =
99  make_byte_extract(ode.root_object(), ode.offset(), expr.type());
100 
101  // recursive call
102  result = address_arithmetic(be, state, keep_array);
103 
104  do_simplify(result);
105  }
106  else if(expr.id()==ID_dereference)
107  {
108  // ANSI-C guarantees &*p == p no matter what p is,
109  // even if it's complete garbage
110  // just grab the pointer, but be wary of further dereferencing
111  // in the pointer itself
112  result=to_dereference_expr(expr).pointer();
113  dereference_rec(result, state, false, false);
114  }
115  else if(expr.id()==ID_if)
116  {
117  if_exprt if_expr=to_if_expr(expr);
118 
119  // the condition is not an address
120  dereference_rec(if_expr.cond(), state, false, false);
121 
122  // recursive call
123  if_expr.true_case() =
124  address_arithmetic(if_expr.true_case(), state, keep_array);
125  if_expr.false_case() =
126  address_arithmetic(if_expr.false_case(), state, keep_array);
127 
128  result=if_expr;
129  }
130  else if(expr.id()==ID_symbol ||
131  expr.id()==ID_string_constant ||
132  expr.id()==ID_label ||
133  expr.id()==ID_array)
134  {
135  // give up, just dereference
136  result=expr;
137  dereference_rec(result, state, false, false);
138 
139  // turn &array into &array[0]
140  if(result.type().id() == ID_array && !keep_array)
141  result = index_exprt(result, from_integer(0, c_index_type()));
142 
143  // handle field-sensitive SSA symbol
144  mp_integer offset=0;
145  if(is_ssa_expr(expr))
146  {
147  auto offset_opt = compute_pointer_offset(expr, ns);
148  PRECONDITION(offset_opt.has_value());
149  offset = *offset_opt;
150  }
151 
152  if(offset>0)
153  {
155  to_ssa_expr(expr).get_l1_object(),
156  from_integer(offset, c_index_type()),
157  expr.type());
158 
159  result = address_arithmetic(be, state, keep_array);
160 
161  do_simplify(result);
162  }
163  else
164  result=address_of_exprt(result);
165  }
166  else if(expr.id() == ID_typecast)
167  {
168  const typecast_exprt &tc_expr = to_typecast_expr(expr);
169 
170  result = address_arithmetic(tc_expr.op(), state, keep_array);
171 
172  // treat &array as &array[0]
173  const typet &expr_type = expr.type();
174  typet dest_type_subtype;
175 
176  if(expr_type.id() == ID_array && !keep_array)
177  dest_type_subtype = to_array_type(expr_type).element_type();
178  else
179  dest_type_subtype = expr_type;
180 
181  result = typecast_exprt(result, pointer_type(dest_type_subtype));
182  }
183  else
185  "goto_symext::address_arithmetic does not handle " + expr.id_string());
186 
187  const typet &expr_type = expr.type();
188  INVARIANT(
189  (expr_type.id() == ID_array && !keep_array) ||
190  pointer_type(expr_type) == result.type(),
191  "either non-persistent array or pointer to result");
192 
193  return result;
194 }
195 
197 goto_symext::cache_dereference(exprt &dereference_result, statet &state)
198 {
199  auto const cache_key = [&] {
200  auto cache_key =
201  state.field_sensitivity.apply(ns, state, dereference_result, false);
202  if(auto let_expr = expr_try_dynamic_cast<let_exprt>(dereference_result))
203  {
204  let_expr->value() = state.rename<L2>(let_expr->value(), ns).get();
205  }
206  else
207  {
208  cache_key = state.rename<L2>(cache_key, ns).get();
209  }
210  return cache_key;
211  }();
212 
213  if(auto cached = state.dereference_cache.find(cache_key))
214  {
215  return *cached;
216  }
217 
218  auto const &cache_symbol = get_fresh_aux_symbol(
219  cache_key.type(),
220  "symex",
221  "dereference_cache",
222  dereference_result.source_location(),
224  ns,
225  state.symbol_table);
226 
227  // we need to lift possible lets
228  // (come from the value set to avoid repeating complex pointer comparisons)
229  auto cache_value = cache_key;
230  lift_lets(state, cache_value);
231 
232  auto assign = symex_assignt{
234 
235  auto cache_symbol_expr = cache_symbol.symbol_expr();
236  assign.assign_symbol(
237  to_ssa_expr(state.rename<L1>(cache_symbol_expr, ns).get()),
238  expr_skeletont{},
239  cache_value,
240  {});
241 
242  state.dereference_cache.insert(cache_key, cache_symbol_expr);
243  return cache_symbol_expr;
244 }
245 
258  exprt &expr,
259  statet &state,
260  bool write,
261  bool is_in_quantifier)
262 {
263  if(expr.id()==ID_dereference)
264  {
265  bool expr_is_not_null = false;
266 
267  if(state.threads.size() == 1)
268  {
269  const irep_idt &expr_function = state.source.function_id;
270  if(!expr_function.empty())
271  {
272  const dereference_exprt to_check =
274 
275  expr_is_not_null = path_storage.safe_pointers.at(expr_function)
276  .is_safe_dereference(to_check, state.source.pc);
277  }
278  }
279 
280  exprt tmp1;
281  tmp1.swap(to_dereference_expr(expr).pointer());
282 
283  // first make sure there are no dereferences in there
284  dereference_rec(tmp1, state, false, is_in_quantifier);
285 
286  // Depending on the nature of the pointer expression, the recursive deref
287  // operation might have introduced a construct such as
288  // (x == &o1 ? o1 : o2).field, in which case we should simplify to push the
289  // member operator inside the if, then apply field-sensitivity to yield
290  // (x == &o1 ? o1..field : o2..field). value_set_dereferencet can then
291  // apply the dereference operation to each of o1..field and o2..field
292  // independently, as it special-cases the ternary conditional operator.
293  // There may also be index operators in tmp1 which can now be resolved to
294  // constant array cell references, so we replace symbols with constants
295  // first, hoping for a transformation such as
296  // (x == &o1 ? o1 : o2)[idx] =>
297  // (x == &o1 ? o1 : o2)[2] =>
298  // (x == &o1 ? o1[[2]] : o2[[2]])
299  // Note we don't L2 rename non-constant symbols at this point, because the
300  // value-set works in terms of L1 names and we don't want to ask it to
301  // dereference an L2 pointer, which it would not have an entry for.
302 
303  tmp1 = state.rename<L1_WITH_CONSTANT_PROPAGATION>(tmp1, ns).get();
304 
305  do_simplify(tmp1);
306 
308  {
309  // make sure simplify has not re-introduced any dereferencing that
310  // had previously been cleaned away
311  INVARIANT(
312  !has_subexpr(tmp1, ID_dereference),
313  "simplify re-introduced dereferencing");
314  }
315 
316  tmp1 = state.field_sensitivity.apply(ns, state, std::move(tmp1), false);
317 
318  // we need to set up some elaborate call-backs
319  symex_dereference_statet symex_dereference_state(state, ns);
320 
322  ns,
323  state.symbol_table,
324  symex_dereference_state,
326  expr_is_not_null,
327  log);
328 
329  // std::cout << "**** " << format(tmp1) << '\n';
330  exprt tmp2 =
331  dereference.dereference(tmp1, symex_config.show_points_to_sets);
332  // std::cout << "**** " << format(tmp2) << '\n';
333 
334 
335  // this may yield a new auto-object
336  trigger_auto_object(tmp2, state);
337 
338  // Check various conditions for when we should try to cache the expression.
339  // 1. Caching dereferences must be enabled.
340  // 2. Do not cache inside LHS of writes.
341  // 3. Do not cache inside quantifiers (references variables outside their
342  // scope).
343  // 4. Only cache "complicated" expressions, i.e. of the form
344  // [let p = <expr> in ]
345  // (p == &something ? something : ...))
346  // Otherwise we should just return it unchanged.
347  if(
348  symex_config.cache_dereferences && !write && !is_in_quantifier &&
349  (tmp2.id() == ID_if || tmp2.id() == ID_let))
350  {
351  expr = cache_dereference(tmp2, state);
352  }
353  else
354  {
355  expr = std::move(tmp2);
356  }
357  }
358  else if(
359  expr.id() == ID_index && to_index_expr(expr).array().id() == ID_member &&
360  to_array_type(to_index_expr(expr).array().type()).size().is_zero())
361  {
362  // This is an expression of the form x.a[i],
363  // where a is a zero-sized array. This gets
364  // re-written into *(&x.a+i)
365 
366  index_exprt index_expr=to_index_expr(expr);
367 
368  address_of_exprt address_of_expr(index_expr.array());
369  address_of_expr.type()=pointer_type(expr.type());
370 
371  dereference_exprt tmp{plus_exprt{address_of_expr, index_expr.index()}};
373 
374  // recursive call
375  dereference_rec(tmp, state, write, is_in_quantifier);
376 
377  expr.swap(tmp);
378  }
379  else if(expr.id()==ID_index &&
380  to_index_expr(expr).array().type().id()==ID_pointer)
381  {
382  // old stuff, will go away
383  UNREACHABLE;
384  }
385  else if(expr.id()==ID_address_of)
386  {
387  address_of_exprt &address_of_expr=to_address_of_expr(expr);
388 
389  exprt &object=address_of_expr.object();
390 
391  expr = address_arithmetic(
392  object, state, to_pointer_type(expr.type()).base_type().id() == ID_array);
393  }
394  else if(expr.id()==ID_typecast)
395  {
396  exprt &tc_op=to_typecast_expr(expr).op();
397 
398  // turn &array into &array[0] when casting to pointer-to-element-type
399  if(
400  tc_op.id() == ID_address_of &&
401  to_address_of_expr(tc_op).object().type().id() == ID_array &&
402  expr.type() ==
403  pointer_type(to_array_type(to_address_of_expr(tc_op).object().type())
404  .element_type()))
405  {
407  to_address_of_expr(tc_op).object(), from_integer(0, c_index_type())));
408 
409  dereference_rec(expr, state, write, is_in_quantifier);
410  }
411  else
412  {
413  dereference_rec(tc_op, state, write, is_in_quantifier);
414  }
415  }
416  else
417  {
418  bool is_quantifier = expr.id() == ID_forall || expr.id() == ID_exists;
419  Forall_operands(it, expr)
420  dereference_rec(*it, state, write, is_in_quantifier || is_quantifier);
421  }
422 }
423 
424 static exprt
425 apply_to_objects_in_dereference(exprt e, const std::function<exprt(exprt)> &f)
426 {
427  if(auto deref = expr_try_dynamic_cast<dereference_exprt>(e))
428  {
429  deref->op() = f(std::move(deref->op()));
430  return *deref;
431  }
432 
433  for(auto &sub : e.operands())
434  sub = apply_to_objects_in_dereference(std::move(sub), f);
435  return e;
436 }
437 
475 void goto_symext::dereference(exprt &expr, statet &state, bool write)
476 {
477  PRECONDITION(!state.call_stack().empty());
478 
479  // Symbols whose address is taken need to be renamed to level 1
480  // in order to distinguish addresses of local variables
481  // from different frames.
482  expr = apply_to_objects_in_dereference(std::move(expr), [&](exprt e) {
483  return state.field_sensitivity.apply(
484  ns, state, state.rename<L1>(std::move(e), ns).get(), false);
485  });
486 
487  // start the recursion!
488  dereference_rec(expr, state, write, false);
489  // dereferencing may introduce new symbol_exprt
490  // (like __CPROVER_memory)
491  expr = state.rename<L1>(std::move(expr), ns).get();
492 
493  // Dereferencing is likely to introduce new member-of-if constructs --
494  // for example, "x->field" may have become "(x == &o1 ? o1 : o2).field."
495  // Run expression simplification, which converts that to
496  // (x == &o1 ? o1.field : o2.field))
497  // before applying field sensitivity. Field sensitivity can then turn such
498  // field-of-symbol expressions into atomic SSA expressions instead of having
499  // to rewrite all of 'o1' otherwise.
500  // Even without field sensitivity this can be beneficial: for example,
501  // "(b ? s1 : s2).member := X" results in
502  // (b ? s1 : s2) := (b ? s1 : s2) with (member := X)
503  // and then
504  // s1 := b ? ((b ? s1 : s2) with (member := X)) : s1
505  // when all we need is
506  // s1 := s1 with (member := X) [and guard b]
507  // s2 := s2 with (member := X) [and guard !b]
508  do_simplify(expr);
509 
511  {
512  // make sure simplify has not re-introduced any dereferencing that
513  // had previously been cleaned away
514  INVARIANT(
515  !has_subexpr(expr, ID_dereference),
516  "simplify re-introduced dereferencing");
517  }
518 
519  expr = state.field_sensitivity.apply(ns, state, std::move(expr), write);
520 }
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
exception_utils.h
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
pointer_offset_size.h
goto_statet::dereference_cache
sharing_mapt< exprt, symbol_exprt, false, irep_hash > dereference_cache
This is used for eliminating repeated complicated dereferences.
Definition: goto_state.h:43
make_byte_extract
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.
Definition: byte_operators.cpp:48
goto_symext::cache_dereference
symbol_exprt cache_dereference(exprt &dereference_result, statet &state)
Definition: symex_dereference.cpp:197
L2
@ L2
Definition: renamed.h:26
has_subexpr
bool has_subexpr(const exprt &expr, const std::function< bool(const exprt &)> &pred)
returns true if the expression has a subexpression that satisfies pred
Definition: expr_util.cpp:139
mp_integer
BigInt mp_integer
Definition: smt_terms.h:17
symex_assign.h
Forall_operands
#define Forall_operands(it, expr)
Definition: expr.h:27
arith_tools.h
object_descriptor_exprt::build
void build(const exprt &expr, const namespacet &ns)
Given an expression expr, attempt to find the underlying object it represents by skipping over type c...
Definition: pointer_expr.cpp:107
address_of_exprt::object
exprt & object()
Definition: pointer_expr.h:380
L1
@ L1
Definition: renamed.h:24
to_dereference_expr
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
Definition: pointer_expr.h:716
typet
The type of an expression, extends irept.
Definition: type.h:28
goto_symext::address_arithmetic
exprt address_arithmetic(const exprt &, statet &, bool keep_array)
Transforms an lvalue expression by replacing any dereference operations it contains with explicit ref...
Definition: symex_dereference.cpp:43
fresh_symbol.h
symex_targett::sourcet::pc
goto_programt::const_targett pc
Definition: symex_target.h:42
expr_skeleton.h
to_byte_extract_expr
const byte_extract_exprt & to_byte_extract_expr(const exprt &expr)
Definition: byte_operators.h:57
to_index_expr
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1478
to_if_expr
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition: std_expr.h:2403
goto_symext::target
symex_target_equationt & target
The equation that this execution is building up.
Definition: goto_symex.h:251
value_set_dereference.h
dereference_exprt
Operator to dereference a pointer.
Definition: pointer_expr.h:659
goto_symext::path_storage
path_storaget & path_storage
Symbolic execution paths to be resumed later.
Definition: goto_symex.h:788
symex_configt::cache_dereferences
bool cache_dereferences
Whether or not to replace multiple occurrences of the same dereference with a single symbol that cont...
Definition: symex_config.h:62
goto_symex_statet
Central data structure: state.
Definition: goto_symex_state.h:41
unsupported_operation_exceptiont
Thrown when we encounter an instruction, parameters to an instruction etc.
Definition: exception_utils.h:144
if_exprt
The trinary if-then-else operator.
Definition: std_expr.h:2322
object_descriptor_exprt
Split an expression into a base object and a (byte) offset.
Definition: pointer_expr.h:166
invariant.h
to_type_with_subtype
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:193
plus_exprt
The plus expression Associativity is not specified.
Definition: std_expr.h:946
exprt
Base class for all expressions.
Definition: expr.h:55
goto_symex_statet::source
symex_targett::sourcet source
Definition: goto_symex_state.h:61
symex_assignt
Functor for symex assignment.
Definition: symex_assign.h:25
goto_symext::trigger_auto_object
void trigger_auto_object(const exprt &, statet &)
Definition: auto_objects.cpp:77
symex_dereference_state.h
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
field_sensitivityt::apply
exprt apply(const namespacet &ns, goto_symex_statet &state, exprt expr, bool write) const
Turn an expression expr into a field-sensitive SSA expression.
Definition: field_sensitivity.cpp:32
path_storage.h
Storage of symbolic execution paths to resume.
if_exprt::false_case
exprt & false_case()
Definition: std_expr.h:2360
object_descriptor_exprt::root_object
static const exprt & root_object(const exprt &expr)
Definition: pointer_expr.cpp:168
symex_targett::assignment_typet::STATE
@ STATE
goto_symext::log
messaget log
The messaget to write log messages to.
Definition: goto_symex.h:263
compute_pointer_offset
optionalt< mp_integer > compute_pointer_offset(const exprt &expr, const namespacet &ns)
Definition: pointer_offset_size.cpp:507
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
goto_symex_statet::threads
std::vector< threadt > threads
Definition: goto_symex_state.h:196
byte_operators.h
Expression classes for byte-level operators.
is_ssa_expr
bool is_ssa_expr(const exprt &expr)
Definition: ssa_expr.h:125
goto_symex_statet::call_stack
call_stackt & call_stack()
Definition: goto_symex_state.h:144
symex_configt::show_points_to_sets
bool show_points_to_sets
Definition: symex_config.h:47
to_ssa_expr
const ssa_exprt & to_ssa_expr(const exprt &expr)
Cast a generic exprt to an ssa_exprt.
Definition: ssa_expr.h:145
goto_symext::dereference
virtual void dereference(exprt &, statet &, bool write)
Replace all dereference operations within expr with explicit references to the objects they may refer...
Definition: symex_dereference.cpp:475
goto_symex_statet::symbol_table
symbol_tablet symbol_table
contains symbols that are minted during symbolic execution, such as dynamically created objects etc.
Definition: goto_symex_state.h:66
byte_extract_exprt::op
exprt & op()
Definition: byte_operators.h:43
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
dereference_exprt::pointer
exprt & pointer()
Definition: pointer_expr.h:673
goto_symex_statet::rename
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...
Definition: goto_symex_state.cpp:169
goto_symex.h
goto_symext::dereference_rec
void dereference_rec(exprt &expr, statet &state, bool write, bool is_in_quantifier)
If expr is a dereference_exprt, replace it with explicit references to the objects it may point to.
Definition: symex_dereference.cpp:257
symex_dereference_statet
Callback object that goto_symext::dereference_rec provides to value_set_dereferencet to provide value...
Definition: symex_dereference_state.h:24
irept::id_string
const std::string & id_string() const
Definition: irep.h:399
to_pointer_type
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:79
index_exprt::index
exprt & index()
Definition: std_expr.h:1450
pointer_type
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:253
index_exprt::array
exprt & array()
Definition: std_expr.h:1440
irept::swap
void swap(irept &irep)
Definition: irep.h:442
get_original_name
exprt get_original_name(exprt expr)
Undo all levels of renaming.
Definition: renaming_level.cpp:157
irept::id
const irep_idt & id() const
Definition: irep.h:396
dstringt::empty
bool empty() const
Definition: dstring.h:88
unary_exprt::op
const exprt & op() const
Definition: std_expr.h:326
L1_WITH_CONSTANT_PROPAGATION
@ L1_WITH_CONSTANT_PROPAGATION
Definition: renamed.h:25
goto_symext::do_simplify
virtual void do_simplify(exprt &expr)
Definition: goto_symex.cpp:34
sharing_mapt::insert
void insert(const key_type &k, valueU &&m)
Insert element, element must not exist in map.
Definition: sharing_map.h:1348
goto_symex_statet::field_sensitivity
field_sensitivityt field_sensitivity
Definition: goto_symex_state.h:121
char_type
bitvector_typet char_type()
Definition: c_types.cpp:124
byte_extract_exprt::offset
exprt & offset()
Definition: byte_operators.h:44
value_set_dereferencet
Wrapper for a function dereferencing pointer expressions using a value set.
Definition: value_set_dereference.h:22
goto_symext::ns
namespacet ns
Initialized just before symbolic execution begins, to point to both outer_symbol_table and the symbol...
Definition: goto_symex.h:243
expr_util.h
Deprecated expression utility functions.
apply_to_objects_in_dereference
static exprt apply_to_objects_in_dereference(exprt e, const std::function< exprt(exprt)> &f)
Definition: symex_dereference.cpp:425
if_exprt::true_case
exprt & true_case()
Definition: std_expr.h:2350
goto_symext::language_mode
irep_idt language_mode
language_mode: ID_java, ID_C or another language identifier if we know the source language in use,...
Definition: goto_symex.h:226
path_storaget::safe_pointers
std::unordered_map< irep_idt, local_safe_pointerst > safe_pointers
Map function identifiers to local_safe_pointerst instances.
Definition: path_storage.h:100
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:100
to_typecast_expr
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2051
if_exprt::cond
exprt & cond()
Definition: std_expr.h:2340
goto_symext::lift_lets
void lift_lets(statet &, exprt &)
Execute any let expressions in expr using symex_assignt::assign_symbol.
Definition: symex_clean_expr.cpp:198
goto_symext::symex_config
const symex_configt symex_config
The configuration to use for this symbolic execution.
Definition: goto_symex.h:170
pointer_typet::base_type
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
byte_extract_exprt
Expression of type type extracted from some object op starting at position offset (given in number of...
Definition: byte_operators.h:28
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
type_with_subtypet::subtype
const typet & subtype() const
Definition: type.h:172
to_address_of_expr
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
Definition: pointer_expr.h:408
exprt::operands
operandst & operands()
Definition: expr.h:94
index_exprt
Array index operator.
Definition: std_expr.h:1409
address_of_exprt
Operator to return the address of an object.
Definition: pointer_expr.h:370
exprt::add_source_location
source_locationt & add_source_location()
Definition: expr.h:216
symex_configt::run_validation_checks
bool run_validation_checks
Should the additional validation checks be run? If this flag is set the checks for renaming (both lev...
Definition: symex_config.h:42
typecast_exprt
Semantic type conversion.
Definition: std_expr.h:2016
symex_targett::sourcet::function_id
irep_idt function_id
Definition: symex_target.h:39
c_index_type
bitvector_typet c_index_type()
Definition: c_types.cpp:16
exprt::source_location
const source_locationt & source_location() const
Definition: expr.h:211
c_types.h
get_fresh_aux_symbol
symbolt & get_fresh_aux_symbol(const typet &type, const std::string &name_prefix, const std::string &basename_prefix, const source_locationt &source_location, const irep_idt &symbol_mode, const namespacet &ns, symbol_table_baset &symbol_table)
Installs a fresh-named symbol with respect to the given namespace ns with the requested name pattern ...
Definition: fresh_symbol.cpp:32
expr_skeletont
Expression in which some part is missing and can be substituted for another expression.
Definition: expr_skeleton.h:25
validation_modet::INVARIANT
@ INVARIANT
sharing_mapt::find
optionalt< std::reference_wrapper< const mapped_type > > find(const key_type &k) const
Find element.
Definition: sharing_map.h:1451
array_typet::element_type
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:785
object_descriptor_exprt::offset
exprt & offset()
Definition: pointer_expr.h:209