CBMC
simplify_expr_pointer.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
9 #include "simplify_expr_class.h"
10 
11 #include "arith_tools.h"
12 #include "c_types.h"
13 #include "expr_util.h"
14 #include "namespace.h"
15 #include "pointer_expr.h"
16 #include "pointer_offset_size.h"
17 #include "pointer_predicates.h"
18 #include "std_expr.h"
19 #include "string_constant.h"
20 
22  const exprt &expr,
23  mp_integer &address)
24 {
25  if(expr.id() == ID_dereference)
26  {
27  const auto &pointer = to_dereference_expr(expr).pointer();
28 
29  if(
30  pointer.id() == ID_typecast &&
31  to_typecast_expr(pointer).op().is_constant() &&
32  !to_integer(to_constant_expr(to_typecast_expr(pointer).op()), address))
33  {
34  return true;
35  }
36 
37  if(pointer.is_constant())
38  {
39  const constant_exprt &constant = to_constant_expr(pointer);
40 
41  if(constant.is_null_pointer())
42  {
43  address=0;
44  return true;
45  }
46  else if(!to_integer(constant, address))
47  return true;
48  }
49  }
50 
51  return false;
52 }
53 
56  const unary_exprt &expr)
57 {
58  const exprt &pointer = expr.op();
59  PRECONDITION(pointer.type().id() == ID_pointer);
60 
61  if(pointer.id() == ID_if)
62  {
63  if_exprt if_expr = lift_if(expr, 0);
64  return changed(simplify_if_preorder(if_expr));
65  }
66  else
67  {
68  auto r_it = simplify_rec(pointer); // recursive call
69  if(r_it.has_changed())
70  {
71  auto tmp = expr;
72  tmp.op() = r_it.expr;
73  return tmp;
74  }
75  }
76 
77  return unchanged(expr);
78 }
79 
82 {
83  if(expr.id()==ID_index)
84  {
85  auto new_index_expr = to_index_expr(expr);
86 
87  bool no_change = true;
88 
89  auto array_result = simplify_address_of_arg(new_index_expr.array());
90 
91  if(array_result.has_changed())
92  {
93  no_change = false;
94  new_index_expr.array() = array_result.expr;
95  }
96 
97  auto index_result = simplify_rec(new_index_expr.index());
98 
99  if(index_result.has_changed())
100  {
101  no_change = false;
102  new_index_expr.index() = index_result.expr;
103  }
104 
105  // rewrite (*(type *)int) [index] by
106  // pushing the index inside
107 
108  mp_integer address;
109  if(is_dereference_integer_object(new_index_expr.array(), address))
110  {
111  // push index into address
112  auto step_size = pointer_offset_size(new_index_expr.type(), ns);
113 
114  if(step_size.has_value())
115  {
116  const auto index = numeric_cast<mp_integer>(new_index_expr.index());
117 
118  if(index.has_value())
119  {
121  to_dereference_expr(new_index_expr.array()).pointer().type());
122  pointer_type.base_type() = new_index_expr.type();
123 
124  typecast_exprt typecast_expr(
125  from_integer((*step_size) * (*index) + address, c_index_type()),
126  pointer_type);
127 
128  return dereference_exprt{typecast_expr};
129  }
130  }
131  }
132 
133  if(!no_change)
134  return new_index_expr;
135  }
136  else if(expr.id()==ID_member)
137  {
138  auto new_member_expr = to_member_expr(expr);
139 
140  bool no_change = true;
141 
142  auto struct_op_result =
143  simplify_address_of_arg(new_member_expr.struct_op());
144 
145  if(struct_op_result.has_changed())
146  {
147  new_member_expr.struct_op() = struct_op_result.expr;
148  no_change = false;
149  }
150 
151  const typet &op_type = new_member_expr.struct_op().type();
152 
153  if(op_type.id() == ID_struct || op_type.id() == ID_struct_tag)
154  {
155  // rewrite NULL -> member by
156  // pushing the member inside
157 
158  mp_integer address;
159  if(is_dereference_integer_object(new_member_expr.struct_op(), address))
160  {
161  const struct_typet &struct_type =
162  op_type.id() == ID_struct_tag
163  ? ns.follow_tag(to_struct_tag_type(op_type))
164  : to_struct_type(op_type);
165  const irep_idt &member = to_member_expr(expr).get_component_name();
166  auto offset = member_offset(struct_type, member, ns);
167  if(offset.has_value())
168  {
170  to_dereference_expr(new_member_expr.struct_op()).pointer().type());
171  pointer_type.base_type() = new_member_expr.type();
172  typecast_exprt typecast_expr(
173  from_integer(address + *offset, c_index_type()), pointer_type);
174  return dereference_exprt{typecast_expr};
175  }
176  }
177  }
178 
179  if(!no_change)
180  return new_member_expr;
181  }
182  else if(expr.id()==ID_dereference)
183  {
184  auto new_expr = to_dereference_expr(expr);
185  auto r_pointer = simplify_rec(new_expr.pointer());
186  if(r_pointer.has_changed())
187  {
188  new_expr.pointer() = r_pointer.expr;
189  return std::move(new_expr);
190  }
191  }
192  else if(expr.id()==ID_if)
193  {
194  auto new_if_expr = to_if_expr(expr);
195 
196  bool no_change = true;
197 
198  auto r_cond = simplify_rec(new_if_expr.cond());
199  if(r_cond.has_changed())
200  {
201  new_if_expr.cond() = r_cond.expr;
202  no_change = false;
203  }
204 
205  auto true_result = simplify_address_of_arg(new_if_expr.true_case());
206  if(true_result.has_changed())
207  {
208  new_if_expr.true_case() = true_result.expr;
209  no_change = false;
210  }
211 
212  auto false_result = simplify_address_of_arg(new_if_expr.false_case());
213 
214  if(false_result.has_changed())
215  {
216  new_if_expr.false_case() = false_result.expr;
217  no_change = false;
218  }
219 
220  // condition is a constant?
221  if(new_if_expr.cond().is_true())
222  {
223  return new_if_expr.true_case();
224  }
225  else if(new_if_expr.cond().is_false())
226  {
227  return new_if_expr.false_case();
228  }
229 
230  if(!no_change)
231  return new_if_expr;
232  }
233 
234  return unchanged(expr);
235 }
236 
239 {
240  if(expr.type().id() != ID_pointer)
241  return unchanged(expr);
242 
243  auto new_object = simplify_address_of_arg(expr.object());
244 
245  if(new_object.expr.id() == ID_index)
246  {
247  auto index_expr = to_index_expr(new_object.expr);
248 
249  if(!index_expr.index().is_zero())
250  {
251  // we normalize &a[i] to (&a[0])+i
252  exprt offset = index_expr.op1();
253  index_expr.op1()=from_integer(0, offset.type());
254  auto new_address_of_expr = expr;
255  new_address_of_expr.object() = std::move(index_expr);
256  return plus_exprt(std::move(new_address_of_expr), offset);
257  }
258  }
259  else if(new_object.expr.id() == ID_dereference)
260  {
261  // simplify &*p to p
262  return to_dereference_expr(new_object.expr).pointer();
263  }
264 
265  if(new_object.has_changed())
266  {
267  auto new_expr = expr;
268  new_expr.object() = new_object;
269  return new_expr;
270  }
271  else
272  return unchanged(expr);
273 }
274 
277 {
278  const exprt &ptr = expr.pointer();
279 
280  if(ptr.type().id()!=ID_pointer)
281  return unchanged(expr);
282 
283  if(ptr.id()==ID_address_of)
284  {
285  auto offset = compute_pointer_offset(to_address_of_expr(ptr).object(), ns);
286 
287  if(offset.has_value())
288  return from_integer(*offset, expr.type());
289  }
290  else if(ptr.id()==ID_typecast) // pointer typecast
291  {
292  const auto &op = to_typecast_expr(ptr).op();
293  const typet &op_type = op.type();
294 
295  if(op_type.id()==ID_pointer)
296  {
297  // Cast from pointer to pointer.
298  // This just passes through, remove typecast.
299  auto new_expr = expr;
300  new_expr.op() = op;
301 
302  return changed(simplify_pointer_offset(new_expr)); // recursive call
303  }
304  else if(op_type.id()==ID_signedbv ||
305  op_type.id()==ID_unsignedbv)
306  {
307  // Cast from integer to pointer, say (int *)x.
308 
309  if(op.is_constant())
310  {
311  // (T *)0x1234 -> 0x1234
312  return changed(simplify_typecast(typecast_exprt{op, expr.type()}));
313  }
314  else
315  {
316  // We do a bit of special treatment for (TYPE *)(a+(int)&o),
317  // which is re-written to 'a'.
318 
319  typet type = expr.type();
320  exprt tmp = op;
321  if(tmp.id()==ID_plus && tmp.operands().size()==2)
322  {
323  const auto &plus_expr = to_plus_expr(tmp);
324 
325  if(
326  plus_expr.op0().id() == ID_typecast &&
327  to_typecast_expr(plus_expr.op0()).op().id() == ID_address_of)
328  {
329  auto new_expr =
330  typecast_exprt::conditional_cast(plus_expr.op1(), type);
331 
332  return changed(simplify_node(new_expr));
333  }
334  else if(
335  plus_expr.op1().id() == ID_typecast &&
336  to_typecast_expr(plus_expr.op1()).op().id() == ID_address_of)
337  {
338  auto new_expr =
339  typecast_exprt::conditional_cast(plus_expr.op0(), type);
340 
341  return changed(simplify_node(new_expr));
342  }
343  }
344  }
345  }
346  }
347  else if(ptr.id()==ID_plus) // pointer arithmetic
348  {
349  exprt::operandst ptr_expr;
350  exprt::operandst int_expr;
351 
352  for(const auto &op : ptr.operands())
353  {
354  if(op.type().id()==ID_pointer)
355  ptr_expr.push_back(op);
356  else if(!op.is_zero())
357  {
358  exprt tmp=op;
359  if(tmp.type()!=expr.type())
360  tmp = simplify_typecast(typecast_exprt(tmp, expr.type()));
361 
362  int_expr.push_back(tmp);
363  }
364  }
365 
366  if(ptr_expr.size()!=1 || int_expr.empty())
367  return unchanged(expr);
368 
369  typet pointer_base_type =
370  to_pointer_type(ptr_expr.front().type()).base_type();
371  if(pointer_base_type.id() == ID_empty)
372  pointer_base_type = char_type();
373 
374  auto element_size = pointer_offset_size(pointer_base_type, ns);
375 
376  if(!element_size.has_value())
377  return unchanged(expr);
378 
379  exprt pointer_offset_expr = simplify_pointer_offset(
380  pointer_offset_exprt(ptr_expr.front(), expr.type()));
381 
382  exprt sum;
383 
384  if(int_expr.size()==1)
385  sum=int_expr.front();
386  else
387  sum = simplify_plus(plus_exprt{int_expr, expr.type()});
388 
389  exprt size_expr = from_integer(*element_size, expr.type());
390 
391  exprt product = simplify_mult(mult_exprt{sum, size_expr});
392 
393  auto new_expr = plus_exprt(pointer_offset_expr, product);
394 
395  return changed(simplify_plus(new_expr));
396  }
397  else if(ptr.is_constant())
398  {
399  const constant_exprt &c_ptr = to_constant_expr(ptr);
400 
401  if(c_ptr.is_null_pointer())
402  {
403  return from_integer(0, expr.type());
404  }
405  }
406 
407  return unchanged(expr);
408 }
409 
411  const binary_relation_exprt &expr)
412 {
413  // the operands of the relation are both either one of
414  // a) an address_of_exprt
415  // b) a typecast_exprt with an address_of_exprt operand
416 
417  PRECONDITION(expr.id() == ID_equal || expr.id() == ID_notequal);
418 
419  // skip over the typecast
420  exprt tmp0 = skip_typecast(expr.op0());
421  PRECONDITION(tmp0.id() == ID_address_of);
422 
423  auto &tmp0_address_of = to_address_of_expr(tmp0);
424 
425  if(
426  tmp0_address_of.object().id() == ID_index &&
427  to_index_expr(tmp0_address_of.object()).index().is_zero())
428  {
429  tmp0_address_of =
430  address_of_exprt(to_index_expr(tmp0_address_of.object()).array());
431  }
432 
433  // skip over the typecast
434  exprt tmp1 = skip_typecast(expr.op1());
435  PRECONDITION(tmp1.id() == ID_address_of);
436 
437  auto &tmp1_address_of = to_address_of_expr(tmp1);
438 
439  if(
440  tmp1_address_of.object().id() == ID_index &&
441  to_index_expr(tmp1_address_of.object()).index().is_zero())
442  {
443  tmp1 = address_of_exprt(to_index_expr(tmp1_address_of.object()).array());
444  }
445 
446  const auto &tmp0_object = tmp0_address_of.object();
447  const auto &tmp1_object = tmp1_address_of.object();
448 
449  if(tmp0_object.id() == ID_symbol && tmp1_object.id() == ID_symbol)
450  {
451  bool equal = to_symbol_expr(tmp0_object).get_identifier() ==
452  to_symbol_expr(tmp1_object).get_identifier();
453 
454  return make_boolean_expr(expr.id() == ID_equal ? equal : !equal);
455  }
456  else if(
457  tmp0_object.id() == ID_dynamic_object &&
458  tmp1_object.id() == ID_dynamic_object)
459  {
460  bool equal = to_dynamic_object_expr(tmp0_object).get_instance() ==
461  to_dynamic_object_expr(tmp1_object).get_instance();
462 
463  return make_boolean_expr(expr.id() == ID_equal ? equal : !equal);
464  }
465  else if(
466  (tmp0_object.id() == ID_symbol && tmp1_object.id() == ID_dynamic_object) ||
467  (tmp0_object.id() == ID_dynamic_object && tmp1_object.id() == ID_symbol))
468  {
469  return make_boolean_expr(expr.id() != ID_equal);
470  }
471  else if(
472  tmp0_object.id() == ID_string_constant &&
473  tmp1_object.id() == ID_string_constant && tmp0_object == tmp1_object)
474  {
475  return make_boolean_expr(expr.id() == ID_equal);
476  }
477 
478  return unchanged(expr);
479 }
480 
482  const binary_relation_exprt &expr)
483 {
484  PRECONDITION(expr.id() == ID_equal || expr.id() == ID_notequal);
485  PRECONDITION(expr.is_boolean());
486 
487  exprt::operandst new_inequality_ops;
488  for(const auto &operand : expr.operands())
489  {
490  PRECONDITION(operand.id() == ID_pointer_object);
491  const exprt &op = to_pointer_object_expr(operand).pointer();
492 
493  if(op.id()==ID_address_of)
494  {
495  const auto &op_object = to_address_of_expr(op).object();
496 
497  if((op_object.id() != ID_symbol && op_object.id() != ID_dynamic_object &&
498  op_object.id() != ID_string_constant))
499  {
500  return unchanged(expr);
501  }
502  }
503  else if(!op.is_constant() || !op.is_zero())
504  {
505  return unchanged(expr);
506  }
507 
508  if(new_inequality_ops.empty())
509  new_inequality_ops.push_back(op);
510  else
511  {
512  new_inequality_ops.push_back(
514  op, new_inequality_ops.front().type())));
515  }
516  }
517 
518  auto new_expr = expr;
519 
520  new_expr.operands() = std::move(new_inequality_ops);
521 
522  return changed(simplify_inequality(new_expr));
523 }
524 
527 {
528  const exprt &op = expr.pointer();
529 
530  auto op_result = simplify_object(op);
531 
532  if(op_result.expr.id() == ID_if)
533  {
534  const if_exprt &if_expr = to_if_expr(op_result.expr);
535  exprt cond=if_expr.cond();
536 
537  auto p_o_false = expr;
538  p_o_false.op() = if_expr.false_case();
539 
540  auto p_o_true = expr;
541  p_o_true.op() = if_expr.true_case();
542 
543  auto new_expr = if_exprt(cond, p_o_true, p_o_false, expr.type());
544  return changed(simplify_rec(new_expr));
545  }
546 
547  if(op_result.has_changed())
548  {
549  auto new_expr = expr;
550  new_expr.op() = op_result;
551  return std::move(new_expr);
552  }
553  else
554  return unchanged(expr);
555 }
556 
559 {
560  auto new_expr = expr;
561  exprt &op = new_expr.op();
562 
563  bool no_change = true;
564 
565  auto op_result = simplify_object(op);
566 
567  if(op_result.has_changed())
568  {
569  op = op_result.expr;
570  no_change = false;
571  }
572 
573  // NULL is not dynamic
575  return false_exprt();
576 
577  // &something depends on the something
578  if(op.id() == ID_address_of)
579  {
580  const auto &op_object = to_address_of_expr(op).object();
581 
582  if(op_object.id() == ID_symbol)
583  {
584  const irep_idt identifier = to_symbol_expr(op_object).get_identifier();
585 
586  // this is for the benefit of symex
587  return make_boolean_expr(
588  identifier.starts_with(SYMEX_DYNAMIC_PREFIX "::"));
589  }
590  else if(op_object.id() == ID_string_constant)
591  {
592  return false_exprt();
593  }
594  else if(op_object.id() == ID_array)
595  {
596  return false_exprt();
597  }
598  }
599 
600  if(no_change)
601  return unchanged(expr);
602  else
603  return std::move(new_expr);
604 }
605 
608 {
609  auto new_expr = expr;
610  exprt &op = new_expr.op();
611  bool no_change = true;
612 
613  auto op_result = simplify_object(op);
614 
615  if(op_result.has_changed())
616  {
617  op = op_result.expr;
618  no_change = false;
619  }
620 
621  // NULL is not invalid
623  {
624  return false_exprt();
625  }
626 
627  // &anything is not invalid
628  if(op.id()==ID_address_of)
629  {
630  return false_exprt();
631  }
632 
633  if(no_change)
634  return unchanged(expr);
635  else
636  return std::move(new_expr);
637 }
638 
641 {
642  auto new_expr = expr;
643  bool no_change = true;
644  exprt &op = new_expr.pointer();
645  auto op_result = simplify_object(op);
646 
647  if(op_result.has_changed())
648  {
649  op = op_result.expr;
650  no_change = false;
651  }
652 
653  if(op.id() == ID_address_of)
654  {
655  const auto &op_object = to_address_of_expr(op).object();
656 
657  if(op_object.id() == ID_symbol)
658  {
659  // just get the type
660  auto size_opt = size_of_expr(op_object.type(), ns);
661 
662  if(size_opt.has_value())
663  {
664  const typet &expr_type = expr.type();
665  exprt size = size_opt.value();
666 
667  if(size.type() != expr_type)
668  size = simplify_typecast(typecast_exprt(size, expr_type));
669 
670  return size;
671  }
672  }
673  else if(op_object.id() == ID_string_constant)
674  {
675  typet type=expr.type();
676  return from_integer(
677  to_string_constant(op_object).value().size() + 1, type);
678  }
679  }
680 
681  if(no_change)
682  return unchanged(expr);
683  else
684  return std::move(new_expr);
685 }
686 
688  const prophecy_r_or_w_ok_exprt &expr)
689 {
690  exprt new_expr = simplify_rec(expr.lower(ns));
691  if(!new_expr.is_constant())
692  return unchanged(expr);
693  else
694  return std::move(new_expr);
695 }
696 
699 {
700  exprt new_expr = simplify_rec(expr.lower(ns));
701  if(!new_expr.is_constant())
702  return unchanged(expr);
703  else
704  return std::move(new_expr);
705 }
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
bool to_integer(const constant_exprt &expr, mp_integer &int_value)
Convert a constant expression expr to an arbitrary-precision integer.
Definition: arith_tools.cpp:20
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:235
bitvector_typet char_type()
Definition: c_types.cpp:106
bitvector_typet c_index_type()
Definition: c_types.cpp:16
Operator to return the address of an object.
Definition: pointer_expr.h:540
exprt & object()
Definition: pointer_expr.h:549
exprt & op1()
Definition: expr.h:136
exprt & op0()
Definition: expr.h:133
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition: std_expr.h:762
A constant literal expression.
Definition: std_expr.h:2990
bool is_null_pointer() const
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
Definition: std_expr.cpp:25
Operator to dereference a pointer.
Definition: pointer_expr.h:834
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
bool starts_with(const char *s) const
equivalent of as_string().starts_with(s)
Definition: dstring.h:95
unsigned int get_instance() const
Base class for all expressions.
Definition: expr.h:56
std::vector< exprt > operandst
Definition: expr.h:58
exprt & op1()
Definition: expr.h:136
bool is_boolean() const
Return whether the expression represents a Boolean.
Definition: expr.h:224
bool is_zero() const
Return whether the expression is a constant representing 0.
Definition: expr.cpp:47
typet & type()
Return the type of the expression.
Definition: expr.h:84
bool is_constant() const
Return whether the expression is a constant.
Definition: expr.h:212
operandst & operands()
Definition: expr.h:94
The Boolean constant false.
Definition: std_expr.h:3072
The trinary if-then-else operator.
Definition: std_expr.h:2370
exprt & true_case()
Definition: std_expr.h:2397
exprt & false_case()
Definition: std_expr.h:2407
exprt & cond()
Definition: std_expr.h:2387
exprt & array()
Definition: std_expr.h:1495
exprt & index()
Definition: std_expr.h:1505
const irep_idt & id() const
Definition: irep.h:388
irep_idt get_component_name() const
Definition: std_expr.h:2866
Binary multiplication Associativity is not specified.
Definition: std_expr.h:1107
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
Expression for finding the size (in bytes) of the object a pointer points to.
The plus expression Associativity is not specified.
Definition: std_expr.h:1002
A numerical identifier for the object a pointer points to.
The offset (in bytes) of a pointer relative to the object.
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
Definition: pointer_expr.h:24
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
pointer_in_range (see pointer_in_range_exprt) with prophecy expressions to encode whether a pointer r...
Definition: pointer_expr.h:453
exprt lower(const namespacet &ns) const
A base class for a predicate that indicates that an address range is ok to read or write or both.
exprt lower(const namespacet &ns) const
Lower an r_or_w_ok_exprt to arithmetic and logic expressions.
const namespacet & ns
resultt simplify_inequality_address_of(const binary_relation_exprt &)
resultt simplify_prophecy_r_or_w_ok(const prophecy_r_or_w_ok_exprt &)
Try to simplify prophecy_{r,w,rw}_ok to a constant expression.
static resultt changed(resultt<> result)
resultt simplify_unary_pointer_predicate_preorder(const unary_exprt &)
resultt simplify_address_of(const address_of_exprt &)
resultt simplify_node(const exprt &)
resultt simplify_prophecy_pointer_in_range(const prophecy_pointer_in_range_exprt &)
Try to simplify prophecy_pointer_in_range to a constant expression.
resultt simplify_rec(const exprt &)
resultt simplify_typecast(const typecast_exprt &)
resultt simplify_pointer_object(const pointer_object_exprt &)
resultt simplify_object(const exprt &)
resultt simplify_mult(const mult_exprt &)
resultt simplify_address_of_arg(const exprt &)
resultt simplify_inequality(const binary_relation_exprt &)
simplifies inequalities !=, <=, <, >=, >, and also ==
resultt simplify_inequality_pointer_object(const binary_relation_exprt &)
static resultt unchanged(exprt expr)
resultt simplify_is_invalid_pointer(const unary_exprt &)
resultt simplify_pointer_offset(const pointer_offset_exprt &)
resultt simplify_plus(const plus_exprt &)
resultt simplify_if_preorder(const if_exprt &expr)
resultt simplify_is_dynamic_object(const unary_exprt &)
resultt simplify_object_size(const object_size_exprt &)
Structure type, corresponds to C style structs.
Definition: std_types.h:231
const irep_idt & get_identifier() const
Definition: std_expr.h:160
Semantic type conversion.
Definition: std_expr.h:2068
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2076
The type of an expression, extends irept.
Definition: type.h:29
Generic base class for unary expressions.
Definition: std_expr.h:361
const exprt & op() const
Definition: std_expr.h:391
constant_exprt make_boolean_expr(bool value)
returns true_exprt if given true and false_exprt otherwise
Definition: expr_util.cpp:313
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
Definition: expr_util.cpp:193
if_exprt lift_if(const exprt &src, std::size_t operand_number)
lift up an if_exprt one level
Definition: expr_util.cpp:177
bool is_null_pointer(const constant_exprt &expr)
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
Definition: expr_util.cpp:344
Deprecated expression utility functions.
API to expression classes for Pointers.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
Definition: pointer_expr.h:890
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:93
const pointer_object_exprt & to_pointer_object_expr(const exprt &expr)
Cast an exprt to a pointer_object_exprt.
const dynamic_object_exprt & to_dynamic_object_expr(const exprt &expr)
Cast an exprt to a dynamic_object_exprt.
Definition: pointer_expr.h:315
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
Definition: pointer_expr.h:577
std::optional< mp_integer > compute_pointer_offset(const exprt &expr, const namespacet &ns)
std::optional< exprt > size_of_expr(const typet &type, const namespacet &ns)
std::optional< mp_integer > member_offset(const struct_typet &type, const irep_idt &member, const namespacet &ns)
std::optional< mp_integer > pointer_offset_size(const typet &type, const namespacet &ns)
Compute the size of a type in bytes, rounding up to full bytes.
Pointer Logic.
Various predicates over pointers in programs.
#define SYMEX_DYNAMIC_PREFIX
static bool is_dereference_integer_object(const exprt &expr, mp_integer &address)
BigInt mp_integer
Definition: smt_terms.h:17
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
API to expression classes.
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition: std_expr.h:2450
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition: std_expr.h:3045
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:272
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2102
const plus_exprt & to_plus_expr(const exprt &expr)
Cast an exprt to a plus_exprt.
Definition: std_expr.h:1041
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2936
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1533
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
Definition: std_types.h:29
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 string_constantt & to_string_constant(const exprt &expr)