CBMC
bv_pointers.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 "bv_pointers.h"
10 
11 #include <util/arith_tools.h>
12 #include <util/byte_operators.h>
13 #include <util/c_types.h>
14 #include <util/config.h>
15 #include <util/exception_utils.h>
16 #include <util/expr_util.h>
17 #include <util/namespace.h>
18 #include <util/pointer_expr.h>
21 
27 {
28 public:
30  const typet &type,
31  bool little_endian,
32  const namespacet &_ns,
33  const boolbv_widtht &_boolbv_width)
34  : endianness_mapt(_ns), boolbv_width(_boolbv_width)
35  {
36  build(type, little_endian);
37  }
38 
39 protected:
41 
42  void build_little_endian(const typet &type) override;
43  void build_big_endian(const typet &type) override;
44 };
45 
47 {
48  const auto &width_opt = boolbv_width.get_width_opt(src);
49  if(!width_opt.has_value())
50  return;
51 
52  const std::size_t new_size = map.size() + *width_opt;
53  map.reserve(new_size);
54 
55  for(std::size_t i = map.size(); i < new_size; ++i)
56  map.push_back(i);
57 }
58 
60 {
61  if(src.id() == ID_pointer)
63  else
65 }
66 
68 bv_pointerst::endianness_map(const typet &type, bool little_endian) const
69 {
70  return bv_endianness_mapt{type, little_endian, ns, bv_width};
71 }
72 
74 {
75  // not actually type-dependent for now
77 }
78 
79 std::size_t bv_pointerst::get_offset_width(const pointer_typet &type) const
80 {
81  const std::size_t pointer_width = type.get_width();
82  const std::size_t object_width = get_object_width(type);
83  PRECONDITION(pointer_width >= object_width);
84  return pointer_width - object_width;
85 }
86 
87 std::size_t bv_pointerst::get_address_width(const pointer_typet &type) const
88 {
89  return type.get_width();
90 }
91 
93  const
94 {
95  const std::size_t offset_width = get_offset_width(type);
96  const std::size_t object_width = get_object_width(type);
97  PRECONDITION(bv.size() >= offset_width + object_width);
98 
99  return bvt(
100  bv.begin() + offset_width, bv.begin() + offset_width + object_width);
101 }
102 
104  const
105 {
106  const std::size_t offset_width = get_offset_width(type);
107  PRECONDITION(bv.size() >= offset_width);
108 
109  return bvt(bv.begin(), bv.begin() + offset_width);
110 }
111 
112 bvt bv_pointerst::object_offset_encoding(const bvt &object, const bvt &offset)
113 {
114  bvt result;
115  result.reserve(offset.size() + object.size());
116  result.insert(result.end(), offset.begin(), offset.end());
117  result.insert(result.end(), object.begin(), object.end());
118 
119  return result;
120 }
121 
123 {
124  PRECONDITION(expr.type().id() == ID_bool);
125 
126  const exprt::operandst &operands=expr.operands();
127 
128  if(expr.id() == ID_is_invalid_pointer)
129  {
130  if(operands.size()==1 &&
131  operands[0].type().id()==ID_pointer)
132  {
133  const bvt &bv=convert_bv(operands[0]);
134 
135  if(!bv.empty())
136  {
137  const pointer_typet &type = to_pointer_type(operands[0].type());
138  bvt object_bv = object_literals(bv, type);
139 
140  bvt invalid_bv = object_literals(
141  encode(pointer_logic.get_invalid_object(), type), type);
142 
143  const std::size_t object_bits = get_object_width(type);
144 
145  bvt equal_invalid_bv;
146  equal_invalid_bv.reserve(object_bits);
147 
148  for(std::size_t i=0; i<object_bits; i++)
149  {
150  equal_invalid_bv.push_back(prop.lequal(object_bv[i], invalid_bv[i]));
151  }
152 
153  return prop.land(equal_invalid_bv);
154  }
155  }
156  }
157  else if(expr.id() == ID_is_dynamic_object)
158  {
159  if(operands.size()==1 &&
160  operands[0].type().id()==ID_pointer)
161  {
162  // we postpone
164 
165  postponed_list.emplace_back(bvt{1, l}, convert_bv(operands[0]), expr);
166 
167  return l;
168  }
169  }
170  else if(expr.id()==ID_lt || expr.id()==ID_le ||
171  expr.id()==ID_gt || expr.id()==ID_ge)
172  {
173  if(operands.size()==2 &&
174  operands[0].type().id()==ID_pointer &&
175  operands[1].type().id()==ID_pointer)
176  {
177  const bvt &bv0=convert_bv(operands[0]);
178  const bvt &bv1=convert_bv(operands[1]);
179 
180  const pointer_typet &type0 = to_pointer_type(operands[0].type());
181  bvt offset_bv0 = offset_literals(bv0, type0);
182 
183  const pointer_typet &type1 = to_pointer_type(operands[1].type());
184  bvt offset_bv1 = offset_literals(bv1, type1);
185 
186  // Comparison over pointers to distinct objects is undefined behavior in
187  // C; we choose to always produce "false" in such a case. Alternatively,
188  // we could do a comparison over the integer representation of a pointer
189 
190  // do the same-object-test via an expression as this may permit re-using
191  // already cached encodings of the equality test
192  const exprt same_object = ::same_object(operands[0], operands[1]);
193  const literalt same_object_lit = convert(same_object);
194  if(same_object_lit.is_false())
195  return same_object_lit;
196 
197  return prop.land(
198  same_object_lit,
199  bv_utils.rel(
200  offset_bv0,
201  expr.id(),
202  offset_bv1,
204  }
205  }
206 
207  return SUB::convert_rest(expr);
208 }
209 
211  const namespacet &_ns,
212  propt &_prop,
213  message_handlert &message_handler,
214  bool get_array_constraints)
215  : boolbvt(_ns, _prop, message_handler, get_array_constraints),
216  pointer_logic(_ns)
217 {
218 }
219 
221 {
222  if(expr.id()==ID_symbol)
223  {
224  return add_addr(expr);
225  }
226  else if(expr.id()==ID_label)
227  {
228  return add_addr(expr);
229  }
230  else if(expr.id() == ID_null_object)
231  {
232  pointer_typet pt = pointer_type(expr.type());
233  return encode(pointer_logic.get_null_object(), pt);
234  }
235  else if(expr.id()==ID_index)
236  {
237  const index_exprt &index_expr=to_index_expr(expr);
238  const exprt &array=index_expr.array();
239  const exprt &index=index_expr.index();
240  const auto &array_type = to_array_type(array.type());
241 
242  pointer_typet type = pointer_type(expr.type());
243  const std::size_t bits = boolbv_width(type);
244 
245  bvt bv;
246 
247  // recursive call
248  if(array_type.id()==ID_pointer)
249  {
250  // this should be gone
251  bv=convert_pointer_type(array);
252  CHECK_RETURN(bv.size()==bits);
253  }
254  else if(array_type.id()==ID_array ||
255  array_type.id()==ID_string_constant)
256  {
257  auto bv_opt = convert_address_of_rec(array);
258  if(!bv_opt.has_value())
259  return {};
260  bv = std::move(*bv_opt);
261  CHECK_RETURN(bv.size()==bits);
262  }
263  else
264  UNREACHABLE;
265 
266  // get size
267  auto size = pointer_offset_size(array_type.element_type(), ns);
268  CHECK_RETURN(size.has_value() && *size >= 0);
269 
270  bv = offset_arithmetic(type, bv, *size, index);
271  CHECK_RETURN(bv.size()==bits);
272 
273  return std::move(bv);
274  }
275  else if(expr.id()==ID_byte_extract_little_endian ||
276  expr.id()==ID_byte_extract_big_endian)
277  {
278  const auto &byte_extract_expr=to_byte_extract_expr(expr);
279 
280  // recursive call
281  auto bv_opt = convert_address_of_rec(byte_extract_expr.op());
282  if(!bv_opt.has_value())
283  return {};
284 
285  pointer_typet type = pointer_type(expr.type());
286  const std::size_t bits = boolbv_width(type);
287  CHECK_RETURN(bv_opt->size() == bits);
288 
289  bvt bv = offset_arithmetic(type, *bv_opt, 1, byte_extract_expr.offset());
290  CHECK_RETURN(bv.size()==bits);
291  return std::move(bv);
292  }
293  else if(expr.id()==ID_member)
294  {
295  const member_exprt &member_expr=to_member_expr(expr);
296  const exprt &struct_op = member_expr.compound();
297  const typet &struct_op_type=ns.follow(struct_op.type());
298 
299  // recursive call
300  auto bv_opt = convert_address_of_rec(struct_op);
301  if(!bv_opt.has_value())
302  return {};
303 
304  bvt bv = std::move(*bv_opt);
305  if(struct_op_type.id()==ID_struct)
306  {
307  auto offset = member_offset(
308  to_struct_type(struct_op_type), member_expr.get_component_name(), ns);
309  CHECK_RETURN(offset.has_value());
310 
311  // add offset
312  pointer_typet type = pointer_type(expr.type());
313  bv = offset_arithmetic(type, bv, *offset);
314  }
315  else
316  {
317  INVARIANT(
318  struct_op_type.id() == ID_union,
319  "member expression should operate on struct or union");
320  // nothing to do, all members have offset 0
321  }
322 
323  return std::move(bv);
324  }
325  else if(expr.id()==ID_constant ||
326  expr.id()==ID_string_constant ||
327  expr.id()==ID_array)
328  { // constant
329  return add_addr(expr);
330  }
331  else if(expr.id()==ID_if)
332  {
333  const if_exprt &ifex=to_if_expr(expr);
334 
335  literalt cond=convert(ifex.cond());
336 
337  bvt bv1, bv2;
338 
339  auto bv1_opt = convert_address_of_rec(ifex.true_case());
340  if(!bv1_opt.has_value())
341  return {};
342 
343  auto bv2_opt = convert_address_of_rec(ifex.false_case());
344  if(!bv2_opt.has_value())
345  return {};
346 
347  return bv_utils.select(cond, *bv1_opt, *bv2_opt);
348  }
349 
350  return {};
351 }
352 
354 {
355  const pointer_typet &type = to_pointer_type(expr.type());
356 
357  const std::size_t bits = boolbv_width(expr.type());
358 
359  if(expr.id()==ID_symbol)
360  {
361  const irep_idt &identifier=to_symbol_expr(expr).get_identifier();
362 
363  return map.get_literals(identifier, type, bits);
364  }
365  else if(expr.id()==ID_nondet_symbol)
366  {
367  return prop.new_variables(bits);
368  }
369  else if(expr.id()==ID_typecast)
370  {
371  const typecast_exprt &typecast_expr = to_typecast_expr(expr);
372 
373  const exprt &op = typecast_expr.op();
374  const typet &op_type = op.type();
375 
376  if(op_type.id()==ID_pointer)
377  return convert_bv(op);
378  else if(
379  can_cast_type<bitvector_typet>(op_type) || op_type.id() == ID_bool ||
380  op_type.id() == ID_c_enum || op_type.id() == ID_c_enum_tag)
381  {
382  // Cast from a bitvector type to pointer.
383  // We just do a zero extension.
384 
385  const bvt &op_bv=convert_bv(op);
386 
387  return bv_utils.zero_extension(op_bv, bits);
388  }
389  }
390  else if(expr.id()==ID_if)
391  {
392  return SUB::convert_if(to_if_expr(expr));
393  }
394  else if(expr.id()==ID_index)
395  {
396  return SUB::convert_index(to_index_expr(expr));
397  }
398  else if(expr.id()==ID_member)
399  {
400  return SUB::convert_member(to_member_expr(expr));
401  }
402  else if(expr.id()==ID_address_of)
403  {
404  const address_of_exprt &address_of_expr = to_address_of_expr(expr);
405 
406  auto bv_opt = convert_address_of_rec(address_of_expr.op());
407  if(!bv_opt.has_value())
408  return conversion_failed(address_of_expr);
409 
410  CHECK_RETURN(bv_opt->size() == bits);
411  return *bv_opt;
412  }
413  else if(expr.id()==ID_constant)
414  {
415  const constant_exprt &c = to_constant_expr(expr);
416 
417  if(is_null_pointer(c))
418  return encode(pointer_logic.get_null_object(), type);
419  else
420  {
421  mp_integer i = bvrep2integer(c.get_value(), bits, false);
422  return bv_utils.build_constant(i, bits);
423  }
424  }
425  else if(expr.id()==ID_plus)
426  {
427  // this has to be pointer plus integer
428 
429  const plus_exprt &plus_expr = to_plus_expr(expr);
430 
431  bvt bv;
432 
433  mp_integer size=0;
434  std::size_t count=0;
435 
436  forall_operands(it, plus_expr)
437  {
438  if(it->type().id()==ID_pointer)
439  {
440  count++;
441  bv=convert_bv(*it);
442  CHECK_RETURN(bv.size()==bits);
443 
444  typet pointer_base_type = to_pointer_type(it->type()).base_type();
445 
446  if(pointer_base_type.id() == ID_empty)
447  {
448  // This is a gcc extension.
449  // https://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Pointer-Arith.html
450  size = 1;
451  }
452  else
453  {
454  auto size_opt = pointer_offset_size(pointer_base_type, ns);
455  CHECK_RETURN(size_opt.has_value() && *size_opt >= 0);
456  size = *size_opt;
457  }
458  }
459  }
460 
461  INVARIANT(
462  count == 1,
463  "there should be exactly one pointer-type operand in a pointer-type sum");
464 
465  const std::size_t offset_bits = get_offset_width(type);
466  bvt sum = bv_utils.build_constant(0, offset_bits);
467 
468  forall_operands(it, plus_expr)
469  {
470  if(it->type().id()==ID_pointer)
471  continue;
472 
473  if(it->type().id()!=ID_unsignedbv &&
474  it->type().id()!=ID_signedbv)
475  {
476  return conversion_failed(plus_expr);
477  }
478 
480  it->type().id()==ID_signedbv?bv_utilst::representationt::SIGNED:
482 
483  bvt op=convert_bv(*it);
484  CHECK_RETURN(!op.empty());
485 
486  op = bv_utils.extension(op, offset_bits, rep);
487 
488  sum=bv_utils.add(sum, op);
489  }
490 
491  return offset_arithmetic(type, bv, size, sum);
492  }
493  else if(expr.id()==ID_minus)
494  {
495  // this is pointer-integer
496 
497  const minus_exprt &minus_expr = to_minus_expr(expr);
498 
499  INVARIANT(
500  minus_expr.lhs().type().id() == ID_pointer,
501  "first operand should be of pointer type");
502 
503  if(
504  minus_expr.rhs().type().id() != ID_unsignedbv &&
505  minus_expr.rhs().type().id() != ID_signedbv)
506  {
507  return conversion_failed(minus_expr);
508  }
509 
510  const unary_minus_exprt neg_op1(minus_expr.rhs());
511 
512  const bvt &bv = convert_bv(minus_expr.lhs());
513 
514  typet pointer_base_type =
515  to_pointer_type(minus_expr.lhs().type()).base_type();
516  mp_integer element_size;
517 
518  if(pointer_base_type.id() == ID_empty)
519  {
520  // This is a gcc extension.
521  // https://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Pointer-Arith.html
522  element_size = 1;
523  }
524  else
525  {
526  auto element_size_opt = pointer_offset_size(pointer_base_type, ns);
527  CHECK_RETURN(element_size_opt.has_value() && *element_size_opt > 0);
528  element_size = *element_size_opt;
529  }
530 
531  return offset_arithmetic(type, bv, element_size, neg_op1);
532  }
533  else if(expr.id()==ID_byte_extract_little_endian ||
534  expr.id()==ID_byte_extract_big_endian)
535  {
537  }
538  else if(
539  expr.id() == ID_byte_update_little_endian ||
540  expr.id() == ID_byte_update_big_endian)
541  {
543  }
544  else if(expr.id() == ID_field_address)
545  {
546  const auto &field_address_expr = to_field_address_expr(expr);
547  const typet &compound_type = ns.follow(field_address_expr.compound_type());
548 
549  // recursive call
550  auto bv = convert_bitvector(field_address_expr.base());
551 
552  if(compound_type.id() == ID_struct)
553  {
554  auto offset = member_offset(
555  to_struct_type(compound_type), field_address_expr.component_name(), ns);
556  CHECK_RETURN(offset.has_value());
557 
558  // add offset
559  bv = offset_arithmetic(field_address_expr.type(), bv, *offset);
560  }
561  else if(compound_type.id() == ID_union)
562  {
563  // nothing to do, all fields have offset 0
564  }
565  else
566  {
567  INVARIANT(false, "field address expressions operate on struct or union");
568  }
569 
570  return bv;
571  }
572  else if(expr.id() == ID_element_address)
573  {
574  const auto &element_address_expr = to_element_address_expr(expr);
575 
576  // recursive call
577  auto bv = convert_bitvector(element_address_expr.base());
578 
579  // get element size
580  auto size = pointer_offset_size(element_address_expr.element_type(), ns);
581  CHECK_RETURN(size.has_value() && *size >= 0);
582 
583  // add offset
584  bv = offset_arithmetic(
585  element_address_expr.type(), bv, *size, element_address_expr.index());
586 
587  return bv;
588  }
589 
590  return conversion_failed(expr);
591 }
592 
593 static bool is_pointer_subtraction(const exprt &expr)
594 {
595  if(expr.id() != ID_minus)
596  return false;
597 
598  const auto &minus_expr = to_minus_expr(expr);
599 
600  return minus_expr.lhs().type().id() == ID_pointer &&
601  minus_expr.rhs().type().id() == ID_pointer;
602 }
603 
605 {
606  if(expr.type().id()==ID_pointer)
607  return convert_pointer_type(expr);
608 
609  if(is_pointer_subtraction(expr))
610  {
611  std::size_t width=boolbv_width(expr.type());
612 
613  // pointer minus pointer is subtraction over the offset divided by element
614  // size, iff the pointers point to the same object
615  const auto &minus_expr = to_minus_expr(expr);
616 
617  // do the same-object-test via an expression as this may permit re-using
618  // already cached encodings of the equality test
619  const exprt same_object = ::same_object(minus_expr.lhs(), minus_expr.rhs());
620  const literalt same_object_lit = convert(same_object);
621 
622  // compute the object size (again, possibly using cached results)
623  const exprt object_size = ::object_size(minus_expr.lhs());
624  const bvt object_size_bv =
626 
627  bvt bv = prop.new_variables(width);
628 
629  if(!same_object_lit.is_false())
630  {
631  const pointer_typet &lhs_pt = to_pointer_type(minus_expr.lhs().type());
632  const bvt &lhs = convert_bv(minus_expr.lhs());
633  const bvt lhs_offset =
634  bv_utils.sign_extension(offset_literals(lhs, lhs_pt), width);
635 
636  const literalt lhs_in_bounds = prop.land(
637  !bv_utils.sign_bit(lhs_offset),
638  bv_utils.rel(
639  lhs_offset,
640  ID_le,
641  object_size_bv,
643 
644  const pointer_typet &rhs_pt = to_pointer_type(minus_expr.rhs().type());
645  const bvt &rhs = convert_bv(minus_expr.rhs());
646  const bvt rhs_offset =
647  bv_utils.sign_extension(offset_literals(rhs, rhs_pt), width);
648 
649  const literalt rhs_in_bounds = prop.land(
650  !bv_utils.sign_bit(rhs_offset),
651  bv_utils.rel(
652  rhs_offset,
653  ID_le,
654  object_size_bv,
656 
657  bvt difference = bv_utils.sub(lhs_offset, rhs_offset);
658 
659  // Support for void* is a gcc extension, with the size treated as 1 byte
660  // (no division required below).
661  // https://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Pointer-Arith.html
662  if(lhs_pt.base_type().id() != ID_empty)
663  {
664  auto element_size_opt = pointer_offset_size(lhs_pt.base_type(), ns);
665  CHECK_RETURN(element_size_opt.has_value() && *element_size_opt > 0);
666 
667  if(*element_size_opt != 1)
668  {
669  bvt element_size_bv =
670  bv_utils.build_constant(*element_size_opt, width);
671  difference = bv_utils.divider(
672  difference, element_size_bv, bv_utilst::representationt::SIGNED);
673  }
674  }
675 
677  prop.land(same_object_lit, prop.land(lhs_in_bounds, rhs_in_bounds)),
678  bv_utils.equal(difference, bv)));
679  }
680 
681  return bv;
682  }
683  else if(
684  expr.id() == ID_pointer_offset &&
685  to_pointer_offset_expr(expr).pointer().type().id() == ID_pointer)
686  {
687  std::size_t width=boolbv_width(expr.type());
688 
689  const exprt &pointer = to_pointer_offset_expr(expr).pointer();
690  const bvt &pointer_bv = convert_bv(pointer);
691 
692  bvt offset_bv =
693  offset_literals(pointer_bv, to_pointer_type(pointer.type()));
694 
695  // we do a sign extension to permit negative offsets
696  return bv_utils.sign_extension(offset_bv, width);
697  }
698  else if(
699  const auto object_size = expr_try_dynamic_cast<object_size_exprt>(expr))
700  {
701  // we postpone until we know the objects
702  std::size_t width = boolbv_width(object_size->type());
703 
704  postponed_list.emplace_back(
705  prop.new_variables(width),
706  convert_bv(object_size->pointer()),
707  *object_size);
708 
709  return postponed_list.back().bv;
710  }
711  else if(
712  expr.id() == ID_pointer_object &&
713  to_pointer_object_expr(expr).pointer().type().id() == ID_pointer)
714  {
715  std::size_t width=boolbv_width(expr.type());
716 
717  const exprt &pointer = to_pointer_object_expr(expr).pointer();
718  const bvt &pointer_bv = convert_bv(pointer);
719 
720  bvt object_bv =
721  object_literals(pointer_bv, to_pointer_type(pointer.type()));
722 
723  return bv_utils.zero_extension(object_bv, width);
724  }
725  else if(
726  expr.id() == ID_typecast &&
727  to_typecast_expr(expr).op().type().id() == ID_pointer)
728  {
729  // pointer to int
730  bvt op0 = convert_pointer_type(to_typecast_expr(expr).op());
731 
732  // squeeze it in!
733  std::size_t width=boolbv_width(expr.type());
734 
735  return bv_utils.zero_extension(op0, width);
736  }
737  else if(expr.id() == ID_object_address)
738  {
739  const auto &object_address_expr = to_object_address_expr(expr);
740  return add_addr(object_address_expr.object_expr());
741  }
742 
743  return SUB::convert_bitvector(expr);
744 }
745 
746 static std::string bits_to_string(const propt &prop, const bvt &bv)
747 {
748  std::string result;
749 
750  for(const auto &literal : bv)
751  {
752  char ch=0;
753 
754  // clang-format off
755  switch(prop.l_get(literal).get_value())
756  {
757  case tvt::tv_enumt::TV_FALSE: ch = '0'; break;
758  case tvt::tv_enumt::TV_TRUE: ch = '1'; break;
759  case tvt::tv_enumt::TV_UNKNOWN: ch = '0'; break;
760  }
761  // clang-format on
762 
763  result = ch + result;
764  }
765 
766  return result;
767 }
768 
770  const exprt &expr,
771  const bvt &bv,
772  std::size_t offset) const
773 {
774  const typet &type = expr.type();
775 
776  if(type.id() != ID_pointer)
777  return SUB::bv_get_rec(expr, bv, offset);
778 
779  const pointer_typet &pt = to_pointer_type(type);
780  const std::size_t bits = boolbv_width(pt);
781  bvt value_bv(bv.begin() + offset, bv.begin() + offset + bits);
782 
783  std::string value = bits_to_string(prop, value_bv);
784  std::string value_addr = bits_to_string(prop, object_literals(value_bv, pt));
785  std::string value_offset =
786  bits_to_string(prop, offset_literals(value_bv, pt));
787 
788  // we treat these like bit-vector constants, but with
789  // some additional annotation
790 
791  const irep_idt bvrep = make_bvrep(bits, [&value](std::size_t i) {
792  return value[value.size() - 1 - i] == '1';
793  });
794 
795  constant_exprt result(bvrep, type);
796 
797  pointer_logict::pointert pointer;
798  pointer.object =
799  numeric_cast_v<std::size_t>(binary2integer(value_addr, false));
800  pointer.offset=binary2integer(value_offset, true);
801 
803  bvrep, pointer_logic.pointer_expr(pointer, pt)};
804 }
805 
807  const
808 {
809  const std::size_t offset_bits = get_offset_width(type);
810  const std::size_t object_bits = get_object_width(type);
811 
812  bvt zero_offset(offset_bits, const_literal(false));
813  bvt object = bv_utils.build_constant(addr, object_bits);
814 
815  return object_offset_encoding(object, zero_offset);
816 }
817 
819  const pointer_typet &type,
820  const bvt &bv,
821  const mp_integer &x)
822 {
823  const std::size_t offset_bits = get_offset_width(type);
824 
825  return offset_arithmetic(
826  type, bv, 1, bv_utils.build_constant(x, offset_bits));
827 }
828 
830  const pointer_typet &type,
831  const bvt &bv,
832  const mp_integer &factor,
833  const exprt &index)
834 {
835  bvt bv_index=convert_bv(index);
836 
838  index.type().id()==ID_signedbv?bv_utilst::representationt::SIGNED:
840 
841  const std::size_t offset_bits = get_offset_width(type);
842  bv_index=bv_utils.extension(bv_index, offset_bits, rep);
843 
844  return offset_arithmetic(type, bv, factor, bv_index);
845 }
846 
848  const pointer_typet &type,
849  const bvt &bv,
850  const mp_integer &factor,
851  const bvt &index)
852 {
853  bvt bv_index;
854 
855  if(factor==1)
856  bv_index=index;
857  else
858  {
859  bvt bv_factor=bv_utils.build_constant(factor, index.size());
860  bv_index = bv_utils.signed_multiplier(index, bv_factor);
861  }
862 
863  const std::size_t offset_bits = get_offset_width(type);
864  bv_index = bv_utils.sign_extension(bv_index, offset_bits);
865 
866  bvt offset_bv = offset_literals(bv, type);
867 
868  bvt bv_tmp = bv_utils.add(offset_bv, bv_index);
869 
870  return object_offset_encoding(object_literals(bv, type), bv_tmp);
871 }
872 
874 {
875  const auto a = pointer_logic.add_object(expr);
876 
877  const pointer_typet type = pointer_type(expr.type());
878  const std::size_t object_bits = get_object_width(type);
879  const std::size_t max_objects=std::size_t(1)<<object_bits;
880 
881  if(a==max_objects)
882  throw analysis_exceptiont(
883  "too many addressed objects: maximum number of objects is set to 2^n=" +
884  std::to_string(max_objects) + " (with n=" + std::to_string(object_bits) +
885  "); " +
886  "use the `--object-bits n` option to increase the maximum number");
887 
888  return encode(a, type);
889 }
890 
892  const postponedt &postponed)
893 {
894  if(postponed.expr.id() == ID_is_dynamic_object)
895  {
896  const auto &type =
897  to_pointer_type(to_unary_expr(postponed.expr).op().type());
898  const auto &objects = pointer_logic.objects;
899  std::size_t number=0;
900 
901  for(auto it = objects.cbegin(); it != objects.cend(); ++it, ++number)
902  {
903  const exprt &expr=*it;
904 
905  bool is_dynamic=pointer_logic.is_dynamic_object(expr);
906 
907  // only compare object part
908  pointer_typet pt = pointer_type(expr.type());
909  bvt bv = object_literals(encode(number, pt), type);
910 
911  bvt saved_bv = object_literals(postponed.op, type);
912 
913  POSTCONDITION(bv.size()==saved_bv.size());
914  PRECONDITION(postponed.bv.size()==1);
915 
916  literalt l1=bv_utils.equal(bv, saved_bv);
917  literalt l2=postponed.bv.front();
918 
919  if(!is_dynamic)
920  l2=!l2;
921 
922  prop.l_set_to_true(prop.limplies(l1, l2));
923  }
924  }
925  else if(
926  const auto postponed_object_size =
927  expr_try_dynamic_cast<object_size_exprt>(postponed.expr))
928  {
929  const auto &type = to_pointer_type(postponed_object_size->pointer().type());
930  const auto &objects = pointer_logic.objects;
931  std::size_t number=0;
932 
933  for(auto it = objects.cbegin(); it != objects.cend(); ++it, ++number)
934  {
935  const exprt &expr=*it;
936 
937  if(expr.id() != ID_symbol && expr.id() != ID_string_constant)
938  continue;
939 
940  const auto size_expr = size_of_expr(expr.type(), ns);
941 
942  if(!size_expr.has_value())
943  continue;
944 
946  size_expr.value(), postponed_object_size->type());
947 
948  // only compare object part
949  pointer_typet pt = pointer_type(expr.type());
950  bvt bv = object_literals(encode(number, pt), type);
951 
952  bvt saved_bv = object_literals(postponed.op, type);
953 
954  bvt size_bv = convert_bv(object_size);
955 
956  POSTCONDITION(bv.size()==saved_bv.size());
957  PRECONDITION(postponed.bv.size()>=1);
958  PRECONDITION(size_bv.size() == postponed.bv.size());
959 
960  literalt l1=bv_utils.equal(bv, saved_bv);
961  if(l1.is_true())
962  {
963  for(std::size_t i = 0; i < postponed.bv.size(); ++i)
964  prop.set_equal(postponed.bv[i], size_bv[i]);
965  break;
966  }
967  else if(l1.is_false())
968  continue;
969 #define COMPACT_OBJECT_SIZE_EQ
970 #ifndef COMPACT_OBJECT_SIZE_EQ
971  literalt l2=bv_utils.equal(postponed.bv, size_bv);
972 
973  prop.l_set_to_true(prop.limplies(l1, l2));
974 #else
975  for(std::size_t i = 0; i < postponed.bv.size(); ++i)
976  {
977  prop.lcnf({!l1, !postponed.bv[i], size_bv[i]});
978  prop.lcnf({!l1, postponed.bv[i], !size_bv[i]});
979  }
980 #endif
981  }
982  }
983  else
984  UNREACHABLE;
985 }
986 
988 {
989  // post-processing arrays may yield further objects, do this first
991 
992  for(postponed_listt::const_iterator
993  it=postponed_list.begin();
994  it!=postponed_list.end();
995  it++)
996  do_postponed(*it);
997 
998  // Clear the list to avoid re-doing in case of incremental usage.
999  postponed_list.clear();
1000 }
to_element_address_expr
const element_address_exprt & to_element_address_expr(const exprt &expr)
Cast an exprt to an element_address_exprt.
Definition: pointer_expr.h:640
bv_pointerst::encode
bvt encode(const mp_integer &object, const pointer_typet &) const
Definition: bv_pointers.cpp:806
bv_endianness_mapt::build_big_endian
void build_big_endian(const typet &type) override
Definition: bv_pointers.cpp:59
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
boolbvt::bv_width
boolbv_widtht bv_width
Definition: boolbv.h:116
configt::bv_encodingt::object_bits
std::size_t object_bits
Definition: config.h:336
typecast_exprt::conditional_cast
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2025
to_unary_expr
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition: std_expr.h:361
bv_pointerst::finish_eager_conversion
void finish_eager_conversion() override
Definition: bv_pointers.cpp:987
boolbvt::map
boolbv_mapt map
Definition: boolbv.h:123
boolbvt::convert_member
virtual bvt convert_member(const member_exprt &expr)
Definition: boolbv_member.cpp:46
bv_endianness_mapt::bv_endianness_mapt
bv_endianness_mapt(const typet &type, bool little_endian, const namespacet &_ns, const boolbv_widtht &_boolbv_width)
Definition: bv_pointers.cpp:29
mp_integer
BigInt mp_integer
Definition: smt_terms.h:17
endianness_mapt::build
void build(const typet &type, bool little_endian)
Definition: endianness_map.cpp:30
bv_endianness_mapt::boolbv_width
const boolbv_widtht & boolbv_width
Definition: bv_pointers.cpp:40
binary_exprt::rhs
exprt & rhs()
Definition: std_expr.h:623
bv_pointerst::bv_pointerst
bv_pointerst(const namespacet &, propt &, message_handlert &, bool get_array_constraints=false)
Definition: bv_pointers.cpp:210
bv_pointerst::convert_bitvector
bvt convert_bitvector(const exprt &) override
Converts an expression into its gate-level representation and returns a vector of literals correspond...
Definition: bv_pointers.cpp:604
boolbvt::convert_byte_update
virtual bvt convert_byte_update(const byte_update_exprt &expr)
Definition: boolbv_byte_update.cpp:17
configt::bv_encoding
struct configt::bv_encodingt bv_encoding
bv_utilst::zero_extension
static bvt zero_extension(const bvt &bv, std::size_t new_size)
Definition: bv_utils.h:187
arith_tools.h
boolbvt::finish_eager_conversion
void finish_eager_conversion() override
Definition: boolbv.h:80
make_bvrep
irep_idt make_bvrep(const std::size_t width, const std::function< bool(std::size_t)> f)
construct a bit-vector representation from a functor
Definition: arith_tools.cpp:306
bv_pointerst::postponedt::op
bvt op
Definition: bv_pointers.h:77
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
propt::new_variables
virtual bvt new_variables(std::size_t width)
generates a bitvector of given width with new variables
Definition: prop.cpp:20
boolbvt::convert_bitvector
virtual bvt convert_bitvector(const exprt &expr)
Converts an expression into its gate-level representation and returns a vector of literals correspond...
Definition: boolbv.cpp:97
bv_pointerst::bv_get_rec
exprt bv_get_rec(const exprt &, const bvt &, std::size_t offset) const override
Definition: bv_pointers.cpp:769
bv_pointerst::object_offset_encoding
static bvt object_offset_encoding(const bvt &object, const bvt &offset)
Construct a pointer encoding from given encodings of object and offset.
Definition: bv_pointers.cpp:112
boolbvt::bv_get_rec
virtual exprt bv_get_rec(const exprt &expr, const bvt &bv, std::size_t offset) const
Definition: boolbv_get.cpp:52
CHECK_RETURN
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
typet
The type of an expression, extends irept.
Definition: type.h:28
bvt
std::vector< literalt > bvt
Definition: literal.h:201
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
bv_utilst::signed_multiplier
bvt signed_multiplier(const bvt &op0, const bvt &op1)
Definition: bv_utils.cpp:802
bv_endianness_mapt
Map bytes according to the configured endianness.
Definition: bv_pointers.cpp:26
bv_pointerst::postponed_list
postponed_listt postponed_list
Definition: bv_pointers.h:87
bv_pointerst::postponedt::expr
exprt expr
Definition: bv_pointers.h:78
if_exprt
The trinary if-then-else operator.
Definition: std_expr.h:2322
pointer_predicates.h
boolbv_mapt::get_literals
const bvt & get_literals(const irep_idt &identifier, const typet &type, std::size_t width)
Definition: boolbv_map.cpp:41
propt::set_equal
virtual void set_equal(literalt a, literalt b)
asserts a==b in the propositional formula
Definition: prop.cpp:12
bv_utilst::representationt::UNSIGNED
@ UNSIGNED
pointer_offset_exprt::pointer
exprt & pointer()
Definition: pointer_expr.h:897
bv_pointerst::object_literals
bvt object_literals(const bvt &bv, const pointer_typet &type) const
Given a pointer encoded in bv, extract the literals identifying the object that the pointer points to...
Definition: bv_pointers.cpp:92
plus_exprt
The plus expression Associativity is not specified.
Definition: std_expr.h:946
bv_pointerst::do_postponed
void do_postponed(const postponedt &postponed)
Definition: bv_pointers.cpp:891
propt::new_variable
virtual literalt new_variable()=0
boolbvt::convert_index
virtual bvt convert_index(const exprt &array, const mp_integer &index)
index operator with constant index
Definition: boolbv_index.cpp:284
exprt
Base class for all expressions.
Definition: expr.h:55
binary_exprt::lhs
exprt & lhs()
Definition: std_expr.h:613
bv_utilst::sign_extension
static bvt sign_extension(const bvt &bv, std::size_t new_size)
Definition: bv_utils.h:182
bv_pointerst::convert_address_of_rec
optionalt< bvt > convert_address_of_rec(const exprt &)
Definition: bv_pointers.cpp:220
propt::l_set_to_true
void l_set_to_true(literalt a)
Definition: prop.h:50
to_string
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
Definition: string_constraint.cpp:58
pointer_logict::get_invalid_object
const mp_integer & get_invalid_object() const
Definition: pointer_logic.h:62
namespace.h
bv_pointerst::endianness_map
endianness_mapt endianness_map(const typet &, bool little_endian) const override
Definition: bv_pointers.cpp:68
endianness_mapt::build_big_endian
virtual void build_big_endian(const typet &type)
Definition: endianness_map.cpp:52
propt::land
virtual literalt land(literalt a, literalt b)=0
bv_utilst::select
bvt select(literalt s, const bvt &a, const bvt &b)
If s is true, selects a otherwise selects b.
Definition: bv_utils.cpp:92
to_minus_expr
const minus_exprt & to_minus_expr(const exprt &expr)
Cast an exprt to a minus_exprt.
Definition: std_expr.h:1031
boolbv_widtht::get_width_opt
virtual optionalt< std::size_t > get_width_opt(const typet &type) const
Definition: boolbv_width.h:31
if_exprt::false_case
exprt & false_case()
Definition: std_expr.h:2360
bv_pointers.h
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
literalt::is_true
bool is_true() const
Definition: literal.h:156
to_pointer_object_expr
const pointer_object_exprt & to_pointer_object_expr(const exprt &expr)
Cast an exprt to a pointer_object_exprt.
Definition: pointer_expr.h:986
boolbvt::convert_byte_extract
virtual bvt convert_byte_extract(const byte_extract_exprt &expr)
Definition: boolbv_byte_extract.cpp:35
tvt::tv_enumt::TV_TRUE
@ TV_TRUE
bv_utilst::add
bvt add(const bvt &op0, const bvt &op1)
Definition: bv_utils.h:66
byte_operators.h
Expression classes for byte-level operators.
bv_pointerst::add_addr
virtual bvt add_addr(const exprt &)
Definition: bv_pointers.cpp:873
endianness_mapt::map
std::vector< size_t > map
Definition: endianness_map.h:66
propt::limplies
virtual literalt limplies(literalt a, literalt b)=0
to_object_address_expr
const object_address_exprt & to_object_address_expr(const exprt &expr)
Cast an exprt to an object_address_exprt.
Definition: pointer_expr.h:474
boolbvt::boolbv_width
virtual std::size_t boolbv_width(const typet &type) const
Definition: boolbv.h:102
member_exprt::compound
const exprt & compound() const
Definition: std_expr.h:2843
boolbvt::convert_bv
virtual const bvt & convert_bv(const exprt &expr, const optionalt< std::size_t > expected_width={})
Convert expression to vector of literalts, using an internal cache to speed up conversion if availabl...
Definition: boolbv.cpp:39
bv_utilst::representationt::SIGNED
@ SIGNED
forall_operands
#define forall_operands(it, expr)
Definition: expr.h:20
to_byte_update_expr
const byte_update_exprt & to_byte_update_expr(const exprt &expr)
Definition: byte_operators.h:117
pointer_logict::pointert::offset
mp_integer offset
Definition: pointer_logic.h:30
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
bv_utilst::representationt
representationt
Definition: bv_utils.h:28
symbol_exprt::get_identifier
const irep_idt & get_identifier() const
Definition: std_expr.h:142
arrayst::ns
const namespacet & ns
Definition: arrays.h:56
boolbvt::convert_if
virtual bvt convert_if(const if_exprt &expr)
Definition: boolbv_if.cpp:12
to_plus_expr
const plus_exprt & to_plus_expr(const exprt &expr)
Cast an exprt to a plus_exprt.
Definition: std_expr.h:986
pointer_expr.h
literalt::is_false
bool is_false() const
Definition: literal.h:161
const_literal
literalt const_literal(bool value)
Definition: literal.h:188
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
bv_pointerst::pointer_logic
pointer_logict pointer_logic
Definition: bv_pointers.h:33
pointer_type
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:253
unary_minus_exprt
The unary minus expression.
Definition: std_expr.h:422
index_exprt::array
exprt & array()
Definition: std_expr.h:1440
to_symbol_expr
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:222
object_size
exprt object_size(const exprt &pointer)
Definition: pointer_predicates.cpp:33
irept::id
const irep_idt & id() const
Definition: irep.h:396
message_handlert
Definition: message.h:27
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
unary_exprt::op
const exprt & op() const
Definition: std_expr.h:326
annotated_pointer_constant_exprt
Pointer-typed bitvector constant annotated with the pointer expression that the bitvector is the nume...
Definition: pointer_expr.h:817
bv_pointerst::offset_arithmetic
bvt offset_arithmetic(const pointer_typet &, const bvt &, const mp_integer &)
Definition: bv_pointers.cpp:818
optionalt
nonstd::optional< T > optionalt
Definition: optional.h:35
prop_conv_solvert::convert
literalt convert(const exprt &expr) override
Convert a Boolean expression and return the corresponding literal.
Definition: prop_conv_solver.cpp:156
pointer_logict::objects
numberingt< exprt, irep_hash > objects
Definition: pointer_logic.h:26
minus_exprt
Binary minus.
Definition: std_expr.h:1005
pointer_logict::pointert::object
mp_integer object
Definition: pointer_logic.h:30
config
configt config
Definition: config.cpp:25
bv_pointerst::get_address_width
std::size_t get_address_width(const pointer_typet &) const
Definition: bv_pointers.cpp:87
bitvector_typet::get_width
std::size_t get_width() const
Definition: std_types.h:876
member_exprt
Extract member of struct or union.
Definition: std_expr.h:2793
boolbv_widtht
Definition: boolbv_width.h:18
expr_util.h
Deprecated expression utility functions.
bvrep2integer
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
Definition: arith_tools.cpp:402
bv_pointerst::get_object_width
std::size_t get_object_width(const pointer_typet &) const
Definition: bv_pointers.cpp:73
bv_utilst::build_constant
static bvt build_constant(const mp_integer &i, std::size_t width)
Definition: bv_utils.cpp:11
propt::lequal
virtual literalt lequal(literalt a, literalt b)=0
bv_utilst::rel
literalt rel(const bvt &bv0, irep_idt id, const bvt &bv1, representationt rep)
Definition: bv_utils.cpp:1337
POSTCONDITION
#define POSTCONDITION(CONDITION)
Definition: invariant.h:479
propt
TO_BE_DOCUMENTED.
Definition: prop.h:22
bv_endianness_mapt::build_little_endian
void build_little_endian(const typet &type) override
Definition: bv_pointers.cpp:46
pointer_offset_size
optionalt< mp_integer > pointer_offset_size(const typet &type, const namespacet &ns)
Compute the size of a type in bytes, rounding up to full bytes.
Definition: pointer_offset_size.cpp:90
pointer_logict::is_dynamic_object
bool is_dynamic_object(const exprt &expr) const
Definition: pointer_logic.cpp:25
if_exprt::true_case
exprt & true_case()
Definition: std_expr.h:2350
propt::l_get
virtual tvt l_get(literalt a) const =0
bv_pointerst::postponedt
Definition: bv_pointers.h:75
namespace_baset::follow
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition: namespace.cpp:49
boolbvt::bv_utils
bv_utilst bv_utils
Definition: boolbv.h:117
bv_utilst::sign_bit
static literalt sign_bit(const bvt &op)
Definition: bv_utils.h:138
to_typecast_expr
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2051
bv_utilst::extension
static bvt extension(const bvt &bv, std::size_t new_size, representationt rep)
Definition: bv_utils.cpp:105
binary2integer
const mp_integer binary2integer(const std::string &n, bool is_signed)
convert binary string representation to mp_integer
Definition: mp_arith.cpp:117
if_exprt::cond
exprt & cond()
Definition: std_expr.h:2340
bits_to_string
static std::string bits_to_string(const propt &prop, const bvt &bv)
Definition: bv_pointers.cpp:746
to_field_address_expr
const field_address_exprt & to_field_address_expr(const exprt &expr)
Cast an exprt to an field_address_exprt.
Definition: pointer_expr.h:558
pointer_typet::base_type
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
bv_pointerst::convert_rest
literalt convert_rest(const exprt &) override
Definition: bv_pointers.cpp:122
literalt
Definition: literal.h:25
bv_pointerst::get_offset_width
std::size_t get_offset_width(const pointer_typet &) const
Definition: bv_pointers.cpp:79
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
same_object
exprt same_object(const exprt &p1, const exprt &p2)
Definition: pointer_predicates.cpp:28
bv_utilst::divider
bvt divider(const bvt &op0, const bvt &op1, representationt rep)
Definition: bv_utils.h:89
endianness_mapt
Maps a big-endian offset to a little-endian offset.
Definition: endianness_map.h:30
boolbvt
Definition: boolbv.h:46
config.h
to_pointer_offset_expr
const pointer_offset_exprt & to_pointer_offset_expr(const exprt &expr)
Cast an exprt to a pointer_offset_exprt.
Definition: pointer_expr.h:928
tvt::tv_enumt::TV_UNKNOWN
@ TV_UNKNOWN
size_of_expr
optionalt< exprt > size_of_expr(const typet &type, const namespacet &ns)
Definition: pointer_offset_size.cpp:280
to_member_expr
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2886
boolbvt::conversion_failed
bvt conversion_failed(const exprt &expr)
Print that the expression of x has failed conversion, then return a vector of x's width.
Definition: boolbv.cpp:83
pointer_object_exprt::pointer
exprt & pointer()
Definition: pointer_expr.h:955
member_exprt::get_component_name
irep_idt get_component_name() const
Definition: std_expr.h:2816
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
bv_pointerst::offset_literals
bvt offset_literals(const bvt &bv, const pointer_typet &type) const
Given a pointer encoded in bv, extract the literals representing the offset into an object that the p...
Definition: bv_pointers.cpp:103
exprt::operands
operandst & operands()
Definition: expr.h:94
bv_pointerst::convert_pointer_type
virtual bvt convert_pointer_type(const exprt &)
Definition: bv_pointers.cpp:353
pointer_logict::add_object
mp_integer add_object(const exprt &expr)
Definition: pointer_logic.cpp:44
is_null_pointer
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:315
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
bv_utilst::equal
literalt equal(const bvt &op0, const bvt &op1)
Bit-blasting ID_equal and use in other encodings.
Definition: bv_utils.cpp:1165
typecast_exprt
Semantic type conversion.
Definition: std_expr.h:2016
pointer_typet
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
Definition: pointer_expr.h:23
tvt::get_value
tv_enumt get_value() const
Definition: threeval.h:40
boolbvt::convert_rest
literalt convert_rest(const exprt &expr) override
Definition: boolbv.cpp:319
constant_exprt
A constant literal expression.
Definition: std_expr.h:2941
is_pointer_subtraction
static bool is_pointer_subtraction(const exprt &expr)
Definition: bv_pointers.cpp:593
tvt::tv_enumt::TV_FALSE
@ TV_FALSE
constant_exprt::get_value
const irep_idt & get_value() const
Definition: std_expr.h:2950
member_offset
optionalt< mp_integer > member_offset(const struct_typet &type, const irep_idt &member, const namespacet &ns)
Definition: pointer_offset_size.cpp:24
c_types.h
propt::lcnf
void lcnf(literalt l0, literalt l1)
Definition: prop.h:56
pointer_logict::pointert
Definition: pointer_logic.h:28
can_cast_type< bitvector_typet >
bool can_cast_type< bitvector_typet >(const typet &type)
Check whether a reference to a typet is a bitvector_typet.
Definition: std_types.h:899
validation_modet::INVARIANT
@ INVARIANT
prop_conv_solvert::prop
propt & prop
Definition: prop_conv_solver.h:130
bv_pointerst::postponedt::bv
bvt bv
Definition: bv_pointers.h:77
pointer_logict::get_null_object
const mp_integer & get_null_object() const
Definition: pointer_logic.h:56
bv_utilst::sub
bvt sub(const bvt &op0, const bvt &op1)
Definition: bv_utils.h:67
pointer_logict::pointer_expr
exprt pointer_expr(const pointert &pointer, const pointer_typet &type) const
Convert an (object,offset) pair to an expression.
Definition: pointer_logic.cpp:67
analysis_exceptiont
Thrown when an unexpected error occurs during the analysis (e.g., when the SAT solver returns an erro...
Definition: exception_utils.h:153
to_constant_expr
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition: std_expr.h:2992